@djangocfg/seo 2.1.204 → 2.1.206

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -3181,12 +3181,12 @@ var LINK_PATTERNS = [
3181
3181
  { regex: /\]\(\/docs\/([^)#\s"]+)/g, type: "absolute" },
3182
3182
  { regex: /href="\/docs\/([^"#]+)"/g, type: "absolute" },
3183
3183
  { regex: /to="\/docs\/([^"#]+)"/g, type: "absolute" },
3184
- // Dot-slash relative: [text](./path)
3184
+ // Dot-slash relative: [text](./path) — captures without ./
3185
3185
  { regex: /\]\(\.\/([^)#\s"]+)(?:#[^)]*)?\)/g, type: "dotslash" },
3186
3186
  { regex: /href="\.\/([^"#]+)"/g, type: "dotslash" },
3187
- // Parent relative: [text](../path)
3188
- { regex: /\]\(\.\.\/([^)#\s"]+)(?:#[^)]*)?\)/g, type: "parent" },
3189
- { regex: /href="\.\.\/([^"#]+)"/g, type: "parent" },
3187
+ // Parent relative: [text](../path) — captures FULL href including leading ../
3188
+ { regex: /\]\((\.\.\/[^)#\s"]+)(?:#[^)]*)?\)/g, type: "parent" },
3189
+ { regex: /href="(\.\.\/[^"#]+)"/g, type: "parent" },
3190
3190
  // Simple relative (no prefix): [text](path)
3191
3191
  { regex: /\]\((?!\/|http|#|\.|\[)([a-zA-Z][^)#\s"]*)(?:#[^)]*)?\)/g, type: "simple" },
3192
3192
  { regex: /href="(?!\/|http|#|\.)([a-zA-Z][^"#]*)"/g, type: "simple" }
@@ -3198,23 +3198,15 @@ function resolveLink(fromFilePath, linkPath, linkType, contentDir) {
3198
3198
  if (linkType === "absolute") {
3199
3199
  return linkPath;
3200
3200
  }
3201
- const { isIndex, folder: sourceFolder, name: fileName } = getFileInfo(fromFilePath, contentDir);
3202
- const sourceParts = sourceFolder ? sourceFolder.split("/") : [];
3201
+ const { folder: sourceFolder} = getFileInfo(fromFilePath, contentDir);
3202
+ sourceFolder ? sourceFolder.split("/") : [];
3203
3203
  if (linkType === "dotslash" || linkType === "simple") {
3204
- if (isIndex) {
3205
- return sourceFolder ? `${sourceFolder}/${linkPath}` : linkPath;
3206
- } else {
3207
- return sourceFolder ? `${sourceFolder}/${fileName}/${linkPath}` : `${fileName}/${linkPath}`;
3208
- }
3204
+ return sourceFolder ? `${sourceFolder}/${linkPath}` : linkPath;
3209
3205
  }
3210
3206
  if (linkType === "parent") {
3211
- if (isIndex) {
3212
- const newParts = [...sourceParts];
3213
- newParts.pop();
3214
- return newParts.length ? `${newParts.join("/")}/${linkPath}` : linkPath;
3215
- } else {
3216
- return sourceParts.length ? `${sourceParts.join("/")}/${linkPath}` : linkPath;
3217
- }
3207
+ const base = sourceFolder ? `/${sourceFolder}` : "/";
3208
+ const resolved = path.posix.resolve(base, linkPath);
3209
+ return resolved.replace(/^\//, "");
3218
3210
  }
3219
3211
  return linkPath;
3220
3212
  }
@@ -3337,11 +3329,12 @@ function calculateRelativePath(sourceFile, targetDocsPath, contentDir) {
3337
3329
  function processFile(filePath, contentDir, assetExtensions) {
3338
3330
  const content = fs4.readFileSync(filePath, "utf-8");
3339
3331
  const fixes = [];
3340
- const patterns = [
3332
+ const { isIndex, folder: sourceFolder } = getFileInfo(filePath, contentDir);
3333
+ const absolutePatterns = [
3341
3334
  { regex: /(\]\()\/docs\/([^)#\s"]+)(\))/g },
3342
3335
  { regex: /(href=")\/docs\/([^"#]+)(")/g }
3343
3336
  ];
3344
- for (const { regex } of patterns) {
3337
+ for (const { regex } of absolutePatterns) {
3345
3338
  regex.lastIndex = 0;
3346
3339
  let match;
3347
3340
  while ((match = regex.exec(content)) !== null) {
@@ -3359,6 +3352,24 @@ function processFile(filePath, contentDir, assetExtensions) {
3359
3352
  }
3360
3353
  }
3361
3354
  }
3355
+ if (!isIndex && sourceFolder) {
3356
+ const parentRelPattern = /\]\(\.\.\/([^./][^)#\s"]*?)(#[^)]*?)?\)/g;
3357
+ parentRelPattern.lastIndex = 0;
3358
+ let match;
3359
+ while ((match = parentRelPattern.exec(content)) !== null) {
3360
+ const slug = match[1];
3361
+ const anchor = match[2] || "";
3362
+ if (!slug || slug.includes("/")) continue;
3363
+ if (isAssetLink2(slug, assetExtensions)) continue;
3364
+ const siblingPath = sourceFolder ? `${sourceFolder}/${slug}` : slug;
3365
+ if (!pathExists(siblingPath, contentDir)) continue;
3366
+ fixes.push({
3367
+ from: `](../${slug}${anchor})`,
3368
+ to: `](./${slug}${anchor})`,
3369
+ line: content.substring(0, match.index).split("\n").length
3370
+ });
3371
+ }
3372
+ }
3362
3373
  return fixes;
3363
3374
  }
3364
3375
  function applyFixes(filePath, fixes) {