docnest 0.1.5 → 0.1.6
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 +1 -0
- package/dist/attachments.js +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -89,6 +89,7 @@ startServer(3000)
|
|
|
89
89
|
如果宿主项目需要生成静态站点,可使用 `docnest/attachments` 提供的
|
|
90
90
|
`collectDocumentAttachmentPaths` 和 `copyDocumentAttachments`。它们只复制
|
|
91
91
|
Markdown 或 HTML 中明确引用的本地附件,不按文件扩展名设置业务白名单;外链、文档链接、隐藏路径、路径穿越和代码块中的伪引用会被忽略,缺失的附件默认会让构建失败。
|
|
92
|
+
常见凭据文件(如 `.env`、私钥和证书容器)属于公共安全阻断项,即使被误写进文档链接也不会进入静态产物。
|
|
92
93
|
|
|
93
94
|
## 开发
|
|
94
95
|
|
package/dist/attachments.js
CHANGED
|
@@ -8,6 +8,23 @@ exports.copyDocumentAttachments = copyDocumentAttachments;
|
|
|
8
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const MARKDOWN_SOURCE_EXTENSIONS = new Set(['.md', '.markdown']);
|
|
11
|
+
const SENSITIVE_ATTACHMENT_EXTENSIONS = new Set([
|
|
12
|
+
'.env',
|
|
13
|
+
'.pem',
|
|
14
|
+
'.key',
|
|
15
|
+
'.p12',
|
|
16
|
+
'.pfx',
|
|
17
|
+
'.jks',
|
|
18
|
+
'.keystore',
|
|
19
|
+
'.secret',
|
|
20
|
+
'.secrets',
|
|
21
|
+
]);
|
|
22
|
+
const SENSITIVE_ATTACHMENT_NAMES = new Set([
|
|
23
|
+
'id_rsa',
|
|
24
|
+
'id_dsa',
|
|
25
|
+
'id_ecdsa',
|
|
26
|
+
'id_ed25519',
|
|
27
|
+
]);
|
|
11
28
|
const MARKDOWN_LINK_PATTERN = /!?\[[^\]]*\]\(\s*(?:<([^>\n]+)>|([^\s)]+))(?:\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?\s*\)/g;
|
|
12
29
|
const MARKDOWN_REFERENCE_PATTERN = /^\s{0,3}\[[^\]]+\]:\s*(?:<([^>\n]+)>|(\S+))/gm;
|
|
13
30
|
const HTML_ASSET_PATTERN = /\b(?:src|href)=["']([^"']+)["']/gi;
|
|
@@ -33,6 +50,12 @@ function isLocalRelativeTarget(target) {
|
|
|
33
50
|
function stripTargetSuffix(target) {
|
|
34
51
|
return target.split(/[?#]/, 1)[0];
|
|
35
52
|
}
|
|
53
|
+
function isSensitiveAttachment(target) {
|
|
54
|
+
const baseName = node_path_1.default.basename(target).toLowerCase();
|
|
55
|
+
return SENSITIVE_ATTACHMENT_EXTENSIONS.has(node_path_1.default.extname(baseName))
|
|
56
|
+
|| SENSITIVE_ATTACHMENT_NAMES.has(baseName)
|
|
57
|
+
|| baseName.startsWith('.env.');
|
|
58
|
+
}
|
|
36
59
|
function extractTargets(markdown) {
|
|
37
60
|
const source = markdown.replace(FENCED_CODE_PATTERN, '');
|
|
38
61
|
const targets = [];
|
|
@@ -65,6 +88,8 @@ function resolveAttachmentPath(docsRoot, realDocsRoot, markdownPath, rawTarget,
|
|
|
65
88
|
const extension = node_path_1.default.extname(decodedTarget).toLowerCase();
|
|
66
89
|
if (MARKDOWN_SOURCE_EXTENSIONS.has(extension))
|
|
67
90
|
return null;
|
|
91
|
+
if (isSensitiveAttachment(decodedTarget))
|
|
92
|
+
return null;
|
|
68
93
|
const resolved = node_path_1.default.resolve(docsRoot, node_path_1.default.dirname(markdownPath), decodedTarget);
|
|
69
94
|
const relative = node_path_1.default.relative(docsRoot, resolved);
|
|
70
95
|
if (!relative || node_path_1.default.isAbsolute(relative) || relative === '..' || relative.startsWith(`..${node_path_1.default.sep}`)) {
|