@o2b/meta 1.0.0-dev.0
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/dist/cli.js +241 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +143 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +44 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
|
|
25
|
+
// src/cli.ts
|
|
26
|
+
var import_cac = __toESM(require("cac"));
|
|
27
|
+
|
|
28
|
+
// package.json
|
|
29
|
+
var package_default = {
|
|
30
|
+
name: "@o2b/meta",
|
|
31
|
+
version: "1.0.0-alpha.0",
|
|
32
|
+
description: "filetree generator for o2b",
|
|
33
|
+
main: "./dist/index.js",
|
|
34
|
+
module: "./dist/index.mjs",
|
|
35
|
+
types: "./dist/index.d.ts",
|
|
36
|
+
exports: {
|
|
37
|
+
".": {
|
|
38
|
+
types: "./dist/index.d.ts",
|
|
39
|
+
import: "./dist/index.mjs",
|
|
40
|
+
require: "./dist/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
bin: {
|
|
44
|
+
"o2b-meta": "./dist/cli.js"
|
|
45
|
+
},
|
|
46
|
+
scripts: {
|
|
47
|
+
build: "tsup",
|
|
48
|
+
test: "vitest",
|
|
49
|
+
"test:run": "vitest run"
|
|
50
|
+
},
|
|
51
|
+
keywords: [],
|
|
52
|
+
author: "goonco",
|
|
53
|
+
license: "ISC",
|
|
54
|
+
type: "commonjs",
|
|
55
|
+
files: [
|
|
56
|
+
"dist"
|
|
57
|
+
],
|
|
58
|
+
devDependencies: {
|
|
59
|
+
"@biomejs/biome": "2.3.10",
|
|
60
|
+
"@types/node": "^25.0.3",
|
|
61
|
+
"@vitest/ui": "^4.0.16",
|
|
62
|
+
tsup: "^8.5.1",
|
|
63
|
+
typescript: "^5.9.3",
|
|
64
|
+
vitest: "^4.0.16"
|
|
65
|
+
},
|
|
66
|
+
dependencies: {
|
|
67
|
+
cac: "^6.7.14",
|
|
68
|
+
"gray-matter": "^4.0.3",
|
|
69
|
+
ignore: "^7.0.5",
|
|
70
|
+
lilconfig: "^3.1.3"
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/core/sync/mirror.ts
|
|
75
|
+
var import_node_fs = require("fs");
|
|
76
|
+
var import_node_path = require("path");
|
|
77
|
+
function mirror(filetree, srcPath, destPath) {
|
|
78
|
+
function aux(filetree2) {
|
|
79
|
+
const from = (0, import_node_path.join)(srcPath, filetree2.path);
|
|
80
|
+
const to = (0, import_node_path.join)(destPath, filetree2.path);
|
|
81
|
+
if (filetree2.type === "dir") {
|
|
82
|
+
if (!(0, import_node_fs.existsSync)(to)) (0, import_node_fs.mkdirSync)(to, { recursive: true });
|
|
83
|
+
filetree2.files.forEach((file) => {
|
|
84
|
+
aux(file);
|
|
85
|
+
});
|
|
86
|
+
filetree2.dirs.forEach((dir) => {
|
|
87
|
+
aux(dir);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (filetree2.type === "file") {
|
|
91
|
+
(0, import_node_fs.copyFileSync)(from, to);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
aux(filetree);
|
|
95
|
+
generateFileTree(filetree, destPath);
|
|
96
|
+
}
|
|
97
|
+
function generateFileTree(filetree, destPath) {
|
|
98
|
+
const jsonFilePath = (0, import_node_path.join)(destPath, "o2bFileTree.json");
|
|
99
|
+
(0, import_node_fs.writeFileSync)(jsonFilePath, JSON.stringify(filetree, null, 2), "utf-8");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/core/sync/scan.ts
|
|
103
|
+
var import_node_fs4 = require("fs");
|
|
104
|
+
var import_node_path4 = require("path");
|
|
105
|
+
var import_gray_matter = __toESM(require("gray-matter"));
|
|
106
|
+
|
|
107
|
+
// src/utils/ignore.ts
|
|
108
|
+
var import_node_fs3 = require("fs");
|
|
109
|
+
var import_node_path3 = require("path");
|
|
110
|
+
var import_ignore = __toESM(require("ignore"));
|
|
111
|
+
|
|
112
|
+
// src/utils/path.ts
|
|
113
|
+
var import_node_fs2 = require("fs");
|
|
114
|
+
var import_node_path2 = require("path");
|
|
115
|
+
function toAbsPath(path) {
|
|
116
|
+
if (!(0, import_node_path2.isAbsolute)(path)) path = (0, import_node_path2.resolve)(path);
|
|
117
|
+
return path;
|
|
118
|
+
}
|
|
119
|
+
function toRelPath(from, to) {
|
|
120
|
+
return (0, import_node_path2.relative)(from, to);
|
|
121
|
+
}
|
|
122
|
+
function isObsidianDirectory(path) {
|
|
123
|
+
const stat = (0, import_node_fs2.lstatSync)(path);
|
|
124
|
+
if (!stat.isDirectory()) return false;
|
|
125
|
+
const obsMetaDir = (0, import_node_fs2.readdirSync)(path, { withFileTypes: true }).filter((node) => node.isDirectory()).filter((node) => node.name === ".obsidian");
|
|
126
|
+
if (obsMetaDir.length !== 1) return false;
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/utils/ignore.ts
|
|
131
|
+
var VaultIgnorer = class {
|
|
132
|
+
ign;
|
|
133
|
+
rootPath;
|
|
134
|
+
constructor(rootPath) {
|
|
135
|
+
this.rootPath = rootPath;
|
|
136
|
+
this.ign = (0, import_ignore.default)();
|
|
137
|
+
this.ign.add([".*"]);
|
|
138
|
+
}
|
|
139
|
+
load() {
|
|
140
|
+
const ignorePath = (0, import_node_path3.join)(this.rootPath, ".o2bignore");
|
|
141
|
+
if ((0, import_node_fs3.existsSync)(ignorePath))
|
|
142
|
+
this.ign.add((0, import_node_fs3.readFileSync)(ignorePath).toString());
|
|
143
|
+
}
|
|
144
|
+
ignore(path) {
|
|
145
|
+
if (path === this.rootPath) return false;
|
|
146
|
+
if (!(0, import_node_fs3.existsSync)(path)) throw new Error("somethings wrong!");
|
|
147
|
+
const stat = (0, import_node_fs3.lstatSync)(path);
|
|
148
|
+
const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
|
|
149
|
+
return this.ign.ignores(relPath);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/core/sync/scan.ts
|
|
154
|
+
function scan(rootPath, ign) {
|
|
155
|
+
function aux(path) {
|
|
156
|
+
if (ign == null ? void 0 : ign.ignore(path)) return null;
|
|
157
|
+
const stat = (0, import_node_fs4.lstatSync)(path);
|
|
158
|
+
const name = (0, import_node_path4.basename)(path);
|
|
159
|
+
if (stat.isDirectory()) {
|
|
160
|
+
const { dirs, files } = (0, import_node_fs4.readdirSync)(path).reduce(
|
|
161
|
+
(acc, entry) => {
|
|
162
|
+
const node = aux(toAbsPath((0, import_node_path4.join)(path, entry)));
|
|
163
|
+
if ((node == null ? void 0 : node.type) === "dir") acc.dirs.push(node);
|
|
164
|
+
if ((node == null ? void 0 : node.type) === "file") acc.files.push(node);
|
|
165
|
+
return acc;
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
dirs: [],
|
|
169
|
+
files: []
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
return {
|
|
173
|
+
path: toRelPath(rootPath, path),
|
|
174
|
+
name,
|
|
175
|
+
type: "dir",
|
|
176
|
+
dirs,
|
|
177
|
+
files
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (stat.isFile() && name.endsWith(".md")) {
|
|
181
|
+
return {
|
|
182
|
+
path: toRelPath(rootPath, path),
|
|
183
|
+
name,
|
|
184
|
+
type: "file",
|
|
185
|
+
frontmatter: getFrontmatter(path)
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
return aux(rootPath);
|
|
191
|
+
}
|
|
192
|
+
function getFrontmatter(path) {
|
|
193
|
+
const { data: srcFrontmatter } = (0, import_gray_matter.default)((0, import_node_fs4.readFileSync)(path, "utf-8"));
|
|
194
|
+
return {
|
|
195
|
+
title: (0, import_node_path4.basename)(path).replace(/\.md$/, ""),
|
|
196
|
+
description: "No description provided.",
|
|
197
|
+
last_modified: (0, import_node_fs4.lstatSync)(path).mtime.toLocaleDateString("sv-SE"),
|
|
198
|
+
// "sv-SE" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.
|
|
199
|
+
...srcFrontmatter
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/index.ts
|
|
204
|
+
function main(config) {
|
|
205
|
+
const { srcPath, destPath, ignore: ignore2 } = config;
|
|
206
|
+
if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
|
|
207
|
+
const ign = new VaultIgnorer(srcPath);
|
|
208
|
+
if (ignore2) ign.load();
|
|
209
|
+
const fileTree = scan(srcPath, ign);
|
|
210
|
+
if (fileTree === null) throw new Error("No content in vault");
|
|
211
|
+
mirror(fileTree, srcPath, destPath);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// src/cli.ts
|
|
215
|
+
var cli = (0, import_cac.default)("o2b-meta");
|
|
216
|
+
cli.command("<srcPath>", "target vault file").option("--destPath [destPath]", "dist", {
|
|
217
|
+
default: "./o2b"
|
|
218
|
+
}).option("--ignore", "read the .o2bIgnore if exists", {
|
|
219
|
+
default: true
|
|
220
|
+
}).option("--sync", "synchro", {
|
|
221
|
+
default: true
|
|
222
|
+
}).action((srcPath, option) => {
|
|
223
|
+
const { destPath, ignore: ignore2, sync } = option;
|
|
224
|
+
const startTime = performance.now();
|
|
225
|
+
if (sync) {
|
|
226
|
+
main({
|
|
227
|
+
srcPath: toAbsPath(srcPath),
|
|
228
|
+
destPath: toAbsPath(destPath),
|
|
229
|
+
ignore: ignore2
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const endTime = performance.now();
|
|
233
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
234
|
+
console.log(`
|
|
235
|
+
\u2705 Build Success!`);
|
|
236
|
+
console.log(` Time: ${duration}ms`);
|
|
237
|
+
});
|
|
238
|
+
cli.help();
|
|
239
|
+
cli.version(package_default.version);
|
|
240
|
+
cli.parse();
|
|
241
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../package.json","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/index.ts"],"sourcesContent":["import cac from \"cac\";\nimport pkg from \"../package.json\";\nimport main from \".\";\nimport { toAbsPath } from \"./utils\";\n\nconst cli = cac(\"o2b-meta\");\n\ncli\n\t.command(\"<srcPath>\", \"target vault file\")\n\t.option(\"--destPath [destPath]\", \"dist\", {\n\t\tdefault: \"./o2b\",\n\t})\n\t.option(\"--ignore\", \"read the .o2bIgnore if exists\", {\n\t\tdefault: true,\n\t})\n\t.option(\"--sync\", \"synchro\", {\n\t\tdefault: true,\n\t})\n\t.action((srcPath, option) => {\n\t\tconst { destPath, ignore, sync } = option;\n\n\t\tconst startTime = performance.now();\n\n\t\tif (sync) {\n\t\t\tmain({\n\t\t\t\tsrcPath: toAbsPath(srcPath),\n\t\t\t\tdestPath: toAbsPath(destPath),\n\t\t\t\tignore,\n\t\t\t});\n\t\t}\n\n\t\tconst endTime = performance.now();\n\t\tconst duration = (endTime - startTime).toFixed(2); // 소수점 2자리까지\n\n\t\tconsole.log(`\\n✅ Build Success!`);\n\t\tconsole.log(` Time: ${duration}ms`);\n\t\t// console.log(` Dest: ${config.destPath}\\n`);\n\t});\n\ncli.help();\ncli.version(pkg.version);\n\n// production에 대한 에러처리\ncli.parse();\n","{\n \"name\": \"@o2b/meta\",\n \"version\": \"1.0.0-alpha.0\",\n \"description\": \"filetree generator for o2b\",\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.js\"\n }\n },\n \"bin\": {\n \"o2b-meta\": \"./dist/cli.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\"\n },\n \"keywords\": [],\n \"author\": \"goonco\",\n \"license\": \"ISC\",\n \"type\": \"commonjs\",\n \"files\": [\n \"dist\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.3.10\",\n \"@types/node\": \"^25.0.3\",\n \"@vitest/ui\": \"^4.0.16\",\n \"tsup\": \"^8.5.1\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.0.16\"\n },\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"gray-matter\": \"^4.0.3\",\n \"ignore\": \"^7.0.5\",\n \"lilconfig\": \"^3.1.3\"\n }\n}\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n\tif (!isAbsolute(path)) path = resolve(path);\n\treturn path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n\treturn relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n\tconst stat = lstatSync(path);\n\n\tif (!stat.isDirectory()) return false;\n\n\tconst obsMetaDir = readdirSync(path, { withFileTypes: true })\n\t\t.filter((node) => node.isDirectory())\n\t\t.filter((node) => node.name === \".obsidian\");\n\n\tif (obsMetaDir.length !== 1) return false;\n\n\treturn true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function main(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","ignore","matter","ignore","cac","ignore"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare const __brand: unique symbol;
|
|
2
|
+
type Branded<K, T> = K & {
|
|
3
|
+
[__brand]: T;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type AbsPath = Branded<string, "abspath">;
|
|
7
|
+
|
|
8
|
+
type Config = {
|
|
9
|
+
srcPath: AbsPath;
|
|
10
|
+
destPath: AbsPath;
|
|
11
|
+
ignore: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare function main(config: Config): void;
|
|
15
|
+
|
|
16
|
+
export { main as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare const __brand: unique symbol;
|
|
2
|
+
type Branded<K, T> = K & {
|
|
3
|
+
[__brand]: T;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type AbsPath = Branded<string, "abspath">;
|
|
7
|
+
|
|
8
|
+
type Config = {
|
|
9
|
+
srcPath: AbsPath;
|
|
10
|
+
destPath: AbsPath;
|
|
11
|
+
ignore: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
declare function main(config: Config): void;
|
|
15
|
+
|
|
16
|
+
export { main as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/index.ts
|
|
30
|
+
var index_exports = {};
|
|
31
|
+
__export(index_exports, {
|
|
32
|
+
default: () => main
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/core/sync/mirror.ts
|
|
37
|
+
var import_node_fs = require("fs");
|
|
38
|
+
var import_node_path = require("path");
|
|
39
|
+
function mirror(filetree, srcPath, destPath) {
|
|
40
|
+
function aux(filetree2) {
|
|
41
|
+
const from = (0, import_node_path.join)(srcPath, filetree2.path);
|
|
42
|
+
const to = (0, import_node_path.join)(destPath, filetree2.path);
|
|
43
|
+
if (filetree2.type === "dir") {
|
|
44
|
+
if (!(0, import_node_fs.existsSync)(to)) (0, import_node_fs.mkdirSync)(to, { recursive: true });
|
|
45
|
+
filetree2.files.forEach((file) => {
|
|
46
|
+
aux(file);
|
|
47
|
+
});
|
|
48
|
+
filetree2.dirs.forEach((dir) => {
|
|
49
|
+
aux(dir);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (filetree2.type === "file") {
|
|
53
|
+
(0, import_node_fs.copyFileSync)(from, to);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
aux(filetree);
|
|
57
|
+
generateFileTree(filetree, destPath);
|
|
58
|
+
}
|
|
59
|
+
function generateFileTree(filetree, destPath) {
|
|
60
|
+
const jsonFilePath = (0, import_node_path.join)(destPath, "o2bFileTree.json");
|
|
61
|
+
(0, import_node_fs.writeFileSync)(jsonFilePath, JSON.stringify(filetree, null, 2), "utf-8");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/core/sync/scan.ts
|
|
65
|
+
var import_node_fs4 = require("fs");
|
|
66
|
+
var import_node_path4 = require("path");
|
|
67
|
+
var import_gray_matter = __toESM(require("gray-matter"));
|
|
68
|
+
|
|
69
|
+
// src/utils/ignore.ts
|
|
70
|
+
var import_node_fs3 = require("fs");
|
|
71
|
+
var import_node_path3 = require("path");
|
|
72
|
+
var import_ignore = __toESM(require("ignore"));
|
|
73
|
+
|
|
74
|
+
// src/utils/path.ts
|
|
75
|
+
var import_node_fs2 = require("fs");
|
|
76
|
+
var import_node_path2 = require("path");
|
|
77
|
+
function toAbsPath(path) {
|
|
78
|
+
if (!(0, import_node_path2.isAbsolute)(path)) path = (0, import_node_path2.resolve)(path);
|
|
79
|
+
return path;
|
|
80
|
+
}
|
|
81
|
+
function toRelPath(from, to) {
|
|
82
|
+
return (0, import_node_path2.relative)(from, to);
|
|
83
|
+
}
|
|
84
|
+
function isObsidianDirectory(path) {
|
|
85
|
+
const stat = (0, import_node_fs2.lstatSync)(path);
|
|
86
|
+
if (!stat.isDirectory()) return false;
|
|
87
|
+
const obsMetaDir = (0, import_node_fs2.readdirSync)(path, { withFileTypes: true }).filter((node) => node.isDirectory()).filter((node) => node.name === ".obsidian");
|
|
88
|
+
if (obsMetaDir.length !== 1) return false;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/utils/ignore.ts
|
|
93
|
+
var VaultIgnorer = class {
|
|
94
|
+
ign;
|
|
95
|
+
rootPath;
|
|
96
|
+
constructor(rootPath) {
|
|
97
|
+
this.rootPath = rootPath;
|
|
98
|
+
this.ign = (0, import_ignore.default)();
|
|
99
|
+
this.ign.add([".*"]);
|
|
100
|
+
}
|
|
101
|
+
load() {
|
|
102
|
+
const ignorePath = (0, import_node_path3.join)(this.rootPath, ".o2bignore");
|
|
103
|
+
if ((0, import_node_fs3.existsSync)(ignorePath))
|
|
104
|
+
this.ign.add((0, import_node_fs3.readFileSync)(ignorePath).toString());
|
|
105
|
+
}
|
|
106
|
+
ignore(path) {
|
|
107
|
+
if (path === this.rootPath) return false;
|
|
108
|
+
if (!(0, import_node_fs3.existsSync)(path)) throw new Error("somethings wrong!");
|
|
109
|
+
const stat = (0, import_node_fs3.lstatSync)(path);
|
|
110
|
+
const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
|
|
111
|
+
return this.ign.ignores(relPath);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/core/sync/scan.ts
|
|
116
|
+
function scan(rootPath, ign) {
|
|
117
|
+
function aux(path) {
|
|
118
|
+
if (ign == null ? void 0 : ign.ignore(path)) return null;
|
|
119
|
+
const stat = (0, import_node_fs4.lstatSync)(path);
|
|
120
|
+
const name = (0, import_node_path4.basename)(path);
|
|
121
|
+
if (stat.isDirectory()) {
|
|
122
|
+
const { dirs, files } = (0, import_node_fs4.readdirSync)(path).reduce(
|
|
123
|
+
(acc, entry) => {
|
|
124
|
+
const node = aux(toAbsPath((0, import_node_path4.join)(path, entry)));
|
|
125
|
+
if ((node == null ? void 0 : node.type) === "dir") acc.dirs.push(node);
|
|
126
|
+
if ((node == null ? void 0 : node.type) === "file") acc.files.push(node);
|
|
127
|
+
return acc;
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
dirs: [],
|
|
131
|
+
files: []
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
return {
|
|
135
|
+
path: toRelPath(rootPath, path),
|
|
136
|
+
name,
|
|
137
|
+
type: "dir",
|
|
138
|
+
dirs,
|
|
139
|
+
files
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (stat.isFile() && name.endsWith(".md")) {
|
|
143
|
+
return {
|
|
144
|
+
path: toRelPath(rootPath, path),
|
|
145
|
+
name,
|
|
146
|
+
type: "file",
|
|
147
|
+
frontmatter: getFrontmatter(path)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
return aux(rootPath);
|
|
153
|
+
}
|
|
154
|
+
function getFrontmatter(path) {
|
|
155
|
+
const { data: srcFrontmatter } = (0, import_gray_matter.default)((0, import_node_fs4.readFileSync)(path, "utf-8"));
|
|
156
|
+
return {
|
|
157
|
+
title: (0, import_node_path4.basename)(path).replace(/\.md$/, ""),
|
|
158
|
+
description: "No description provided.",
|
|
159
|
+
last_modified: (0, import_node_fs4.lstatSync)(path).mtime.toLocaleDateString("sv-SE"),
|
|
160
|
+
// "sv-SE" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.
|
|
161
|
+
...srcFrontmatter
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/index.ts
|
|
166
|
+
function main(config) {
|
|
167
|
+
const { srcPath, destPath, ignore: ignore2 } = config;
|
|
168
|
+
if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
|
|
169
|
+
const ign = new VaultIgnorer(srcPath);
|
|
170
|
+
if (ignore2) ign.load();
|
|
171
|
+
const fileTree = scan(srcPath, ign);
|
|
172
|
+
if (fileTree === null) throw new Error("No content in vault");
|
|
173
|
+
mirror(fileTree, srcPath, destPath);
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts"],"sourcesContent":["import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function main(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n","import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n\tif (!isAbsolute(path)) path = resolve(path);\n\treturn path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n\treturn relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n\tconst stat = lstatSync(path);\n\n\tif (!stat.isDirectory()) return false;\n\n\tconst obsMetaDir = readdirSync(path, { withFileTypes: true })\n\t\t.filter((node) => node.isDirectory())\n\t\t.filter((node) => node.name === \".obsidian\");\n\n\tif (obsMetaDir.length !== 1) return false;\n\n\treturn true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n"],"mappings":"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","names":["filetree","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","ignore","matter","ignore"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// src/core/sync/mirror.ts
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
function mirror(filetree, srcPath, destPath) {
|
|
5
|
+
function aux(filetree2) {
|
|
6
|
+
const from = join(srcPath, filetree2.path);
|
|
7
|
+
const to = join(destPath, filetree2.path);
|
|
8
|
+
if (filetree2.type === "dir") {
|
|
9
|
+
if (!existsSync(to)) mkdirSync(to, { recursive: true });
|
|
10
|
+
filetree2.files.forEach((file) => {
|
|
11
|
+
aux(file);
|
|
12
|
+
});
|
|
13
|
+
filetree2.dirs.forEach((dir) => {
|
|
14
|
+
aux(dir);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (filetree2.type === "file") {
|
|
18
|
+
copyFileSync(from, to);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
aux(filetree);
|
|
22
|
+
generateFileTree(filetree, destPath);
|
|
23
|
+
}
|
|
24
|
+
function generateFileTree(filetree, destPath) {
|
|
25
|
+
const jsonFilePath = join(destPath, "o2bFileTree.json");
|
|
26
|
+
writeFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), "utf-8");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/core/sync/scan.ts
|
|
30
|
+
import { lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
|
|
31
|
+
import { basename, join as join3 } from "path";
|
|
32
|
+
import matter from "gray-matter";
|
|
33
|
+
|
|
34
|
+
// src/utils/ignore.ts
|
|
35
|
+
import { existsSync as existsSync2, lstatSync as lstatSync2, readFileSync } from "fs";
|
|
36
|
+
import { join as join2 } from "path";
|
|
37
|
+
import ignore from "ignore";
|
|
38
|
+
|
|
39
|
+
// src/utils/path.ts
|
|
40
|
+
import { lstatSync, readdirSync } from "fs";
|
|
41
|
+
import { isAbsolute, relative, resolve } from "path";
|
|
42
|
+
function toAbsPath(path) {
|
|
43
|
+
if (!isAbsolute(path)) path = resolve(path);
|
|
44
|
+
return path;
|
|
45
|
+
}
|
|
46
|
+
function toRelPath(from, to) {
|
|
47
|
+
return relative(from, to);
|
|
48
|
+
}
|
|
49
|
+
function isObsidianDirectory(path) {
|
|
50
|
+
const stat = lstatSync(path);
|
|
51
|
+
if (!stat.isDirectory()) return false;
|
|
52
|
+
const obsMetaDir = readdirSync(path, { withFileTypes: true }).filter((node) => node.isDirectory()).filter((node) => node.name === ".obsidian");
|
|
53
|
+
if (obsMetaDir.length !== 1) return false;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/utils/ignore.ts
|
|
58
|
+
var VaultIgnorer = class {
|
|
59
|
+
ign;
|
|
60
|
+
rootPath;
|
|
61
|
+
constructor(rootPath) {
|
|
62
|
+
this.rootPath = rootPath;
|
|
63
|
+
this.ign = ignore();
|
|
64
|
+
this.ign.add([".*"]);
|
|
65
|
+
}
|
|
66
|
+
load() {
|
|
67
|
+
const ignorePath = join2(this.rootPath, ".o2bignore");
|
|
68
|
+
if (existsSync2(ignorePath))
|
|
69
|
+
this.ign.add(readFileSync(ignorePath).toString());
|
|
70
|
+
}
|
|
71
|
+
ignore(path) {
|
|
72
|
+
if (path === this.rootPath) return false;
|
|
73
|
+
if (!existsSync2(path)) throw new Error("somethings wrong!");
|
|
74
|
+
const stat = lstatSync2(path);
|
|
75
|
+
const relPath = toRelPath(this.rootPath, path) + (stat.isDirectory() ? "/" : "");
|
|
76
|
+
return this.ign.ignores(relPath);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/core/sync/scan.ts
|
|
81
|
+
function scan(rootPath, ign) {
|
|
82
|
+
function aux(path) {
|
|
83
|
+
if (ign == null ? void 0 : ign.ignore(path)) return null;
|
|
84
|
+
const stat = lstatSync3(path);
|
|
85
|
+
const name = basename(path);
|
|
86
|
+
if (stat.isDirectory()) {
|
|
87
|
+
const { dirs, files } = readdirSync2(path).reduce(
|
|
88
|
+
(acc, entry) => {
|
|
89
|
+
const node = aux(toAbsPath(join3(path, entry)));
|
|
90
|
+
if ((node == null ? void 0 : node.type) === "dir") acc.dirs.push(node);
|
|
91
|
+
if ((node == null ? void 0 : node.type) === "file") acc.files.push(node);
|
|
92
|
+
return acc;
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
dirs: [],
|
|
96
|
+
files: []
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
return {
|
|
100
|
+
path: toRelPath(rootPath, path),
|
|
101
|
+
name,
|
|
102
|
+
type: "dir",
|
|
103
|
+
dirs,
|
|
104
|
+
files
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (stat.isFile() && name.endsWith(".md")) {
|
|
108
|
+
return {
|
|
109
|
+
path: toRelPath(rootPath, path),
|
|
110
|
+
name,
|
|
111
|
+
type: "file",
|
|
112
|
+
frontmatter: getFrontmatter(path)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return aux(rootPath);
|
|
118
|
+
}
|
|
119
|
+
function getFrontmatter(path) {
|
|
120
|
+
const { data: srcFrontmatter } = matter(readFileSync2(path, "utf-8"));
|
|
121
|
+
return {
|
|
122
|
+
title: basename(path).replace(/\.md$/, ""),
|
|
123
|
+
description: "No description provided.",
|
|
124
|
+
last_modified: lstatSync3(path).mtime.toLocaleDateString("sv-SE"),
|
|
125
|
+
// "sv-SE" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.
|
|
126
|
+
...srcFrontmatter
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/index.ts
|
|
131
|
+
function main(config) {
|
|
132
|
+
const { srcPath, destPath, ignore: ignore2 } = config;
|
|
133
|
+
if (!isObsidianDirectory(srcPath)) throw new Error("Not a obsidian vault");
|
|
134
|
+
const ign = new VaultIgnorer(srcPath);
|
|
135
|
+
if (ignore2) ign.load();
|
|
136
|
+
const fileTree = scan(srcPath, ign);
|
|
137
|
+
if (fileTree === null) throw new Error("No content in vault");
|
|
138
|
+
mirror(fileTree, srcPath, destPath);
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
main as default
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/sync/mirror.ts","../src/core/sync/scan.ts","../src/utils/ignore.ts","../src/utils/path.ts","../src/index.ts"],"sourcesContent":["import { copyFileSync, existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AbsPath, FileTree } from \"../../types\";\n\nexport function mirror(\n\tfiletree: FileTree,\n\tsrcPath: AbsPath,\n\tdestPath: AbsPath,\n) {\n\tfunction aux(filetree: FileTree) {\n\t\tconst from = join(srcPath, filetree.path);\n\t\tconst to = join(destPath, filetree.path);\n\n\t\tif (filetree.type === \"dir\") {\n\t\t\tif (!existsSync(to)) mkdirSync(to, { recursive: true });\n\n\t\t\tfiletree.files.forEach((file) => {\n\t\t\t\taux(file);\n\t\t\t});\n\n\t\t\tfiletree.dirs.forEach((dir) => {\n\t\t\t\taux(dir);\n\t\t\t});\n\t\t}\n\n\t\tif (filetree.type === \"file\") {\n\t\t\tcopyFileSync(from, to);\n\t\t}\n\t}\n\n\taux(filetree);\n\tgenerateFileTree(filetree, destPath);\n}\n\nfunction generateFileTree(filetree: FileTree, destPath: AbsPath) {\n\tconst jsonFilePath = join(destPath, \"o2bFileTree.json\");\n\twriteFileSync(jsonFilePath, JSON.stringify(filetree, null, 2), \"utf-8\");\n}\n","import { lstatSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\nimport matter from \"gray-matter\";\nimport type {\n\tAbsPath,\n\tDirNode,\n\tFileNode,\n\tFileTree,\n\tFrontmatter,\n} from \"../../types\";\nimport { toAbsPath, toRelPath, type VaultIgnorer } from \"../../utils\";\n\nexport function scan(rootPath: AbsPath, ign: VaultIgnorer): FileTree | null {\n\tfunction aux(path: AbsPath): FileTree | null {\n\t\tif (ign?.ignore(path)) return null;\n\n\t\tconst stat = lstatSync(path);\n\t\tconst name = basename(path);\n\n\t\tif (stat.isDirectory()) {\n\t\t\tconst { dirs, files } = readdirSync(path).reduce(\n\t\t\t\t(acc, entry) => {\n\t\t\t\t\tconst node = aux(toAbsPath(join(path, entry)));\n\n\t\t\t\t\tif (node?.type === \"dir\") acc.dirs.push(node);\n\t\t\t\t\tif (node?.type === \"file\") acc.files.push(node);\n\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdirs: [] as DirNode[],\n\t\t\t\t\tfiles: [] as FileNode[],\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"dir\",\n\t\t\t\tdirs,\n\t\t\t\tfiles,\n\t\t\t};\n\t\t}\n\n\t\tif (stat.isFile() && name.endsWith(\".md\")) {\n\t\t\treturn {\n\t\t\t\tpath: toRelPath(rootPath, path),\n\t\t\t\tname,\n\t\t\t\ttype: \"file\",\n\t\t\t\tfrontmatter: getFrontmatter(path),\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\treturn aux(rootPath);\n}\n\nfunction getFrontmatter(path: AbsPath): Frontmatter {\n\tconst { data: srcFrontmatter } = matter(readFileSync(path, \"utf-8\"));\n\treturn {\n\t\ttitle: basename(path).replace(/\\.md$/, \"\"),\n\t\tdescription: \"No description provided.\",\n\t\tlast_modified: lstatSync(path).mtime.toLocaleDateString(\"sv-SE\"), // \"sv-SE\" (스웨덴어)는 YYYY-MM-DD 형식으로 출력되는 유명한 트릭입니다.\n\t\t...srcFrontmatter,\n\t};\n}\n","import { existsSync, lstatSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore, { type Ignore } from \"ignore\";\nimport type { AbsPath } from \"../types\";\nimport { toRelPath } from \"./path\";\n\nexport class VaultIgnorer {\n\tprivate ign: Ignore;\n\tprivate rootPath: AbsPath;\n\n\tconstructor(rootPath: AbsPath) {\n\t\tthis.rootPath = rootPath;\n\t\tthis.ign = ignore();\n\n\t\tthis.ign.add([\".*\"]);\n\t}\n\n\tpublic load() {\n\t\tconst ignorePath = join(this.rootPath, \".o2bignore\");\n\t\tif (existsSync(ignorePath))\n\t\t\tthis.ign.add(readFileSync(ignorePath).toString());\n\t}\n\n\tpublic ignore(path: AbsPath): boolean {\n\t\tif (path === this.rootPath) return false;\n\n\t\tif (!existsSync(path)) throw new Error(\"somethings wrong!\");\n\n\t\tconst stat = lstatSync(path);\n\n\t\tconst relPath =\n\t\t\ttoRelPath(this.rootPath, path) + (stat.isDirectory() ? \"/\" : \"\");\n\n\t\treturn this.ign.ignores(relPath);\n\t}\n}\n","import { lstatSync, readdirSync } from \"node:fs\";\nimport { isAbsolute, relative, resolve } from \"node:path\";\nimport type { AbsPath, RelPath } from \"../types\";\n\nfunction toAbsPath(path: string): AbsPath {\n\tif (!isAbsolute(path)) path = resolve(path);\n\treturn path as AbsPath;\n}\n\nfunction toRelPath(from: AbsPath, to: AbsPath): RelPath {\n\treturn relative(from, to) as RelPath;\n}\n\nfunction isObsidianDirectory(path: AbsPath) {\n\tconst stat = lstatSync(path);\n\n\tif (!stat.isDirectory()) return false;\n\n\tconst obsMetaDir = readdirSync(path, { withFileTypes: true })\n\t\t.filter((node) => node.isDirectory())\n\t\t.filter((node) => node.name === \".obsidian\");\n\n\tif (obsMetaDir.length !== 1) return false;\n\n\treturn true;\n}\n\nexport { toAbsPath, toRelPath, isObsidianDirectory };\n","import { mirror, scan } from \"./core/sync\";\nimport type { Config } from \"./types\";\nimport { isObsidianDirectory, VaultIgnorer } from \"./utils\";\n\nexport default function main(config: Config) {\n const { srcPath, destPath, ignore } = config;\n if (!isObsidianDirectory(srcPath)) throw new Error(\"Not a obsidian vault\");\n\n const ign = new VaultIgnorer(srcPath);\n if (ignore) ign.load();\n\n const fileTree = scan(srcPath, ign);\n if (fileTree === null) throw new Error(\"No content in vault\");\n\n mirror(fileTree, srcPath, destPath);\n}\n"],"mappings":"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","names":["filetree","lstatSync","readdirSync","readFileSync","join","existsSync","lstatSync","join","join","existsSync","lstatSync","lstatSync","readdirSync","join","readFileSync","ignore"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@o2b/meta",
|
|
3
|
+
"version": "1.0.0-dev.0",
|
|
4
|
+
"description": "filetree generator for o2b",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"o2b-meta": "./dist/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"test:run": "vitest run"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [],
|
|
24
|
+
"author": "goonco",
|
|
25
|
+
"license": "ISC",
|
|
26
|
+
"type": "commonjs",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@biomejs/biome": "2.3.10",
|
|
32
|
+
"@types/node": "^25.0.3",
|
|
33
|
+
"@vitest/ui": "^4.0.16",
|
|
34
|
+
"tsup": "^8.5.1",
|
|
35
|
+
"typescript": "^5.9.3",
|
|
36
|
+
"vitest": "^4.0.16"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"cac": "^6.7.14",
|
|
40
|
+
"gray-matter": "^4.0.3",
|
|
41
|
+
"ignore": "^7.0.5",
|
|
42
|
+
"lilconfig": "^3.1.3"
|
|
43
|
+
}
|
|
44
|
+
}
|