Skip to content

Conversation

@BoDonkey
Copy link
Contributor

@BoDonkey BoDonkey commented Dec 9, 2025

Summary

Summarize the changes briefly, including which issue/ticket this resolves. If it closes an existing Github issue, include "Closes #[issue number]"
This PR moves the approved JSON-LD changes from the old repo to the new repo with no additional changes.

What are the specific steps to test this change?

For example:

  1. Run the website and log in as an admin
  2. Open a piece manager modal and select several pieces
  3. Click the "Archive" button on the top left of the manager and confirm that it should proceed
  4. Check that all pieces have been archived properly

What kind of change does this PR introduce?

(Check at least one)

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Build-related changes
  • Other

Make sure the PR fulfills these requirements:

  • It includes a) the existing issue ID being resolved, b) a convincing reason for adding this feature, or c) a clear description of the bug it resolves
  • The changelog is updated
  • Related documentation has been updated
  • Related tests have been updated

If adding a new feature without an already open issue, it's best to open a feature request issue first and wait for approval before working on it.

Other information:

@BoDonkey BoDonkey requested a review from boutell December 9, 2025 15:53
// Verify social profiles
assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
assert.strictEqual(orgSchema.sameAs.length, 2);
assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

'
https://twitter.com/examplecorp
' can be anywhere in the URL, and arbitrary hosts may come before or after it.

Copilot Autofix

AI about 1 month ago

To fix the problem, the test should check that the actual value(s) in orgSchema.sameAs array match the required host(s), not simply that the specified URL appears as a substring.
Specifically, replace orgSchema.sameAs.includes('https://twitter.com/examplecorp') with a check that at least one value in the array, when parsed as a URL, has a host that matches 'twitter.com' and a pathname that matches the expected path ('/examplecorp'). Use Node's built-in url module (or the global URL class, if available) to parse each entry before comparison.
Edit only the relevant assertion on line 118, using Array.some together with URL parsing.
Since the test uses NodeJS, we can use the global URL class without additional imports.

Suggested changeset 1
packages/seo/test/functional-tests.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/seo/test/functional-tests.js b/packages/seo/test/functional-tests.js
--- a/packages/seo/test/functional-tests.js
+++ b/packages/seo/test/functional-tests.js
@@ -115,7 +115,17 @@
       // Verify social profiles
       assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
       assert.strictEqual(orgSchema.sameAs.length, 2);
-      assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));
+      assert(
+        orgSchema.sameAs.some(u => {
+          try {
+            const { host, pathname } = new URL(u);
+            return host === 'twitter.com' && pathname === '/examplecorp';
+          } catch (e) {
+            return false;
+          }
+        }),
+        'Organization should have a Twitter "sameAs" with correct host and pathname'
+      );
       assert(orgSchema.sameAs.includes('https://linkedin.com/company/example'));
     });
 
EOF
@@ -115,7 +115,17 @@
// Verify social profiles
assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
assert.strictEqual(orgSchema.sameAs.length, 2);
assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));
assert(
orgSchema.sameAs.some(u => {
try {
const { host, pathname } = new URL(u);
return host === 'twitter.com' && pathname === '/examplecorp';
} catch (e) {
return false;
}
}),
'Organization should have a Twitter "sameAs" with correct host and pathname'
);
assert(orgSchema.sameAs.includes('https://linkedin.com/company/example'));
});

Copilot is powered by AI and may make mistakes. Always verify output.
assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
assert.strictEqual(orgSchema.sameAs.length, 2);
assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));
assert(orgSchema.sameAs.includes('https://linkedin.com/company/example'));

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

'
https://linkedin.com/company/example
' can be anywhere in the URL, and arbitrary hosts may come before or after it.

Copilot Autofix

AI about 1 month ago

The best way to fix this problem is to avoid relying on substring (includes) checks and instead use exact string matching for URLs within the sameAs array. This involves replacing the substring check (orgSchema.sameAs.includes(...)) with a check that at least one string in the array is exactly equal to the expected URL. In JavaScript, this can be done with the Array.prototype.some() method, for example: orgSchema.sameAs.some(url => url === 'https://linkedin.com/company/example'). This ensures that only the exact expected URL passes the check, eliminating the risk of dangerous substrings. The required change is localized to line 119 in the test file, with no imports or additional definitions required.

Suggested changeset 1
packages/seo/test/functional-tests.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/seo/test/functional-tests.js b/packages/seo/test/functional-tests.js
--- a/packages/seo/test/functional-tests.js
+++ b/packages/seo/test/functional-tests.js
@@ -116,7 +116,7 @@
       assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
       assert.strictEqual(orgSchema.sameAs.length, 2);
       assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));
-      assert(orgSchema.sameAs.includes('https://linkedin.com/company/example'));
+      assert(orgSchema.sameAs.some(url => url === 'https://linkedin.com/company/example'));
     });
 
     it('should render homepage with minimal configuration', async function () {
EOF
@@ -116,7 +116,7 @@
assert(Array.isArray(orgSchema.sameAs), 'Organization should have sameAs array');
assert.strictEqual(orgSchema.sameAs.length, 2);
assert(orgSchema.sameAs.includes('https://twitter.com/examplecorp'));
assert(orgSchema.sameAs.includes('https://linkedin.com/company/example'));
assert(orgSchema.sameAs.some(url => url === 'https://linkedin.com/company/example'));
});

