Skip to content

Commit 5457fc7

Browse files
add option for root file
1 parent 4c483d2 commit 5457fc7

File tree

3 files changed

+78
-11
lines changed

3 files changed

+78
-11
lines changed

remark-alt-text-files/README.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# @fujocoded/remark-alt-text-files
2+
3+
A remark plugin that allows loading alt text from a file, rather than hardocding it in markdown
4+
5+
## Sample usage
6+
7+
In `astro.config.js`:
8+
9+
```ts
10+
import remarkAltTextFiles from "@fujocoded/remark-alt-text-files";
11+
12+
export default defineConfig({
13+
// ...
14+
integrations: [
15+
mdx({
16+
remarkPlugins: [remarkAltTextFiles],
17+
}),
18+
],
19+
});
20+
```
21+
22+
In markdown files:
23+
24+
```md
25+
![regular alt text](./image.png)
26+
27+
![file:path/to/alt/text.alt.txt](./image.png)
28+
29+
# This will load alt text from "./image.alt.txt"
30+
31+
![file:](./image.png)
32+
```
33+
34+
You can change the following options:
35+
36+
- `root`: where the alt text file will be searched from (default: the loaded path of the markdown file or `process.cwd()`)
37+
- `pathPrefix`: the prefix to indicate alt text should be loaded from a file (default: `file:`)

remark-alt-text-files/index.ts

+18-8
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,41 @@ import { VFile } from "vfile";
66

77
import type mdast from "mdast";
88

9-
interface PluginArgs {
9+
export interface PluginArgs {
1010
pathPrefix?: string;
11+
root?: string;
1112
}
1213

1314
const getFilePath = ({
1415
imageNode,
1516
vfile,
16-
pathPrefix,
17+
options,
1718
}: {
1819
imageNode: mdast.Image;
1920
vfile: VFile;
20-
pathPrefix: string;
21+
options: PluginArgs & { pathPrefix: string };
2122
}) => {
22-
let filePath = imageNode.alt!.replace(pathPrefix, "");
23+
let filePath = imageNode.alt!.replace(options.pathPrefix, "");
2324
if (filePath == "") {
2425
// We use the name of the imageNode file and replace the extension with .alt.txt
2526
filePath = imageNode.url.replace(/\.[^.]+$/, ".alt.txt")!;
2627
}
2728

2829
return join(
29-
// If this was loaded from a file, then use the directory of that file
30+
// If the root is provided, use it
31+
// Otherwise, if this was loaded from a file, then use the directory of that file
3032
// Otherwise, use the current working directory
31-
vfile.history[0] ? dirname(vfile.history[0]) : process.cwd(),
33+
options.root
34+
? options.root
35+
: vfile.history[0]
36+
? dirname(vfile.history[0])
37+
: process.cwd(),
3238
filePath
3339
);
3440
};
3541

3642
const plugin: Plugin<PluginArgs[], mdast.Root> =
37-
({ pathPrefix = "file:" } = {}) =>
43+
({ pathPrefix = "file:", root } = {}) =>
3844
async (tree, vfile) => {
3945
const loadingAltText: Promise<string>[] = [];
4046
const loadingAltFiles: string[] = [];
@@ -43,7 +49,11 @@ const plugin: Plugin<PluginArgs[], mdast.Root> =
4349
if (!node.alt || !node.alt.startsWith(pathPrefix)) {
4450
return;
4551
}
46-
const filePath = getFilePath({ imageNode: node, vfile, pathPrefix });
52+
const filePath = getFilePath({
53+
imageNode: node,
54+
vfile,
55+
options: { pathPrefix, root },
56+
});
4757
loadingAltText.push(
4858
readFile(filePath, "utf8").then((text) => (node.alt = text.trim()))
4959
);

remark-alt-text-files/tests/index.test.ts

+23-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { remark } from "remark";
33
import { Compatible, VFile } from "vfile";
44
import { fs, vol } from "memfs";
55
import { pathToFileURL } from "node:url";
6-
import remarkAltTextFiles from "../index.ts";
6+
import remarkAltTextFiles, { PluginArgs } from "../index.ts";
77

88
/**
99
* NOTE TO FUTURE SELF: vitest is annoying about the output of new lines on
@@ -34,6 +34,9 @@ beforeEach(() => {
3434

3535
"./path/to/image.alt.txt":
3636
"This is the alt text from /path/to/image.alt.txt",
37+
38+
"./root/directory/path/to/image.alt.txt":
39+
"This is the alt text for /path/to/image.png, relative to root/directory",
3740
},
3841
process.cwd()
3942
);
@@ -74,6 +77,21 @@ test("should load specific file when path is provided, from file's directory", a
7477
![This is the alt text for /path/to/image.png, relative to markdown-folder](/path/to/image.png)`);
7578
});
7679

80+
test("should load specific file when path is provided, from given root", async () => {
81+
const result = await processMarkdown(
82+
`# Hello, world!
83+
84+
![file:./path/to/image.alt.txt](/path/to/image.png)`,
85+
{
86+
root: `${process.cwd()}/root/directory`,
87+
}
88+
);
89+
90+
expect(result).toBe(`# Hello, world!
91+
92+
![This is the alt text for /path/to/image.png, relative to root/directory](/path/to/image.png)`);
93+
});
94+
7795
test("should load file with same name when no path is provided", async () => {
7896
const result = await processMarkdown(`# Hello, world!
7997
@@ -95,7 +113,9 @@ test("should fail when file does not exist", async () => {
95113
);
96114
});
97115

98-
const processMarkdown = async (value: Compatible) => {
99-
const processedTree = await remark().use(remarkAltTextFiles).process(value);
116+
const processMarkdown = async (value: Compatible, options?: PluginArgs) => {
117+
const processedTree = await remark()
118+
.use(remarkAltTextFiles, options ?? {})
119+
.process(value);
100120
return processedTree.toString().slice(0, -1);
101121
};

0 commit comments

Comments
 (0)