diff --git a/src/index.d.ts b/src/index.d.ts index 3df82a2..4ce7d5a 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,7 +1,31 @@ export type TrailingSlash = 'always' | 'never' | 'ignore'; +type CollectionPathMode = 'subdirectory' | `root` + export interface Options { contentPath?: string; // where you store your content relative to the root directory + /** + * @docs + * @name collectionPathMode + * @type {CollectionPathMode} + * @default `'subdirectory'` + * @description + * + * Where you store your collections: + * - `'subdirectory'` - Subdirectories under `contentPath` (ex: "src/content/docs/index.md" where docs is the content collection subdirectory of the contentPath src/content) + * - `'root'` - Directly inside `contentPath` (ex. src/content/index.md where src/content is the contentPath) + * + * Use the `root` configuration option when you are treating a single content collection as if it where located in the site root. In most scenarios, you should set this + * value to `subdirectory` or not set this value and the default of `subdirectory` will be used. + * + * ```js + * { + * // Example: Use `subdirectory` mode + * collectionPathMode: `subdirectory` + * } + * ``` + */ + collectionPathMode?: CollectionPathMode; basePath?: string; // https://docs.astro.build/en/reference/configuration-reference/#base /** * @name trailingSlash diff --git a/src/index.mjs b/src/index.mjs index 2b64d48..e849fb0 100644 --- a/src/index.mjs +++ b/src/index.mjs @@ -23,6 +23,9 @@ const defaultContentPath = ["src", "content"].join(path.sep); /** @type {import("./index").TrailingSlash} */ const defaultTrailingSlash = 'ignore'; +/** @type {import("./index").CollectionPathMode} */ +const defaultCollectionPathMode = 'subdirectory'; + /** @param {import('./index').Options} options */ function astroRehypeRelativeMarkdownLinks(options = {}) { return (tree, file) => { @@ -57,9 +60,9 @@ function astroRehypeRelativeMarkdownLinks(options = {}) { const { data: frontmatter } = matter(relativeFileContent); const frontmatterSlug = frontmatter.slug; const contentDir = options.contentPath || defaultContentPath; - + const collectionPathMode = options.collectionPathMode || defaultCollectionPathMode; const relativeToContentPath = path.relative(contentDir, relativeFile); - const collectionName = path.dirname(relativeToContentPath).split(path.posix.sep)[0]; + const collectionName = collectionPathMode === 'root' ? "" : path.dirname(relativeToContentPath).split(path.posix.sep)[0]; const relativeToCollectionPath = path.relative(collectionName, relativeToContentPath); const withoutFileExt = replaceExt(relativeToCollectionPath, "") const pathSegments = withoutFileExt.split(path.posix.sep); @@ -67,9 +70,9 @@ function astroRehypeRelativeMarkdownLinks(options = {}) { const resolvedSlug = resolveSlug(generatedSlug, frontmatterSlug); const trailingSlashMode = options.trailingSlash || defaultTrailingSlash; - const resolvedUrl = path.posix.sep + + const resolvedUrl = [ - collectionName, + !collectionName ? '' : (path.posix.sep + collectionName), resolvedSlug, ].join(path.posix.sep); diff --git a/src/index.test.mjs b/src/index.test.mjs index 8ee41b4..3d4ff65 100644 --- a/src/index.test.mjs +++ b/src/index.test.mjs @@ -303,7 +303,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected = @@ -319,7 +319,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures/dir-test-custom-slug" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures/dir-test-custom-slug", collectionPathMode: 'root' }) .process(input); const expected = @@ -335,7 +335,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected = @@ -351,7 +351,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected = @@ -367,7 +367,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected = @@ -383,7 +383,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected = @@ -399,7 +399,7 @@ test("astroRehypeRelativeMarkdownLinks", async (t) => { const input = 'foo'; const { value: actual } = await rehype() .use(testSetupRehype) - .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures" }) + .use(astroRehypeRelativeMarkdownLinks, { contentPath: "src/fixtures", collectionPathMode: 'root' }) .process(input); const expected =