@notatki/core 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.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/dist/export-notes.d.ts +3 -0
  3. package/dist/export-notes.d.ts.map +1 -0
  4. package/dist/export-notes.js +28 -0
  5. package/dist/export-notes.js.map +1 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +11 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/insert-note-id.d.ts +5 -0
  11. package/dist/insert-note-id.d.ts.map +1 -0
  12. package/dist/insert-note-id.js +20 -0
  13. package/dist/insert-note-id.js.map +1 -0
  14. package/dist/model.d.ts +128 -0
  15. package/dist/model.d.ts.map +1 -0
  16. package/dist/model.js +125 -0
  17. package/dist/model.js.map +1 -0
  18. package/dist/nodes.d.ts +14 -0
  19. package/dist/nodes.d.ts.map +1 -0
  20. package/dist/nodes.js +7 -0
  21. package/dist/nodes.js.map +1 -0
  22. package/dist/note-parser.d.ts +34 -0
  23. package/dist/note-parser.d.ts.map +1 -0
  24. package/dist/note-parser.js +233 -0
  25. package/dist/note-parser.js.map +1 -0
  26. package/dist/note.d.ts +42 -0
  27. package/dist/note.d.ts.map +1 -0
  28. package/dist/note.js +156 -0
  29. package/dist/note.js.map +1 -0
  30. package/dist/output.d.ts +7 -0
  31. package/dist/output.d.ts.map +1 -0
  32. package/dist/output.js +25 -0
  33. package/dist/output.js.map +1 -0
  34. package/dist/print-model-nodes.d.ts +3 -0
  35. package/dist/print-model-nodes.d.ts.map +1 -0
  36. package/dist/print-model-nodes.js +39 -0
  37. package/dist/print-model-nodes.js.map +1 -0
  38. package/dist/print-note-nodes.d.ts +3 -0
  39. package/dist/print-note-nodes.d.ts.map +1 -0
  40. package/dist/print-note-nodes.js +34 -0
  41. package/dist/print-note-nodes.js.map +1 -0
  42. package/dist/reformat-model-nodes.d.ts +3 -0
  43. package/dist/reformat-model-nodes.d.ts.map +1 -0
  44. package/dist/reformat-model-nodes.js +5 -0
  45. package/dist/reformat-model-nodes.js.map +1 -0
  46. package/dist/reformat-note-nodes.d.ts +3 -0
  47. package/dist/reformat-note-nodes.d.ts.map +1 -0
  48. package/dist/reformat-note-nodes.js +31 -0
  49. package/dist/reformat-note-nodes.js.map +1 -0
  50. package/package.json +19 -0
  51. package/src/export-notes.ts +31 -0
  52. package/src/index.ts +10 -0
  53. package/src/insert-note-id.ts +23 -0
  54. package/src/model.ts +155 -0
  55. package/src/nodes.ts +7 -0
  56. package/src/note-parser.ts +277 -0
  57. package/src/note.ts +189 -0
  58. package/src/output.ts +27 -0
  59. package/src/print-model-nodes.ts +39 -0
  60. package/src/print-note-nodes.ts +31 -0
  61. package/src/reformat-model-nodes.ts +5 -0
  62. package/src/reformat-note-nodes.ts +34 -0
