@salesforcedevs/sfdocs-remark-include-plugin 0.0.5-alpha → 0.1.0-alpha

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/README.md CHANGED
@@ -1,21 +1,15 @@
1
1
  # Remark Include Plugin
2
2
 
3
- ## Usage
4
-
5
- Use with `remark-directive` in your unified pipeline:
6
-
7
3
  ## Examples
8
4
 
9
- Basic include:
5
+ Include another markdown file:
10
6
 
11
7
  ```
12
8
  ::include{src="../shared/snippet.md"}
13
9
  ```
14
10
 
15
- Include with shared media rewrite:
11
+ The plugin reads the target file, parses it, and inserts its children into the current document.
16
12
 
17
- ```
18
- ::include{src="../shared/test_include.md"}
19
- ```
13
+ If the included file path contains `/shared/`, relative image URLs in that included content are rewritten to absolute content paths.
20
14
 
21
- If the included file path contains `/shared/`, relative media links inside that file are rewritten to content-root absolute paths.
15
+ You can pass custom render functions as the plugin’s second argument, e.g. for a VS Code extension.
package/dist/index.d.ts CHANGED
@@ -6,8 +6,9 @@ import { Transformer } from 'unified';
6
6
  * with the included content. Must be used after remark-directive.
7
7
  * When the included file path contains /shared/, image URLs in that content are rewritten to absolute paths using the content directory.
8
8
  *
9
+ * @param customRenderFunctions - Optional; for custom rendering functions (e.g. `renderInclude`).
9
10
  * @returns Function that returns a Remark transformer
10
11
  */
11
- declare function includePlugin(): () => Transformer;
12
+ declare function includePlugin(customRenderFunctions?: any): () => Transformer;
12
13
  export default includePlugin;
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAwCtC;;;;;;;;GAQG;AACH,iBAAS,aAAa,UACmB,WAAW,CAgCnD;AAED,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAoCtC;;;;;;;;;GASG;AACH,iBAAS,aAAa,CAAC,qBAAqB,CAAC,KAAA,SACJ,WAAW,CAiCnD;AAED,eAAe,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
7
- const hastscript_1 = __importDefault(require("hastscript"));
8
7
  const path_1 = __importDefault(require("path"));
9
8
  const fs_1 = __importDefault(require("fs"));
10
9
  const vfile_1 = __importDefault(require("vfile"));
@@ -12,6 +11,7 @@ const INCLUDE_DIRECTIVE = 'include';
12
11
  const LEAF_DIRECTIVE_TYPE = 'leafDirective';
13
12
  const CONTENT_FOLDER = '/content/';
14
13
  const SHARED_PATH_SEGMENT = '/shared/';
14
+ const MEDIA_FOLDER = '/media';
15
15
  function getContentDirPath(curFilePath) {
16
16
  const position = curFilePath.indexOf(CONTENT_FOLDER);
17
17
  if (position !== -1) {
@@ -20,13 +20,8 @@ function getContentDirPath(curFilePath) {
20
20
  return '';
21
21
  }
22
22
  function getSubstringAfterMedia(folderPath) {
23
- const idx = folderPath.indexOf('/media');
24
- if (idx !== -1)
25
- return folderPath.substring(idx + 1);
26
- const idx2 = folderPath.indexOf('media');
27
- if (idx2 !== -1)
28
- return folderPath.substring(idx2);
29
- return folderPath;
23
+ const index = folderPath.indexOf(MEDIA_FOLDER);
24
+ return folderPath.substring(index);
30
25
  }
31
26
  function transformImageLinksInTree(root, contentDir) {
32
27
  if (!contentDir)
@@ -47,9 +42,10 @@ function transformImageLinksInTree(root, contentDir) {
47
42
  * with the included content. Must be used after remark-directive.
48
43
  * When the included file path contains /shared/, image URLs in that content are rewritten to absolute paths using the content directory.
49
44
  *
45
+ * @param customRenderFunctions - Optional; for custom rendering functions (e.g. `renderInclude`).
50
46
  * @returns Function that returns a Remark transformer
51
47
  */
52
- function includePlugin() {
48
+ function includePlugin(customRenderFunctions) {
53
49
  return function includePluginImpl() {
54
50
  const processor = this;
55
51
  return function transformer(tree, file) {
@@ -59,24 +55,26 @@ function includePlugin() {
59
55
  return;
60
56
  const src = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.src;
61
57
  const filename = path_1.default.resolve(file.dirname || '', src);
62
- if (!fs_1.default.existsSync(filename)) {
63
- file.fail(`File not found ${filename}`, node);
64
- return;
65
- }
66
58
  try {
67
59
  const content = fs_1.default.readFileSync(filename);
68
60
  const includeFile = (0, vfile_1.default)({ path: filename, contents: content });
69
- let root = processor.parse(includeFile);
70
- if (filename.includes(SHARED_PATH_SEGMENT)) {
71
- transformImageLinksInTree(root, getContentDirPath(filename));
61
+ if (customRenderFunctions === null || customRenderFunctions === void 0 ? void 0 : customRenderFunctions.renderInclude) {
62
+ const root = processor.processSync(includeFile);
63
+ const metadata = new Map([
64
+ ['root', root],
65
+ ['node', node],
66
+ ]);
67
+ const out = customRenderFunctions.renderInclude(metadata).get('outputDom');
68
+ parent.children.splice(i, 1, { type: 'html', value: out !== null && out !== void 0 ? out : '' });
69
+ }
70
+ else {
71
+ let root = processor.parse(includeFile);
72
+ if (filename.includes(SHARED_PATH_SEGMENT)) {
73
+ transformImageLinksInTree(root, getContentDirPath(filename));
74
+ }
75
+ const { children } = root;
76
+ parent.children.splice(i + 1, 0, ...(Array.isArray(children) ? children : []));
72
77
  }
73
- const { children } = root;
74
- const data = node.data || (node.data = {});
75
- const hast = (0, hastscript_1.default)(INCLUDE_DIRECTIVE, node.attributes || {});
76
- // node.type = 'containerDirective';
77
- node.children = Array.isArray(children) ? children : [];
78
- data.hName = INCLUDE_DIRECTIVE;
79
- data.hProperties = hast.properties;
80
78
  }
81
79
  catch (err) {
82
80
  file.fail((err === null || err === void 0 ? void 0 : err.message) || `Failed to read file ${filename}`, node);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.5-alpha",
2
+ "version": "0.1.0-alpha",
3
3
  "name": "@salesforcedevs/sfdocs-remark-include-plugin",
4
4
  "description": "SFDocs remark plugin for the include directive (::include)",
5
5
  "author": "SFDocs Team",
@@ -39,7 +39,7 @@ describe('Include plugin test', () => {
39
39
  jest.restoreAllMocks();
40
40
  });
41
41
 
42
- test('Include from shared folder testing', async () => {
42
+ test('includes markdown content from a shared file', async () => {
43
43
  fs.mkdirSync(path.join(testRoot, 'abc/xyz/guides'), { recursive: true });
44
44
  fs.mkdirSync(path.join(testRoot, 'abc/xyz/shared'), { recursive: true });
45
45
  fs.writeFileSync(
@@ -54,11 +54,12 @@ describe('Include plugin test', () => {
54
54
  `);
55
55
  const file = vfile({ path: path.join(testRoot, 'abc/xyz/guides/parent.md'), contents: content });
56
56
  const transformedHtml = await processMarkdown(file);
57
+
57
58
  expect(transformedHtml.contents).toContain('<h2>Include file</h2>');
58
59
  expect(transformedHtml.contents).toContain('<p>shared content</p>');
59
60
  });
60
61
 
61
- test('Include from shared folder with media image (rewrites image URL)', async () => {
62
+ test('rewrites shared include media image URL to content media path', async () => {
62
63
  fs.mkdirSync(path.join(testRoot, 'abc/xyz/content/guides'), { recursive: true });
63
64
  fs.mkdirSync(path.join(testRoot, 'abc/xyz/content/shared'), { recursive: true });
64
65
  fs.writeFileSync(
@@ -77,11 +78,12 @@ describe('Include plugin test', () => {
77
78
  contents: content,
78
79
  });
79
80
  const transformedHtml = await processMarkdown(file);
81
+
80
82
  expect(transformedHtml.contents).toContain('<h2>Include file</h2>');
81
83
  expect(transformedHtml.contents).toContain(path.join(testRoot, 'abc/xyz/content/media/test.jpeg'));
82
84
  });
83
85
 
84
- test('Include from shared folder with media image in locale (rewrites image URL)', async () => {
86
+ test('rewrites localized shared include media image URL to root content media path', async () => {
85
87
  fs.mkdirSync(path.join(testRoot, 'abc/content/ja-jp/guides'), { recursive: true });
86
88
  fs.mkdirSync(path.join(testRoot, 'abc/content/ja-jp/shared'), { recursive: true });
87
89
  fs.writeFileSync(
@@ -100,6 +102,36 @@ describe('Include plugin test', () => {
100
102
  contents: content,
101
103
  });
102
104
  const transformedHtml = await processMarkdown(file);
105
+
103
106
  expect(transformedHtml.contents).toContain(path.join(testRoot, 'abc/content/media/test.jpeg'));
104
107
  });
108
+
109
+ test('renderInclude replaces directive with HTML from outputDom', async () => {
110
+ fs.mkdirSync(path.join(testRoot, 'guides'), { recursive: true });
111
+ fs.writeFileSync(path.join(testRoot, 'guides/included.md'), '# Included heading');
112
+ const content = stripIndent(`
113
+ ::include{src="included.md"}
114
+ `);
115
+ const file = vfile({ path: path.join(testRoot, 'guides/parent.md'), contents: content });
116
+ const transformedHtml = unified()
117
+ .use(parse)
118
+ .use(directive)
119
+ .use(
120
+ includePlugin({
121
+ renderInclude: () => {
122
+ const m = new Map<string, string>();
123
+ m.set('outputDom', '<section class="include-custom">custom block</section>');
124
+ return m;
125
+ },
126
+ }),
127
+ )
128
+ .use(remark2rehype, { allowDangerousHtml: true })
129
+ .use(rawHtml)
130
+ .use(remarkGfm)
131
+ .use(html)
132
+ .processSync(file);
133
+
134
+ expect(transformedHtml.contents).toContain('<section class="include-custom">custom block</section>');
135
+ expect(transformedHtml.contents).not.toContain('Included heading');
136
+ });
105
137
  });
package/src/index.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import visit from 'unist-util-visit';
2
- import h from 'hastscript';
3
2
  import { Transformer } from 'unified';
4
3
  import path from 'path';
5
4
  import fs from 'fs';
@@ -9,6 +8,7 @@ const INCLUDE_DIRECTIVE = 'include';
9
8
  const LEAF_DIRECTIVE_TYPE = 'leafDirective';
10
9
  const CONTENT_FOLDER = '/content/';
11
10
  const SHARED_PATH_SEGMENT = '/shared/';
11
+ const MEDIA_FOLDER = '/media';
12
12
 
13
13
  function getContentDirPath(curFilePath: string): string {
14
14
  const position = curFilePath.indexOf(CONTENT_FOLDER);
@@ -18,14 +18,9 @@ function getContentDirPath(curFilePath: string): string {
18
18
  return '';
19
19
  }
20
20
 
21
- function getSubstringAfterMedia(folderPath: string): string {
22
- const idx = folderPath.indexOf('/media');
23
-
24
- if (idx !== -1) return folderPath.substring(idx + 1);
25
- const idx2 = folderPath.indexOf('media');
26
-
27
- if (idx2 !== -1) return folderPath.substring(idx2);
28
- return folderPath;
21
+ function getSubstringAfterMedia(folderPath: string) {
22
+ const index = folderPath.indexOf(MEDIA_FOLDER);
23
+ return folderPath.substring(index);
29
24
  }
30
25
 
31
26
  function transformImageLinksInTree(root: any, contentDir: string): void {
@@ -47,9 +42,10 @@ function transformImageLinksInTree(root: any, contentDir: string): void {
47
42
  * with the included content. Must be used after remark-directive.
48
43
  * When the included file path contains /shared/, image URLs in that content are rewritten to absolute paths using the content directory.
49
44
  *
45
+ * @param customRenderFunctions - Optional; for custom rendering functions (e.g. `renderInclude`).
50
46
  * @returns Function that returns a Remark transformer
51
47
  */
52
- function includePlugin() {
48
+ function includePlugin(customRenderFunctions?) {
53
49
  return function includePluginImpl(): Transformer {
54
50
  const processor = this;
55
51
  return function transformer(tree: any, file: VFile): void {
@@ -57,25 +53,26 @@ function includePlugin() {
57
53
  if (node.type !== LEAF_DIRECTIVE_TYPE || node.name !== INCLUDE_DIRECTIVE || !parent) return;
58
54
  const src = node.attributes?.src;
59
55
  const filename = path.resolve(file.dirname || '', src);
60
- if (!fs.existsSync(filename)) {
61
- file.fail(`File not found ${filename}`, node);
62
- return;
63
- }
64
56
 
65
57
  try {
66
58
  const content = fs.readFileSync(filename);
67
59
  const includeFile = vfile({ path: filename, contents: content });
68
- let root = processor.parse(includeFile);
69
- if (filename.includes(SHARED_PATH_SEGMENT)) {
70
- transformImageLinksInTree(root, getContentDirPath(filename));
60
+ if (customRenderFunctions?.renderInclude) {
61
+ const root = processor.processSync(includeFile);
62
+ const metadata = new Map([
63
+ ['root', root],
64
+ ['node', node],
65
+ ]);
66
+ const out = customRenderFunctions.renderInclude(metadata).get('outputDom');
67
+ parent.children.splice(i, 1, { type: 'html', value: out ?? '' });
68
+ } else {
69
+ let root = processor.parse(includeFile);
70
+ if (filename.includes(SHARED_PATH_SEGMENT)) {
71
+ transformImageLinksInTree(root, getContentDirPath(filename));
72
+ }
73
+ const { children } = root;
74
+ parent.children.splice(i + 1, 0, ...(Array.isArray(children) ? children : []));
71
75
  }
72
- const { children } = root;
73
- const data = node.data || (node.data = {});
74
- const hast = h(INCLUDE_DIRECTIVE, node.attributes || {});
75
- // node.type = 'containerDirective';
76
- node.children = Array.isArray(children) ? children : [];
77
- data.hName = INCLUDE_DIRECTIVE;
78
- data.hProperties = hast.properties;
79
76
  } catch (err: any) {
80
77
  file.fail(err?.message || `Failed to read file ${filename}`, node);
81
78
  }