@xsynaptic/satteri-trailing-slash 0.2.1 → 0.2.3

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/index.mjs CHANGED
@@ -35,7 +35,7 @@ function normalizeHref(href, mode) {
35
35
  return `${path}/${suffix}`;
36
36
  }
37
37
  if (!path.endsWith("/")) return void 0;
38
- return `${path.slice(0, -1)}${suffix}`;
38
+ return `${path.replace(/\/+$/, "")}${suffix}`;
39
39
  }
40
40
  export { normalizeHref, trailingSlash };
41
41
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { defineHastPlugin } from 'satteri';\nimport { z } from 'zod';\n\nconst optionsSchema = z.object({\n\ttrailingSlash: z.enum(['always', 'never', 'ignore']).default('ignore'),\n});\n\ntype TrailingSlashOptions = z.input<typeof optionsSchema>;\n\nexport function trailingSlash(options?: null | Readonly<TrailingSlashOptions>) {\n\tconst settings = optionsSchema.parse(options ?? {});\n\n\treturn defineHastPlugin({\n\t\telement: {\n\t\t\tfilter: ['a'],\n\t\t\tvisit(node, ctx) {\n\t\t\t\tif (settings.trailingSlash === 'ignore') return;\n\n\t\t\t\tconst href = node.properties.href;\n\t\t\t\tif (typeof href !== 'string') return;\n\n\t\t\t\tconst next = normalizeHref(href, settings.trailingSlash);\n\t\t\t\tif (next !== undefined) ctx.setProperty(node, 'href', next);\n\t\t\t},\n\t\t},\n\t\tname: 'trailing-slash',\n\t});\n}\n\n// Returns undefined when nothing should change, so the visitor skips the write\nfunction normalizeHref(href: string, mode: 'always' | 'never'): string | undefined {\n\tif (!href.startsWith('/') || href.startsWith('//')) return undefined; // internal root-relative only\n\n\tconst suffixMarkers = [href.indexOf('?'), href.indexOf('#')].filter((index) => index !== -1);\n\tconst cut = suffixMarkers.length === 0 ? -1 : Math.min(...suffixMarkers);\n\tconst path = cut === -1 ? href : href.slice(0, cut);\n\n\tif (path === '/') return undefined; // root is canonical in both modes\n\n\tconst suffix = cut === -1 ? '' : href.slice(cut);\n\n\tif (mode === 'always') {\n\t\tconst lastSegment = path.slice(path.lastIndexOf('/') + 1);\n\t\tif (path.endsWith('/') || lastSegment.includes('.')) return undefined; // already slashed, or a file\n\t\treturn `${path}/${suffix}`;\n\t}\n\n\tif (!path.endsWith('/')) return undefined; // 'never': nothing to strip\n\treturn `${path.slice(0, -1)}${suffix}`;\n}\n\nexport { normalizeHref };\nexport type { TrailingSlashOptions };\n"],"mappings":";;;AAGA,MAAM,gBAAgB,EAAE,OAAO,EAC9B,eAAe,EAAE,KAAK;CAAC;CAAU;CAAS;AAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,EACtE,CAAC;AAID,SAAgB,cAAc,SAAiD;CAC9E,MAAM,WAAW,cAAc,MAAM,WAAW,CAAC,CAAC;CAElD,OAAO,iBAAiB;EACvB,SAAS;GACR,QAAQ,CAAC,GAAG;GACZ,MAAM,MAAM,KAAK;IAChB,IAAI,SAAS,kBAAkB,UAAU;IAEzC,MAAM,OAAO,KAAK,WAAW;IAC7B,IAAI,OAAO,SAAS,UAAU;IAE9B,MAAM,OAAO,cAAc,MAAM,SAAS,aAAa;IACvD,IAAI,SAAS,KAAA,GAAW,IAAI,YAAY,MAAM,QAAQ,IAAI;GAC3D;EACD;EACA,MAAM;CACP,CAAC;AACF;AAGA,SAAS,cAAc,MAAc,MAA8C;CAClF,IAAI,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,IAAI,GAAG,OAAO,KAAA;CAE3D,MAAM,gBAAgB,CAAC,KAAK,QAAQ,GAAG,GAAG,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE;CAC3F,MAAM,MAAM,cAAc,WAAW,IAAI,KAAK,KAAK,IAAI,GAAG,aAAa;CACvE,MAAM,OAAO,QAAQ,KAAK,OAAO,KAAK,MAAM,GAAG,GAAG;CAElD,IAAI,SAAS,KAAK,OAAO,KAAA;CAEzB,MAAM,SAAS,QAAQ,KAAK,KAAK,KAAK,MAAM,GAAG;CAE/C,IAAI,SAAS,UAAU;EACtB,MAAM,cAAc,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;EACxD,IAAI,KAAK,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG,OAAO,KAAA;EAC5D,OAAO,GAAG,KAAK,GAAG;CACnB;CAEA,IAAI,CAAC,KAAK,SAAS,GAAG,GAAG,OAAO,KAAA;CAChC,OAAO,GAAG,KAAK,MAAM,GAAG,EAAE,IAAI;AAC/B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { defineHastPlugin } from 'satteri';\nimport { z } from 'zod';\n\nconst optionsSchema = z.object({\n\ttrailingSlash: z.enum(['always', 'never', 'ignore']).default('ignore'),\n});\n\ntype TrailingSlashOptions = z.input<typeof optionsSchema>;\n\nexport function trailingSlash(options?: null | Readonly<TrailingSlashOptions>) {\n\tconst settings = optionsSchema.parse(options ?? {});\n\n\treturn defineHastPlugin({\n\t\telement: {\n\t\t\tfilter: ['a'],\n\t\t\tvisit(node, ctx) {\n\t\t\t\tif (settings.trailingSlash === 'ignore') return;\n\n\t\t\t\tconst href = node.properties.href;\n\t\t\t\tif (typeof href !== 'string') return;\n\n\t\t\t\tconst next = normalizeHref(href, settings.trailingSlash);\n\t\t\t\tif (next !== undefined) ctx.setProperty(node, 'href', next);\n\t\t\t},\n\t\t},\n\t\tname: 'trailing-slash',\n\t});\n}\n\n// Returns undefined when nothing should change, so the visitor skips the write\nfunction normalizeHref(href: string, mode: 'always' | 'never'): string | undefined {\n\tif (!href.startsWith('/') || href.startsWith('//')) return undefined; // internal root-relative only\n\n\tconst suffixMarkers = [href.indexOf('?'), href.indexOf('#')].filter((index) => index !== -1);\n\tconst cut = suffixMarkers.length === 0 ? -1 : Math.min(...suffixMarkers);\n\tconst path = cut === -1 ? href : href.slice(0, cut);\n\n\tif (path === '/') return undefined; // root is canonical in both modes\n\n\tconst suffix = cut === -1 ? '' : href.slice(cut);\n\n\tif (mode === 'always') {\n\t\tconst lastSegment = path.slice(path.lastIndexOf('/') + 1);\n\t\tif (path.endsWith('/') || lastSegment.includes('.')) return undefined; // already slashed, or a file\n\t\treturn `${path}/${suffix}`;\n\t}\n\n\tif (!path.endsWith('/')) return undefined; // 'never': nothing to strip\n\treturn `${path.replace(/\\/+$/, '')}${suffix}`;\n}\n\nexport { normalizeHref };\nexport type { TrailingSlashOptions };\n"],"mappings":";;;AAGA,MAAM,gBAAgB,EAAE,OAAO,EAC9B,eAAe,EAAE,KAAK;CAAC;CAAU;CAAS;AAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,EACtE,CAAC;AAID,SAAgB,cAAc,SAAiD;CAC9E,MAAM,WAAW,cAAc,MAAM,WAAW,CAAC,CAAC;CAElD,OAAO,iBAAiB;EACvB,SAAS;GACR,QAAQ,CAAC,GAAG;GACZ,MAAM,MAAM,KAAK;IAChB,IAAI,SAAS,kBAAkB,UAAU;IAEzC,MAAM,OAAO,KAAK,WAAW;IAC7B,IAAI,OAAO,SAAS,UAAU;IAE9B,MAAM,OAAO,cAAc,MAAM,SAAS,aAAa;IACvD,IAAI,SAAS,KAAA,GAAW,IAAI,YAAY,MAAM,QAAQ,IAAI;GAC3D;EACD;EACA,MAAM;CACP,CAAC;AACF;AAGA,SAAS,cAAc,MAAc,MAA8C;CAClF,IAAI,CAAC,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,IAAI,GAAG,OAAO,KAAA;CAE3D,MAAM,gBAAgB,CAAC,KAAK,QAAQ,GAAG,GAAG,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE;CAC3F,MAAM,MAAM,cAAc,WAAW,IAAI,KAAK,KAAK,IAAI,GAAG,aAAa;CACvE,MAAM,OAAO,QAAQ,KAAK,OAAO,KAAK,MAAM,GAAG,GAAG;CAElD,IAAI,SAAS,KAAK,OAAO,KAAA;CAEzB,MAAM,SAAS,QAAQ,KAAK,KAAK,KAAK,MAAM,GAAG;CAE/C,IAAI,SAAS,UAAU;EACtB,MAAM,cAAc,KAAK,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;EACxD,IAAI,KAAK,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG,OAAO,KAAA;EAC5D,OAAO,GAAG,KAAK,GAAG;CACnB;CAEA,IAAI,CAAC,KAAK,SAAS,GAAG,GAAG,OAAO,KAAA;CAChC,OAAO,GAAG,KAAK,QAAQ,QAAQ,EAAE,IAAI;AACtC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsynaptic/satteri-trailing-slash",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Sätteri hast plugin that normalizes trailing slashes on internal markdown links to match an Astro project's trailingSlash setting.",
5
5
  "type": "module",
6
6
  "license": "MIT",