package/src/note.ts ADDED
@@ -0,0 +1,189 @@
1
+ import { type FieldNode, type NoteNode, type PropertyNode } from "@notatki/parser";
2
+ import { type Model, type ModelField, ModelMap } from "./model.js";
3
+ import { loc } from "./nodes.js";
4
+
5
+ export class NoteList implements Iterable<Note> {
6
+ readonly #types: ModelMap;
7
+ readonly #notes: Note[];
8
+
9
+ constructor(types = new ModelMap()) {
10
+ this.#types = types;
11
+ this.#notes = [];
12
+ }
13
+
14
+ get types(): ModelMap {
15
+ return this.#types;
16
+ }
17
+
18
+ [Symbol.iterator](): Iterator<Note> {
19
+ return this.#notes[Symbol.iterator]();
20
+ }
21
+
22
+ get length(): number {
23
+ return this.#notes.length;
24
+ }
25
+
26
+ add(note: Note): void {
27
+ this.#notes.push(note);
28
+ }
29
+ }
30
+
31
+ export class Note implements Iterable<NoteField> {
32
+ readonly #type: Model;
33
+ #deck: string = "";
34
+ #tags: string = "";
35
+ readonly #id = new NoteField({ name: "ID", required: false });
36
+ readonly #fields = new Map<string, NoteField>();
37
+ #node: NoteNode | null = null;
38
+
39
+ constructor(type: Model) {
40
+ this.#type = type;
41
+ for (const field of type.fields) {
42
+ this.#fields.set(field.name.toLowerCase(), new NoteField(field));
43
+ }
44
+ }
45
+
46
+ get type(): Model {
47
+ return this.#type;
48
+ }
49
+
50
+ get deck(): string {
51
+ return this.#deck;
52
+ }
53
+
54
+ set deck(value: string | null) {
55
+ this.#deck = value ?? "";
56
+ }
57
+
58
+ get tags(): string {
59
+ return this.#tags;
60
+ }
61
+
62
+ set tags(value: string | null) {
63
+ this.#tags = value ?? "";
64
+ }
65
+
66
+ get id(): string {
67
+ return this.#id.value;
68
+ }
69
+
70
+ set id(value: string | null) {
71
+ this.#id.value = value;
72
+ }
73
+
74
+ [Symbol.iterator](): Iterator<NoteField> {
75
+ return this.#fields.values();
76
+ }
77
+
78
+ has(fieldName: string): boolean {
79
+ const key = fieldName.toLowerCase();
80
+ if (key === "id") {
81
+ return true;
82
+ }
83
+ return this.#fields.has(key);
84
+ }
85
+
86
+ get(fieldName: string): NoteField {
87
+ return this.#getField(fieldName);
88
+ }
89
+
90
+ set(fieldName: string, value: string | null): void {
91
+ this.#getField(fieldName).value = value;
92
+ }
93
+
94
+ #getField(fieldName: string): NoteField {
95
+ const key = fieldName.toLowerCase();
96
+ if (key === "id") {
97
+ return this.#id;
98
+ }
99
+ const field = this.#fields.get(key);
100
+ if (field != null) {
101
+ return field;
102
+ }
103
+ throw new Error(`Unknown field: "${fieldName}"`);
104
+ }
105
+
106
+ get first(): NoteField {
107
+ const [first] = this.#fields.values();
108
+ if (first != null) {
109
+ return first;
110
+ }
111
+ throw new Error("No fields");
112
+ }
113
+
114
+ get node(): NoteNode | null {
115
+ return this.#node;
116
+ }
117
+
118
+ set node(value: NoteNode | null) {
119
+ this.#node = value;
120
+ }
121
+
122
+ toNode(): NoteNode {
123
+ const properties: PropertyNode[] = [];
124
+ properties.push({ name: { text: "type", loc }, value: { text: this.#type.name, loc }, loc });
125
+ properties.push({ name: { text: "deck", loc }, value: { text: this.#deck, loc }, loc });
126
+ properties.push({ name: { text: "tags", loc }, value: { text: this.#tags, loc }, loc });
127
+ const fields: FieldNode[] = [];
128
+ if (this.#id.value) {
129
+ fields.push(this.#id.toNode());
130
+ }
131
+ for (const field of this.#fields.values()) {
132
+ if (field.value) {
133
+ fields.push(field.toNode());
134
+ }
135
+ }
136
+ return {
137
+ properties,
138
+ fields,
139
+ end: { text: "~~~", loc },
140
+ loc,
141
+ };
142
+ }
143
+
144
+ static isIdField(fieldName: string): boolean {
145
+ return fieldName.toLowerCase() === "id";
146
+ }
147
+ }
148
+
149
+ export class NoteField {
150
+ readonly #type: ModelField;
151
+ #value: string = "";
152
+ #node: FieldNode | null = null;
153
+
154
+ constructor(type: ModelField) {
155
+ this.#type = type;
156
+ }
157
+
158
+ get name(): string {
159
+ return this.#type.name;
160
+ }
161
+
162
+ get required(): boolean {
163
+ return this.#type.required ?? false;
164
+ }
165
+
166
+ get value(): string {
167
+ return this.#value;
168
+ }
169
+
170
+ set value(value: string | null) {
171
+ this.#value = value ?? "";
172
+ }
173
+
174
+ get node(): FieldNode | null {
175
+ return this.#node;
176
+ }
177
+
178
+ set node(value: FieldNode | null) {
179
+ this.#node = value;
180
+ }
181
+
182
+ toNode(): FieldNode {
183
+ return {
184
+ name: { text: this.#type.name.toLowerCase(), loc },
185
+ value: { text: this.#value, loc },
186
+ loc,
187
+ };
188
+ }
189
+ }
package/src/output.ts ADDED
@@ -0,0 +1,27 @@
1
+ export class Output {
2
+ readonly #lines: string[] = [];
3
+ #separate = false;
4
+ #text: string | null = null;
5
+
6
+ separate(): void {
7
+ if (this.#lines.length > 0) {
8
+ this.#separate = true;
9
+ this.#text = null;
10
+ }
11
+ }
12
+
13
+ print(line: string): void {
14
+ if (line.length > 0) {
15
+ if (this.#separate) {
16
+ this.#lines.push("");
17
+ this.#separate = false;
18
+ }
19
+ this.#lines.push(line);
20
+ this.#text = null;
21
+ }
22
+ }
23
+
24
+ toString(): string {
25
+ return (this.#text ??= this.#lines.join("\n") + "\n");
26
+ }
27
+ }
@@ -0,0 +1,39 @@
1
+ import { type ModelNode } from "@notatki/parser";
2
+ import { Output } from "./output.js";
3
+
4
+ export function printModelNodes(nodes: Iterable<ModelNode>): string {
5
+ const out = new Output();
6
+ for (const { name, id, cloze, fields, cards, styling } of nodes) {
7
+ out.separate();
8
+ out.print(`model ${name.text}`);
9
+ out.separate();
10
+ out.print(`id ${id.value}`);
11
+ if (cloze != null) {
12
+ out.separate();
13
+ out.print("cloze");
14
+ }
15
+ out.separate();
16
+ for (const { name, required } of fields) {
17
+ out.print(`field ${name.text}${required ? "" : "?"}`);
18
+ }
19
+ out.separate();
20
+ for (const { name, front, back } of cards) {
21
+ out.print(`card ${name.text}`);
22
+ out.separate();
23
+ out.print("front");
24
+ out.print(front.text);
25
+ out.print("~~~");
26
+ out.separate();
27
+ out.print("back");
28
+ out.print(back.text);
29
+ out.print("~~~");
30
+ out.separate();
31
+ }
32
+ if (styling != null) {
33
+ out.print("styling");
34
+ out.print(styling.text);
35
+ out.print("~~~");
36
+ }
37
+ }
38
+ return String(out);
39
+ }
@@ -0,0 +1,31 @@
1
+ import { type NoteNode } from "@notatki/parser";
2
+ import { Output } from "./output.js";
3
+
4
+ export function printNoteNodes(nodes: Iterable<NoteNode>): string {
5
+ const out = new Output();
6
+ for (const { properties, fields, end } of nodes) {
7
+ out.separate();
8
+ for (const { name, value } of properties) {
9
+ if (value.text) {
10
+ out.print(`!${name.text}: ${value.text}`);
11
+ } else {
12
+ out.print(`!${name.text}:`);
13
+ }
14
+ }
15
+ out.separate();
16
+ for (const { name, value } of fields) {
17
+ if (value.text) {
18
+ if (value.text.includes("\n")) {
19
+ out.print(`!${name.text}:`);
20
+ out.print(value.text);
21
+ } else {
22
+ out.print(`!${name.text}: ${value.text}`);
23
+ }
24
+ } else {
25
+ out.print(`!${name.text}:`);
26
+ }
27
+ }
28
+ out.print(end.text);
29
+ }
30
+ return String(out);
31
+ }
@@ -0,0 +1,5 @@
1
+ import { type ModelNode } from "@notatki/parser";
2
+
3
+ export function reformatModelNodes(nodes: Iterable<ModelNode>): ModelNode[] {
4
+ return [...nodes];
5
+ }
@@ -0,0 +1,34 @@
1
+ import { type FieldNode, type NoteNode, type PropertyNode, type Token } from "@notatki/parser";
2
+ import { loc } from "./nodes.js";
3
+
4
+ export function reformatNoteNodes(nodes: Iterable<NoteNode>): NoteNode[] {
5
+ return [...nodes].map(mapNoteNode);
6
+ }
7
+
8
+ function mapNoteNode(node: NoteNode): NoteNode {
9
+ return {
10
+ properties: node.properties.map(mapPropertyNode),
11
+ fields: node.fields.map(mapFieldNode),
12
+ end: { text: "~~~", loc },
13
+ loc,
14
+ };
15
+ }
16
+
17
+ function mapPropertyNode({ name, value }: PropertyNode): PropertyNode {
18
+ return {
19
+ name: nameOf(name),
20
+ value: { text: value.text, loc },
21
+ loc,
22
+ };
23
+ }
24
+ function mapFieldNode({ name, value }: FieldNode): FieldNode {
25
+ return {
26
+ name: nameOf(name),
27
+ value: { text: value.text, loc },
28
+ loc,
29
+ };
30
+ }
31
+
32
+ function nameOf({ text }: Token): Token {
33
+ return { text: text.toLowerCase(), loc };
34
+ }