it('should render homepage with minimal configuration', async function () {
Copilot is powered by AI and may make mistakes. Always verify output.
llmsTxt.includes('A test site demonstrating llms.txt'),
'Should include site description'
);
assert(llmsTxt.includes('https://example.com'), 'Should include base URL');

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

'
https://example.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.

Copilot Autofix

AI about 1 month ago

To fix the problem, we should avoid substring matching when verifying that a particular canonical URL appears in the llms.txt content in a security-sensitive or correctness-sensitive way. Instead, we should parse the output: extract lines that contain URLs (e.g. by matching lines containing https://), and properly parse the URLs using Node's url or URL class to confirm that 'example.com' is indeed the host of a listed URL. For this test, the optimal fix is to look for a line/lines in llms.txt containing a URL, extract the URL using a regex, and parse it to check that the host is example.com. All required code edits should be limited to the single test block containing line 463. An extra import is not strictly required, as Node.js has a built-in URL class.

Suggested changeset 1
packages/seo/test/functional-tests.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/seo/test/functional-tests.js b/packages/seo/test/functional-tests.js
--- a/packages/seo/test/functional-tests.js
+++ b/packages/seo/test/functional-tests.js
@@ -460,7 +460,16 @@
         llmsTxt.includes('A test site demonstrating llms.txt'),
         'Should include site description'
       );
-      assert(llmsTxt.includes('https://example.com'), 'Should include base URL');
+      // Look for a line with a URL, extract it, and check host
+      const urlMatches = llmsTxt.match(/https?:\/\/[^\s)]+/g) || [];
+      const hasExampleCom = urlMatches.some(u => {
+        try {
+          return (new URL(u)).hostname === 'example.com';
+        } catch (e) {
+          return false;
+        }
+      });
+      assert(hasExampleCom, 'Should include base URL with host example.com');
       assert(
         llmsTxt.includes('## AI Training Policy') ||
         llmsTxt.includes('AI Training'),
EOF
@@ -460,7 +460,16 @@
llmsTxt.includes('A test site demonstrating llms.txt'),
'Should include site description'
);
assert(llmsTxt.includes('https://example.com'), 'Should include base URL');
// Look for a line with a URL, extract it, and check host
const urlMatches = llmsTxt.match(/https?:\/\/[^\s)]+/g) || [];
const hasExampleCom = urlMatches.some(u => {
try {
return (new URL(u)).hostname === 'example.com';
} catch (e) {
return false;
}
});
assert(hasExampleCom, 'Should include base URL with host example.com');
assert(
llmsTxt.includes('## AI Training Policy') ||
llmsTxt.includes('AI Training'),
Copilot is powered by AI and may make mistakes. Always verify output.
ValJed
ValJed previously requested changes Dec 9, 2025
Copy link
Contributor

@ValJed ValJed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are too many unwanted changes in the package.json

"url": "git+https://github.com/apostrophecms/seo.git"
},
"homepage": "https://github.com/apostrophecms/apostrophe/tree/main/packages/seo",
"homepage": "https://github.com/apostrophecms/seo#readme",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should reference inside the monorepo since the seo module will die.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed, along with the "repository"

"lodash": "^4.17.21"
},
"devDependencies": {
"eslint": "^9.39.1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should keep eslint dep

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how that got removed. Added back.

"@apostrophecms/blog": "^1.0.6",
"@apostrophecms/seo": "file:.",
"apostrophe": "^4.24.0",
"eslint-config-apostrophe": "^5.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    "eslint-config-apostrophe": "workspace:^",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

"eslint-config-apostrophe": "workspace:*"
"@apostrophecms/blog": "^1.0.6",
"@apostrophecms/seo": "file:.",
"apostrophe": "^4.24.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    "apostrophe": "workspace:^",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed.

"eslint": "^9.39.1",
"eslint-config-apostrophe": "workspace:*"
"@apostrophecms/blog": "^1.0.6",
"@apostrophecms/seo": "file:.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for the functional tests

"devDependencies": {
"eslint": "^9.39.1",
"eslint-config-apostrophe": "workspace:*"
"@apostrophecms/blog": "^1.0.6",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    "@apostrophecms/blog": "workspace:^",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@BoDonkey BoDonkey requested a review from ValJed December 9, 2025 20:17
Copy link
Member

@boutell boutell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I must admit there's too much here to go line by line.

boutell
boutell previously approved these changes Dec 12, 2025
Copy link
Member

@boutell boutell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK it sounds like this is what I reviewed before, just migrating.

boutell
boutell previously approved these changes Dec 17, 2025
@BoDonkey BoDonkey requested a review from boutell January 2, 2026 19:07
@@ -0,0 +1,11 @@
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should run pnpm changeset in the repo root, not in individual package folders. Note the existing root .changeset folder. The individual changeset files know which package they impact.

boutell@Mac:~/apostrophecms/apostrophe$ ls .changeset/
config.json		modern-radios-attack.md	nice-peas-care.md	README.md		soft-laws-doubt.md
boutell@Mac:~/apostrophecms/apostrophe$ ff changeset
./.changeset/modern-radios-attack.md
./.changeset/config.json
./.changeset/nice-peas-care.md
./.changeset/README.md
./.changeset/soft-laws-doubt.md

@BoDonkey BoDonkey requested a review from boutell January 5, 2026 19:39
boutell
boutell previously approved these changes Jan 8, 2026
@boutell boutell self-requested a review January 8, 2026 15:36
@BoDonkey BoDonkey removed the request for review from ValJed January 8, 2026 15:42
@BoDonkey BoDonkey dismissed ValJed’s stale review January 8, 2026 15:43

Left company

@BoDonkey BoDonkey merged commit 9cfd745 into main Jan 8, 2026
13 of 14 checks passed
@BoDonkey BoDonkey deleted the seo-json-ld-update branch January 8, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants