@salesforcedevs/sfdocs-remark-include-plugin 0.0.1-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 +49 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Remark Include plugin
|
|
2
|
+
|
|
3
|
+
## About
|
|
4
|
+
|
|
5
|
+
This is a custom plugin for including the contents of another file in a markdown document. It processes the include directive (`::include{src="..."}`) by reading the target file, parsing or processing it through the unified pipeline, and replacing the directive with the included content.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
::include{src="../shared/snippet.md"}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
When the included file path contains `/shared/`, image URLs in that content are rewritten to absolute paths using the content directory.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Use with `remark-directive` in your unified pipeline:
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
import unified from 'unified';
|
|
21
|
+
import remarkParse from 'remark-parse';
|
|
22
|
+
import remarkDirective from 'remark-directive';
|
|
23
|
+
import includePlugin from '@salesforcedevs/sfdocs-remark-include-plugin';
|
|
24
|
+
|
|
25
|
+
unified()
|
|
26
|
+
.use(remarkParse)
|
|
27
|
+
.use(remarkDirective)
|
|
28
|
+
.use(includePlugin())
|
|
29
|
+
.processSync(markdown);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Optional custom renderer (for custom HTML wrapping of included content):
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
includePlugin({
|
|
36
|
+
renderInclude(metadata) {
|
|
37
|
+
const root = metadata.get('root');
|
|
38
|
+
const node = metadata.get('node');
|
|
39
|
+
const out = new Map();
|
|
40
|
+
out.set('outputDom', `<div class="include">${root}</div>`);
|
|
41
|
+
return out;
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
- `yarn build` — compile TypeScript
|
|
49
|
+
- `yarn test` — run tests
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Transformer } from 'unified';
|
|
2
|
+
/**
|
|
3
|
+
* SFDocs Include Plugin
|
|
4
|
+
* Processes include directives (::include{src="path/to/file.md"}) by reading the file,
|
|
5
|
+
* parsing or processing it through the unified pipeline, and replacing the directive
|
|
6
|
+
* with the included content. Must be used after remark-directive.
|
|
7
|
+
* When the included file path contains /shared/, image URLs in that content are rewritten to absolute paths using the content directory.
|
|
8
|
+
*
|
|
9
|
+
* @param options - Optional { renderInclude } for custom HTML rendering of included content
|
|
10
|
+
* @returns Remark transformer function
|
|
11
|
+
*/
|
|
12
|
+
declare function includePlugin(options?: {
|
|
13
|
+
renderInclude?: (metadata: Map<string, unknown>) => Map<string, string>;
|
|
14
|
+
}): () => Transformer;
|
|
15
|
+
export default includePlugin;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAwCtC;;;;;;;;;GASG;AACH,iBAAS,aAAa,CAAC,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,MAAM,WAAW,CAsC/H;AAED,eAAe,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const unist_util_visit_1 = __importDefault(require("unist-util-visit"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const vfile_1 = __importDefault(require("vfile"));
|
|
10
|
+
const INCLUDE_DIRECTIVE = 'include';
|
|
11
|
+
const LEAF_DIRECTIVE_TYPE = 'leafDirective';
|
|
12
|
+
const CONTENT_FOLDER = '/content/';
|
|
13
|
+
const SHARED_PATH_SEGMENT = '/shared/';
|
|
14
|
+
function getContentDirPath(curFilePath) {
|
|
15
|
+
const position = curFilePath.indexOf(CONTENT_FOLDER);
|
|
16
|
+
if (position !== -1) {
|
|
17
|
+
return curFilePath.slice(0, position + CONTENT_FOLDER.length);
|
|
18
|
+
}
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
function getSubstringAfterMedia(folderPath) {
|
|
22
|
+
const idx = folderPath.indexOf('/media');
|
|
23
|
+
if (idx !== -1)
|
|
24
|
+
return folderPath.substring(idx + 1);
|
|
25
|
+
const idx2 = folderPath.indexOf('media');
|
|
26
|
+
if (idx2 !== -1)
|
|
27
|
+
return folderPath.substring(idx2);
|
|
28
|
+
return folderPath;
|
|
29
|
+
}
|
|
30
|
+
function transformImageLinksInTree(root, contentDir) {
|
|
31
|
+
if (!contentDir)
|
|
32
|
+
return;
|
|
33
|
+
(0, unist_util_visit_1.default)(root, 'image', (node) => {
|
|
34
|
+
const filePath = node.url;
|
|
35
|
+
const isRelativeUrl = !(filePath === null || filePath === void 0 ? void 0 : filePath.match(/^(https?:\/\/|www\.).*/));
|
|
36
|
+
if (isRelativeUrl && filePath) {
|
|
37
|
+
const afterMedia = getSubstringAfterMedia(filePath);
|
|
38
|
+
node.url = path_1.default.join(contentDir, afterMedia);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* SFDocs Include Plugin
|
|
44
|
+
* Processes include directives (::include{src="path/to/file.md"}) by reading the file,
|
|
45
|
+
* parsing or processing it through the unified pipeline, and replacing the directive
|
|
46
|
+
* with the included content. Must be used after remark-directive.
|
|
47
|
+
* When the included file path contains /shared/, image URLs in that content are rewritten to absolute paths using the content directory.
|
|
48
|
+
*
|
|
49
|
+
* @param options - Optional { renderInclude } for custom HTML rendering of included content
|
|
50
|
+
* @returns Remark transformer function
|
|
51
|
+
*/
|
|
52
|
+
function includePlugin(options) {
|
|
53
|
+
return function includePluginImpl() {
|
|
54
|
+
const processor = this;
|
|
55
|
+
return function transformer(tree, file) {
|
|
56
|
+
(0, unist_util_visit_1.default)(tree, (node, i, parent) => {
|
|
57
|
+
var _a;
|
|
58
|
+
if (node.type !== LEAF_DIRECTIVE_TYPE || node.name !== INCLUDE_DIRECTIVE || !parent)
|
|
59
|
+
return;
|
|
60
|
+
const src = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.src;
|
|
61
|
+
if (!src) {
|
|
62
|
+
file.fail('Include directive requires a src attribute', node);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const filename = path_1.default.resolve(file.dirname || '', src);
|
|
66
|
+
if (!fs_1.default.existsSync(filename)) {
|
|
67
|
+
file.fail(`File not found ${filename}`, node);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const includeFile = (0, vfile_1.default)({ path: filename, contents: fs_1.default.readFileSync(filename) });
|
|
72
|
+
if (options === null || options === void 0 ? void 0 : options.renderInclude) {
|
|
73
|
+
const root = processor.processSync(includeFile);
|
|
74
|
+
const metadata = new Map([['root', root], ['node', node]]);
|
|
75
|
+
const out = options.renderInclude(metadata).get('outputDom');
|
|
76
|
+
parent.children.splice(i, 1, { type: 'html', value: out });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
let root = processor.parse(includeFile);
|
|
80
|
+
if (filename.includes(SHARED_PATH_SEGMENT)) {
|
|
81
|
+
transformImageLinksInTree(root, getContentDirPath(filename));
|
|
82
|
+
}
|
|
83
|
+
parent.children.splice(i, 1, ...root.children);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
file.fail((err === null || err === void 0 ? void 0 : err.message) || `Failed to read file ${filename}`, node);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
exports.default = includePlugin;
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1-alpha",
|
|
3
|
+
"name": "@salesforcedevs/sfdocs-remark-include-plugin",
|
|
4
|
+
"description": "SFDocs remark plugin for the include directive",
|
|
5
|
+
"author": "SFDocs Team",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"sfdocs-plugin",
|
|
8
|
+
"remark-include"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/*",
|
|
14
|
+
"package.json",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "yarn compile",
|
|
19
|
+
"compile": "tsc -p tsconfig.json",
|
|
20
|
+
"prepublish": "yarn build",
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"test:ci": "yarn test --maxWorkers=1 --ci --coverage",
|
|
23
|
+
"watch": "tsc --watch"
|
|
24
|
+
},
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"prettier": "@salesforcedevs/sfdocs-prettier",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@salesforcedevs/sfdocs-prettier": "latest",
|
|
29
|
+
"rehype-raw": "^5.0.0",
|
|
30
|
+
"rehype-stringify": "^8.0.0",
|
|
31
|
+
"remark-directive": "^1.0.1",
|
|
32
|
+
"remark-gfm": "^1.0.0",
|
|
33
|
+
"remark-parse": "^9.0.0",
|
|
34
|
+
"remark-rehype": "^8.0.0",
|
|
35
|
+
"unified": "^9.0.0",
|
|
36
|
+
"unist-util-visit": "^2.0.3",
|
|
37
|
+
"vfile": "^4.2.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@babel/preset-typescript": "7.10.4",
|
|
41
|
+
"@types/jest": "^26.0.23",
|
|
42
|
+
"@types/node": "^15.6.1",
|
|
43
|
+
"jest": "^29.7.0",
|
|
44
|
+
"mock-fs": "^4.13.0",
|
|
45
|
+
"strip-indent": "^3.0.0",
|
|
46
|
+
"ts-jest": "^29.2.5",
|
|
47
|
+
"tslint": "^6.1.2",
|
|
48
|
+
"typescript": "^4.1.3"
|
|
49
|
+
}
|
|
50
|
+
}
|