@notatki/cli 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Aliaksandr Radzivanovich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ export declare function exportCmd({ dir, out, preview }: {
2
+ dir: string;
3
+ out: string;
4
+ preview: boolean;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=cmd-export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-export.d.ts","sourceRoot":"","sources":["../src/cmd-export.ts"],"names":[],"mappings":"AAMA,wBAAsB,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BpH"}
@@ -0,0 +1,37 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { exportNotes, NoteParser } from "@notatki/core";
4
+ import { generatePreview } from "@notatki/preview";
5
+ import { findNoteFiles } from "./io.js";
6
+ export async function exportCmd({ dir, out, preview }) {
7
+ const parser = new NoteParser();
8
+ console.log(`Scanning directory "${dir}"...`);
9
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
10
+ for (const path of modelPaths) {
11
+ console.log(`Parsing models file "${path}"...`);
12
+ const text = await readFile(path, "utf-8");
13
+ parser.parseModels(path, text);
14
+ }
15
+ for (const path of notePaths) {
16
+ console.log(`Parsing notes file "${path}"...`);
17
+ const text = await readFile(path, "utf-8");
18
+ parser.parseNotes(path, text);
19
+ }
20
+ parser.checkDuplicates();
21
+ parser.checkErrors();
22
+ const { notes } = parser;
23
+ console.log(`Parsed ${notes.length} note(s).`);
24
+ if (notes.length > 0) {
25
+ await writeFile(out, exportNotes(notes));
26
+ console.log(`Exported notes to "${out}".`);
27
+ if (preview) {
28
+ const previewOut = path.format({ ...path.parse(out), base: undefined, ext: ".html" });
29
+ await writeFile(previewOut, generatePreview(notes));
30
+ console.log(`Generated preview to "${previewOut}".`);
31
+ }
32
+ }
33
+ else {
34
+ console.warn(`No notes found in "${dir}".`);
35
+ }
36
+ }
37
+ //# sourceMappingURL=cmd-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-export.js","sourceRoot":"","sources":["../src/cmd-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAkD;IACnG,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,MAAM,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,CAAC,eAAe,EAAE,CAAC;IACzB,MAAM,CAAC,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;QAC3C,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;YACtF,MAAM,SAAS,CAAC,UAAU,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,yBAAyB,UAAU,IAAI,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function insertIdCmd({ dir }: {
2
+ dir: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=cmd-insert-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-insert-id.d.ts","sourceRoot":"","sources":["../src/cmd-insert-id.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBzE"}
@@ -0,0 +1,22 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { insertNoteId, NoteParser, printNoteNodes } from "@notatki/core";
3
+ import { findNoteFiles } from "./io.js";
4
+ export async function insertIdCmd({ dir }) {
5
+ console.log(`Scanning directory "${dir}"...`);
6
+ const { notePaths } = await findNoteFiles(dir);
7
+ for (const path of notePaths) {
8
+ const parser = new NoteParser();
9
+ console.log(`Parsing notes file "${path}"...`);
10
+ const text = await readFile(path, "utf-8");
11
+ const nodes = parser.parseNoteNodes(path, text);
12
+ if (parser.errors.length > 0) {
13
+ console.error(`Parse error.`);
14
+ }
15
+ else {
16
+ if (insertNoteId(nodes)) {
17
+ await writeFile(path, printNoteNodes(nodes));
18
+ }
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=cmd-insert-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-insert-id.js","sourceRoot":"","sources":["../src/cmd-insert-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAE,GAAG,EAAmB;IACxD,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function reformatCmd({ dir }: {
2
+ dir: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=cmd-reformat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-reformat.d.ts","sourceRoot":"","sources":["../src/cmd-reformat.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBzE"}
@@ -0,0 +1,32 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { NoteParser, printModelNodes, printNoteNodes, reformatModelNodes, reformatNoteNodes } from "@notatki/core";
3
+ import { findNoteFiles } from "./io.js";
4
+ export async function reformatCmd({ dir }) {
5
+ console.log(`Scanning directory "${dir}"...`);
6
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
7
+ for (const path of modelPaths) {
8
+ const parser = new NoteParser();
9
+ console.log(`Parsing models file "${path}"...`);
10
+ const text = await readFile(path, "utf-8");
11
+ const nodes = parser.parseModelNodes(path, text);
12
+ if (parser.errors.length > 0) {
13
+ console.error(`Parse error.`);
14
+ }
15
+ else {
16
+ await writeFile(path, printModelNodes(reformatModelNodes(nodes)));
17
+ }
18
+ }
19
+ for (const path of notePaths) {
20
+ const parser = new NoteParser();
21
+ console.log(`Parsing notes file "${path}"...`);
22
+ const text = await readFile(path, "utf-8");
23
+ const nodes = parser.parseNoteNodes(path, text);
24
+ if (parser.errors.length > 0) {
25
+ console.error(`Parse error.`);
26
+ }
27
+ else {
28
+ await writeFile(path, printNoteNodes(reformatNoteNodes(nodes)));
29
+ }
30
+ }
31
+ }
32
+ //# sourceMappingURL=cmd-reformat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-reformat.js","sourceRoot":"","sources":["../src/cmd-reformat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACnH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAE,GAAG,EAAmB;IACxD,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,MAAM,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,CAAC,IAAI,EAAE,cAAc,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function syncCmd({ dir }: {
2
+ dir: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=cmd-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-sync.d.ts","sourceRoot":"","sources":["../src/cmd-sync.ts"],"names":[],"mappings":"AAKA,wBAAsB,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBrE"}
@@ -0,0 +1,30 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { NoteParser } from "@notatki/core";
3
+ import { synchronizeNotes } from "@notatki/sync";
4
+ import { findNoteFiles } from "./io.js";
5
+ export async function syncCmd({ dir }) {
6
+ const parser = new NoteParser();
7
+ console.log(`Scanning directory "${dir}"...`);
8
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
9
+ for (const path of modelPaths) {
10
+ console.log(`Parsing models file "${path}"...`);
11
+ const text = await readFile(path, "utf-8");
12
+ parser.parseModels(path, text);
13
+ }
14
+ for (const path of notePaths) {
15
+ console.log(`Parsing notes file "${path}"...`);
16
+ const text = await readFile(path, "utf-8");
17
+ parser.parseNotes(path, text);
18
+ }
19
+ parser.checkDuplicates();
20
+ parser.checkErrors();
21
+ const { notes } = parser;
22
+ console.log(`Parsed ${notes.length} note(s).`);
23
+ if (notes.length > 0) {
24
+ await synchronizeNotes(notes, {});
25
+ }
26
+ else {
27
+ console.warn(`No notes found in "${dir}".`);
28
+ }
29
+ }
30
+ //# sourceMappingURL=cmd-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd-sync.js","sourceRoot":"","sources":["../src/cmd-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,EAAE,GAAG,EAAmB;IACpD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,MAAM,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,MAAM,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,CAAC,eAAe,EAAE,CAAC;IACzB,MAAM,CAAC,WAAW,EAAE,CAAC;IACrB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,gBAAgB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./cmd-export.js";
2
+ export * from "./cmd-insert-id.js";
3
+ export * from "./io.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./cmd-export.js";
2
+ export * from "./cmd-insert-id.js";
3
+ export * from "./io.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC"}
package/dist/io.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare function pathTo(...file: string[]): string;
2
+ export declare function findNoteFiles(dir: string, exclude?: readonly string[]): Promise<{
3
+ notePaths: string[];
4
+ modelPaths: string[];
5
+ }>;
6
+ //# sourceMappingURL=io.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"AAKA,wBAAgB,MAAM,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAEhD;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,SAAS,MAAM,EAAwD;;;GAmBjF"}
package/dist/io.js ADDED
@@ -0,0 +1,26 @@
1
+ import { glob } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ const cwd = process.cwd();
4
+ export function pathTo(...file) {
5
+ return resolve(cwd, ...file);
6
+ }
7
+ export async function findNoteFiles(dir, exclude = ["**/.git", "**/.hg", "**/.svn", "**/node_modules"]) {
8
+ const notePaths = [];
9
+ const modelPaths = [];
10
+ const cwd = pathTo(dir);
11
+ for await (const item of glob("**/*.{note,model}", { cwd, exclude })) {
12
+ const path = join(cwd, item);
13
+ switch (true) {
14
+ case item.endsWith(".note"):
15
+ notePaths.push(path);
16
+ break;
17
+ case item.endsWith(".model"):
18
+ modelPaths.push(path);
19
+ break;
20
+ }
21
+ }
22
+ notePaths.sort();
23
+ modelPaths.sort();
24
+ return { notePaths, modelPaths };
25
+ }
26
+ //# sourceMappingURL=io.js.map
package/dist/io.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE1B,MAAM,UAAU,MAAM,CAAC,GAAG,IAAc;IACtC,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,UAA6B,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,CAAC;IAEhF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,mBAAmB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACzB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,MAAM;YACR,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC1B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,MAAM;QACV,CAAC;IACH,CAAC;IACD,SAAS,CAAC,IAAI,EAAE,CAAC;IACjB,UAAU,CAAC,IAAI,EAAE,CAAC;IAClB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":""}
@@ -0,0 +1,57 @@
1
+ import { styleText } from "node:util";
2
+ import { ParseError } from "@notatki/core";
3
+ import { Command } from "commander";
4
+ import { exportCmd } from "./cmd-export.js";
5
+ import { insertIdCmd } from "./cmd-insert-id.js";
6
+ import { reformatCmd } from "./cmd-reformat.js";
7
+ import { syncCmd } from "./cmd-sync.js";
8
+ import { pathTo } from "./io.js";
9
+ const program = new Command();
10
+ program.configureOutput({
11
+ outputError: (str, write) => write(styleText("red", str)),
12
+ });
13
+ program
14
+ .name("notatki")
15
+ .description("Build Anki notes from text files written in a human readable format.")
16
+ .version("0.0.0");
17
+ program
18
+ .command("sync")
19
+ .description("build and synchronize notes with the desktop Anki application through the Anki Connect protocol")
20
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
21
+ .action(syncCmd);
22
+ program
23
+ .command("export")
24
+ .description("build and export notes to a file in the Anki notes file format")
25
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
26
+ .option("--out <file>", "output file name", parsePath, parsePath("notes.txt"))
27
+ .option("--preview", "whether to generate a preview HTML file", false)
28
+ .action(exportCmd);
29
+ program
30
+ .command("insert-id")
31
+ .description("insert unique note id to each note")
32
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
33
+ .action(insertIdCmd);
34
+ program
35
+ .command("reformat")
36
+ .description("reformat note files")
37
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
38
+ .action(reformatCmd);
39
+ try {
40
+ program.parse();
41
+ }
42
+ catch (err) {
43
+ if (err instanceof ParseError) {
44
+ const lines = [];
45
+ for (const { message, location } of err.errors) {
46
+ lines.push(`${String(location.source)}:${location.start.line}:${location.start.column}: ${message}`);
47
+ }
48
+ program.error(lines.join("\n"));
49
+ }
50
+ else {
51
+ throw err;
52
+ }
53
+ }
54
+ function parsePath(value) {
55
+ return pathTo(value);
56
+ }
57
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO,CAAC,eAAe,CAAC;IACtB,WAAW,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;CAC1D,CAAC,CAAC;AAEH,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,sEAAsE,CAAC;KACnF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,iGAAiG,CAAC;KAC9G,MAAM,CAAC,aAAa,EAAE,8CAA8C,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;KAChG,MAAM,CAAC,OAAO,CAAC,CAAC;AAEnB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,aAAa,EAAE,8CAA8C,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;KAChG,MAAM,CAAC,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;KAC7E,MAAM,CAAC,WAAW,EAAE,yCAAyC,EAAE,KAAK,CAAC;KACrE,MAAM,CAAC,SAAS,CAAC,CAAC;AAErB,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,aAAa,EAAE,8CAA8C,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;KAChG,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,aAAa,EAAE,8CAA8C,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;KAChG,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,IAAI,CAAC;IACH,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,IAAI,GAAG,YAAY,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
package/notatki.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import "./dist/program.js";
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@notatki/cli",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "bin": {
6
+ "notatki": "notatki.js"
7
+ },
8
+ "dependencies": {
9
+ "@notatki/core": "^0.0.1",
10
+ "@notatki/preview": "^0.0.1",
11
+ "@notatki/sync": "^0.0.1",
12
+ "commander": "^14.0.0"
13
+ },
14
+ "scripts": {
15
+ "compile": "rm -fr dist && tsc",
16
+ "pretest": "npm run compile",
17
+ "test": "node --test 'dist/**/*.test.js'"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "gitHead": "545474a85a5cc649ff9ce50f36e87ccf5c57073a"
23
+ }
@@ -0,0 +1,36 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { exportNotes, NoteParser } from "@notatki/core";
4
+ import { generatePreview } from "@notatki/preview";
5
+ import { findNoteFiles } from "./io.js";
6
+
7
+ export async function exportCmd({ dir, out, preview }: { dir: string; out: string; preview: boolean }): Promise<void> {
8
+ const parser = new NoteParser();
9
+ console.log(`Scanning directory "${dir}"...`);
10
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
11
+ for (const path of modelPaths) {
12
+ console.log(`Parsing models file "${path}"...`);
13
+ const text = await readFile(path, "utf-8");
14
+ parser.parseModels(path, text);
15
+ }
16
+ for (const path of notePaths) {
17
+ console.log(`Parsing notes file "${path}"...`);
18
+ const text = await readFile(path, "utf-8");
19
+ parser.parseNotes(path, text);
20
+ }
21
+ parser.checkDuplicates();
22
+ parser.checkErrors();
23
+ const { notes } = parser;
24
+ console.log(`Parsed ${notes.length} note(s).`);
25
+ if (notes.length > 0) {
26
+ await writeFile(out, exportNotes(notes));
27
+ console.log(`Exported notes to "${out}".`);
28
+ if (preview) {
29
+ const previewOut = path.format({ ...path.parse(out), base: undefined, ext: ".html" });
30
+ await writeFile(previewOut, generatePreview(notes));
31
+ console.log(`Generated preview to "${previewOut}".`);
32
+ }
33
+ } else {
34
+ console.warn(`No notes found in "${dir}".`);
35
+ }
36
+ }
@@ -0,0 +1,21 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { insertNoteId, NoteParser, printNoteNodes } from "@notatki/core";
3
+ import { findNoteFiles } from "./io.js";
4
+
5
+ export async function insertIdCmd({ dir }: { dir: string }): Promise<void> {
6
+ console.log(`Scanning directory "${dir}"...`);
7
+ const { notePaths } = await findNoteFiles(dir);
8
+ for (const path of notePaths) {
9
+ const parser = new NoteParser();
10
+ console.log(`Parsing notes file "${path}"...`);
11
+ const text = await readFile(path, "utf-8");
12
+ const nodes = parser.parseNoteNodes(path, text);
13
+ if (parser.errors.length > 0) {
14
+ console.error(`Parse error.`);
15
+ } else {
16
+ if (insertNoteId(nodes)) {
17
+ await writeFile(path, printNoteNodes(nodes));
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,30 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { NoteParser, printModelNodes, printNoteNodes, reformatModelNodes, reformatNoteNodes } from "@notatki/core";
3
+ import { findNoteFiles } from "./io.js";
4
+
5
+ export async function reformatCmd({ dir }: { dir: string }): Promise<void> {
6
+ console.log(`Scanning directory "${dir}"...`);
7
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
8
+ for (const path of modelPaths) {
9
+ const parser = new NoteParser();
10
+ console.log(`Parsing models file "${path}"...`);
11
+ const text = await readFile(path, "utf-8");
12
+ const nodes = parser.parseModelNodes(path, text);
13
+ if (parser.errors.length > 0) {
14
+ console.error(`Parse error.`);
15
+ } else {
16
+ await writeFile(path, printModelNodes(reformatModelNodes(nodes)));
17
+ }
18
+ }
19
+ for (const path of notePaths) {
20
+ const parser = new NoteParser();
21
+ console.log(`Parsing notes file "${path}"...`);
22
+ const text = await readFile(path, "utf-8");
23
+ const nodes = parser.parseNoteNodes(path, text);
24
+ if (parser.errors.length > 0) {
25
+ console.error(`Parse error.`);
26
+ } else {
27
+ await writeFile(path, printNoteNodes(reformatNoteNodes(nodes)));
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,29 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { NoteParser } from "@notatki/core";
3
+ import { synchronizeNotes } from "@notatki/sync";
4
+ import { findNoteFiles } from "./io.js";
5
+
6
+ export async function syncCmd({ dir }: { dir: string }): Promise<void> {
7
+ const parser = new NoteParser();
8
+ console.log(`Scanning directory "${dir}"...`);
9
+ const { notePaths, modelPaths } = await findNoteFiles(dir);
10
+ for (const path of modelPaths) {
11
+ console.log(`Parsing models file "${path}"...`);
12
+ const text = await readFile(path, "utf-8");
13
+ parser.parseModels(path, text);
14
+ }
15
+ for (const path of notePaths) {
16
+ console.log(`Parsing notes file "${path}"...`);
17
+ const text = await readFile(path, "utf-8");
18
+ parser.parseNotes(path, text);
19
+ }
20
+ parser.checkDuplicates();
21
+ parser.checkErrors();
22
+ const { notes } = parser;
23
+ console.log(`Parsed ${notes.length} note(s).`);
24
+ if (notes.length > 0) {
25
+ await synchronizeNotes(notes, {});
26
+ } else {
27
+ console.warn(`No notes found in "${dir}".`);
28
+ }
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./cmd-export.js";
2
+ export * from "./cmd-insert-id.js";
3
+ export * from "./io.js";
package/src/io.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { glob } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+
4
+ const cwd = process.cwd();
5
+
6
+ export function pathTo(...file: string[]): string {
7
+ return resolve(cwd, ...file);
8
+ }
9
+
10
+ export async function findNoteFiles(
11
+ dir: string,
12
+ exclude: readonly string[] = ["**/.git", "**/.hg", "**/.svn", "**/node_modules"],
13
+ ) {
14
+ const notePaths: string[] = [];
15
+ const modelPaths: string[] = [];
16
+ const cwd = pathTo(dir);
17
+ for await (const item of glob("**/*.{note,model}", { cwd, exclude })) {
18
+ const path = join(cwd, item);
19
+ switch (true) {
20
+ case item.endsWith(".note"):
21
+ notePaths.push(path);
22
+ break;
23
+ case item.endsWith(".model"):
24
+ modelPaths.push(path);
25
+ break;
26
+ }
27
+ }
28
+ notePaths.sort();
29
+ modelPaths.sort();
30
+ return { notePaths, modelPaths };
31
+ }
package/src/program.ts ADDED
@@ -0,0 +1,63 @@
1
+ import { styleText } from "node:util";
2
+ import { ParseError } from "@notatki/core";
3
+ import { Command } from "commander";
4
+ import { exportCmd } from "./cmd-export.js";
5
+ import { insertIdCmd } from "./cmd-insert-id.js";
6
+ import { reformatCmd } from "./cmd-reformat.js";
7
+ import { syncCmd } from "./cmd-sync.js";
8
+ import { pathTo } from "./io.js";
9
+
10
+ const program = new Command();
11
+
12
+ program.configureOutput({
13
+ outputError: (str, write) => write(styleText("red", str)),
14
+ });
15
+
16
+ program
17
+ .name("notatki")
18
+ .description("Build Anki notes from text files written in a human readable format.")
19
+ .version("0.0.0");
20
+
21
+ program
22
+ .command("sync")
23
+ .description("build and synchronize notes with the desktop Anki application through the Anki Connect protocol")
24
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
25
+ .action(syncCmd);
26
+
27
+ program
28
+ .command("export")
29
+ .description("build and export notes to a file in the Anki notes file format")
30
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
31
+ .option("--out <file>", "output file name", parsePath, parsePath("notes.txt"))
32
+ .option("--preview", "whether to generate a preview HTML file", false)
33
+ .action(exportCmd);
34
+
35
+ program
36
+ .command("insert-id")
37
+ .description("insert unique note id to each note")
38
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
39
+ .action(insertIdCmd);
40
+
41
+ program
42
+ .command("reformat")
43
+ .description("reformat note files")
44
+ .option("--dir <dir>", "name of the directory with note source files", parsePath, parsePath("."))
45
+ .action(reformatCmd);
46
+
47
+ try {
48
+ program.parse();
49
+ } catch (err) {
50
+ if (err instanceof ParseError) {
51
+ const lines = [];
52
+ for (const { message, location } of err.errors) {
53
+ lines.push(`${String(location.source)}:${location.start.line}:${location.start.column}: ${message}`);
54
+ }
55
+ program.error(lines.join("\n"));
56
+ } else {
57
+ throw err;
58
+ }
59
+ }
60
+
61
+ function parsePath(value: string): string {
62
+ return pathTo(value);
63
+ }