fix(patches): silence false-positive warnings for beta.41 native features
Four patch scripts were warning when they couldn't find their target snippets in @indiekit/endpoint-posts beta.41, because beta.41 already ships those features natively: - patch-endpoint-posts-ai-cleanup: beta.41 form.js has native AI field cleanup — detect via "ai-text-level" presence and skip silently - patch-endpoint-posts-search-tags: beta.41 posts.js/posts.njk have native filter/sort/search — detect via buildFilterQuery / posts-filter-row - patch-endpoint-posts-uid-lookup: beta.41 utils.js uses direct MongoDB queries (getPostProperties) — skip silently - patch-preset-eleventy-ai-frontmatter: add v5 block matching the new upstream structure (mpUrl + URL pathname normalization) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,10 @@ for (const filePath of candidates) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!source.includes(oldSnippet)) {
|
if (!source.includes(oldSnippet)) {
|
||||||
|
// Beta.41+ has native AI field cleanup — skip silently
|
||||||
|
if (source.includes('"ai-text-level"') && source.includes('"ai-code-level"')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
console.warn(
|
console.warn(
|
||||||
`[postinstall] Skipping endpoint-posts AI cleanup patch for ${filePath}: upstream format changed`,
|
`[postinstall] Skipping endpoint-posts AI cleanup patch for ${filePath}: upstream format changed`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -232,6 +232,11 @@ for (const filePath of controllerCandidates) {
|
|||||||
[oldRender, newRender],
|
[oldRender, newRender],
|
||||||
]) {
|
]) {
|
||||||
if (!source.includes(oldSnip)) {
|
if (!source.includes(oldSnip)) {
|
||||||
|
// Beta.41+ has native filter/search/sort built in — skip silently
|
||||||
|
if (source.includes("buildFilterQuery") || source.includes("filters.postType")) {
|
||||||
|
changed = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
console.warn(
|
console.warn(
|
||||||
`[postinstall] posts search-tags: snippet not found in ${filePath}, skipping`,
|
`[postinstall] posts search-tags: snippet not found in ${filePath}, skipping`,
|
||||||
);
|
);
|
||||||
@@ -259,6 +264,10 @@ for (const filePath of viewCandidates) {
|
|||||||
if (source.includes(viewMarker)) continue;
|
if (source.includes(viewMarker)) continue;
|
||||||
|
|
||||||
if (!source.includes(oldView)) {
|
if (!source.includes(oldView)) {
|
||||||
|
// Beta.41+ has native filter/sort UI built in — skip silently
|
||||||
|
if (source.includes("posts-filter-row") || source.includes("posts.filter.type")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
console.warn(
|
console.warn(
|
||||||
`[postinstall] posts search-tags: view not found in ${filePath}, skipping`,
|
`[postinstall] posts search-tags: view not found in ${filePath}, skipping`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -90,6 +90,10 @@ for (const spec of patchSpecs) {
|
|||||||
|
|
||||||
if (source.includes(spec.marker)) continue;
|
if (source.includes(spec.marker)) continue;
|
||||||
if (!source.includes(spec.oldSnippet)) {
|
if (!source.includes(spec.oldSnippet)) {
|
||||||
|
// Beta.41+ uses direct MongoDB queries — uid lookup is native, skip silently
|
||||||
|
if (source.includes("getPostProperties") || source.includes("getPosts")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
console.log(`[postinstall] ${spec.name}: snippet not found in ${filePath}`);
|
console.log(`[postinstall] ${spec.name}: snippet not found in ${filePath}`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -365,6 +365,159 @@ const v4Block = [
|
|||||||
"};",
|
"};",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
|
|
||||||
|
// v5: upstream added mpUrl storage + URL normalization (pathname extraction).
|
||||||
|
// Matches the new block structure added after v4.
|
||||||
|
const v5UpstreamBlock = [
|
||||||
|
" // Store the Micropub URL for frontend edit links before deleting it",
|
||||||
|
" if (properties.url) {",
|
||||||
|
" properties.mpUrl = properties.url;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" // Convert Indiekit URL to Eleventy permalink so pages generate",
|
||||||
|
" // at the canonical URL (e.g., /notes/2026/02/22/slug/) instead of",
|
||||||
|
" // the file-path-based URL (e.g., /content/notes/2026-02-22-slug/).",
|
||||||
|
" if (properties.url) {",
|
||||||
|
" let url = properties.url;",
|
||||||
|
" if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {",
|
||||||
|
" try {",
|
||||||
|
" url = new URL(url).pathname;",
|
||||||
|
" } catch {",
|
||||||
|
" // If URL parsing fails, use as-is",
|
||||||
|
" }",
|
||||||
|
" }",
|
||||||
|
" properties.permalink = url.endsWith(\"/\") ? url : `${url}/`;",
|
||||||
|
" }",
|
||||||
|
" delete properties.url;",
|
||||||
|
"",
|
||||||
|
" const frontMatter = YAML.stringify(properties, { lineWidth: 0 });",
|
||||||
|
" return `---\\n${frontMatter}---\\n`;",
|
||||||
|
"};",
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
const v5PatchedBlock = [
|
||||||
|
" // Store the Micropub URL for frontend edit links before deleting it",
|
||||||
|
" if (properties.url) {",
|
||||||
|
" properties.mpUrl = properties.url;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" // Convert Indiekit URL to Eleventy permalink so pages generate",
|
||||||
|
" // at the canonical URL (e.g., /notes/2026/02/22/slug/) instead of",
|
||||||
|
" // the file-path-based URL (e.g., /content/notes/2026-02-22-slug/).",
|
||||||
|
" if (properties.url) {",
|
||||||
|
" let url = properties.url;",
|
||||||
|
" if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {",
|
||||||
|
" try {",
|
||||||
|
" url = new URL(url).pathname;",
|
||||||
|
" } catch {",
|
||||||
|
" // If URL parsing fails, use as-is",
|
||||||
|
" }",
|
||||||
|
" }",
|
||||||
|
" properties.permalink = url.endsWith(\"/\") ? url : `${url}/`;",
|
||||||
|
" }",
|
||||||
|
" delete properties.url;",
|
||||||
|
"",
|
||||||
|
" // Normalize and sanitize AI disclosure metadata for articles and notes only.",
|
||||||
|
" const aiSource =",
|
||||||
|
" properties.ai && typeof properties.ai === \"object\" && !Array.isArray(properties.ai)",
|
||||||
|
" ? properties.ai",
|
||||||
|
" : {};",
|
||||||
|
"",
|
||||||
|
" const normaliseString = (value) => {",
|
||||||
|
" if (value === undefined || value === null) {",
|
||||||
|
" return undefined;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" const text = String(value).trim();",
|
||||||
|
" return text === \"\" ? undefined : text;",
|
||||||
|
" };",
|
||||||
|
"",
|
||||||
|
" const normaliseLevel = (value, allowedValues, fallback = \"0\") => {",
|
||||||
|
" const candidate = normaliseString(value);",
|
||||||
|
"",
|
||||||
|
" if (!candidate) {",
|
||||||
|
" return fallback;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" return allowedValues.includes(candidate) ? candidate : fallback;",
|
||||||
|
" };",
|
||||||
|
"",
|
||||||
|
" const aiTextLevelRaw =",
|
||||||
|
" aiSource.textLevel ??",
|
||||||
|
" aiSource.aiTextLevel ??",
|
||||||
|
" properties.aiTextLevel ??",
|
||||||
|
" properties[\"ai-text-level\"] ??",
|
||||||
|
" \"0\";",
|
||||||
|
"",
|
||||||
|
" const aiCodeLevelRaw =",
|
||||||
|
" aiSource.codeLevel ??",
|
||||||
|
" aiSource.aiCodeLevel ??",
|
||||||
|
" properties.aiCodeLevel ??",
|
||||||
|
" properties[\"ai-code-level\"] ??",
|
||||||
|
" \"0\";",
|
||||||
|
"",
|
||||||
|
" const aiTextLevel = normaliseLevel(aiTextLevelRaw, [\"0\", \"1\", \"2\", \"3\"]);",
|
||||||
|
" // Legacy value \"3\" is folded into \"2\" for code-level taxonomy compatibility.",
|
||||||
|
" const aiCodeLevel = normaliseLevel(",
|
||||||
|
" aiCodeLevelRaw === \"3\" ? \"2\" : aiCodeLevelRaw,",
|
||||||
|
" [\"0\", \"1\", \"2\"],",
|
||||||
|
" );",
|
||||||
|
"",
|
||||||
|
" const aiTools = normaliseString(",
|
||||||
|
" aiSource.aiTools ?? aiSource.tools ?? properties.aiTools ?? properties[\"ai-tools\"],",
|
||||||
|
" );",
|
||||||
|
"",
|
||||||
|
" const aiDescription = normaliseString(",
|
||||||
|
" aiSource.aiDescription ??",
|
||||||
|
" aiSource.description ??",
|
||||||
|
" properties.aiDescription ??",
|
||||||
|
" properties[\"ai-description\"],",
|
||||||
|
" );",
|
||||||
|
"",
|
||||||
|
" delete properties.ai;",
|
||||||
|
" delete properties.aiTextLevel;",
|
||||||
|
" delete properties.aiCodeLevel;",
|
||||||
|
" delete properties.aiTools;",
|
||||||
|
" delete properties.aiDescription;",
|
||||||
|
" delete properties[\"ai-text-level\"];",
|
||||||
|
" delete properties[\"ai-code-level\"];",
|
||||||
|
" delete properties[\"ai-tools\"];",
|
||||||
|
" delete properties[\"ai-description\"];",
|
||||||
|
"",
|
||||||
|
" // Indiekit removes post-type before calling postTemplate; fall back to permalink-based detection.",
|
||||||
|
" const postType = String(",
|
||||||
|
" properties.postType ?? properties[\"post-type\"] ?? properties.type ?? \"\",",
|
||||||
|
" ).toLowerCase();",
|
||||||
|
" const permalink = String(properties.permalink ?? \"\");",
|
||||||
|
" const supportsAiDisclosure =",
|
||||||
|
" postType === \"article\" || postType === \"note\" ||",
|
||||||
|
" /\\/articles(?:\\/|$)/.test(permalink) || /\\/notes(?:\\/|$)/.test(permalink);",
|
||||||
|
"",
|
||||||
|
" const frontMatter = YAML.stringify(properties, { lineWidth: 0 });",
|
||||||
|
"",
|
||||||
|
" if (!supportsAiDisclosure) {",
|
||||||
|
" return `---\\n${frontMatter}---\\n`;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" let aiFrontMatter = `ai:\\n textLevel: \\\"${aiTextLevel}\\\"\\n codeLevel: \\\"${aiCodeLevel}\\\"\\n # aiTools: \\\"Claude, ChatGPT, Copilot\\\"\\n # aiDescription: \\\"Optional disclosure about how AI was used\\\"\\n`;",
|
||||||
|
"",
|
||||||
|
" if (aiTools) {",
|
||||||
|
" aiFrontMatter = aiFrontMatter.replace(",
|
||||||
|
" ' # aiTools: \\\"Claude, ChatGPT, Copilot\\\"\\n',",
|
||||||
|
" ` aiTools: ${JSON.stringify(aiTools)}\\n`,",
|
||||||
|
" );",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" if (aiDescription) {",
|
||||||
|
" aiFrontMatter = aiFrontMatter.replace(",
|
||||||
|
" ' # aiDescription: \\\"Optional disclosure about how AI was used\\\"\\n',",
|
||||||
|
" ` aiDescription: ${JSON.stringify(aiDescription)}\\n`,",
|
||||||
|
" );",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" return `---\\n${frontMatter}${aiFrontMatter}---\\n`;",
|
||||||
|
"};",
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
async function exists(filePath) {
|
async function exists(filePath) {
|
||||||
try {
|
try {
|
||||||
await access(filePath);
|
await access(filePath);
|
||||||
@@ -392,7 +545,9 @@ for (const filePath of candidates) {
|
|||||||
|
|
||||||
let updated = source;
|
let updated = source;
|
||||||
|
|
||||||
if (source.includes(v3Block)) {
|
if (source.includes(v5UpstreamBlock)) {
|
||||||
|
updated = source.replace(v5UpstreamBlock, v5PatchedBlock);
|
||||||
|
} else if (source.includes(v3Block)) {
|
||||||
updated = source.replace(v3Block, v4Block);
|
updated = source.replace(v3Block, v4Block);
|
||||||
} else if (source.includes(v2PatchedBlock)) {
|
} else if (source.includes(v2PatchedBlock)) {
|
||||||
updated = source.replace(v2PatchedBlock, v4Block);
|
updated = source.replace(v2PatchedBlock, v4Block);
|
||||||
|
|||||||
Reference in New Issue
Block a user