Skip to content

Commit 32feb53

Browse files
author
tung-ideapad
committed
YAML
1 parent dae907f commit 32feb53

10 files changed

Lines changed: 56 additions & 22 deletions

File tree

src/gdrive.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ _GLOBAL.downloadDeletedNotesFromGoogleDrive = async function() {
376376
});
377377

378378
if (response.body) {
379-
const data = JSON.parse(response.body);
379+
const data = YAML.parse(response.body);
380380
return {
381381
ids: data.ids || [],
382382
updatedAt: data.updatedAt || new Date(file.modifiedTime).toISOString()
@@ -428,10 +428,10 @@ _GLOBAL.uploadDeletedNotesToGoogleDrive = async function(deletedIds) {
428428
const multipartRequestBody =
429429
delimiter +
430430
'Content-Type: application/json\r\n\r\n' +
431-
JSON.stringify(metadata) +
431+
YAML.stringify(metadata) +
432432
delimiter +
433433
'Content-Type: application/json\r\n\r\n' +
434-
JSON.stringify(content) +
434+
YAML.stringify(content) +
435435
close_delim;
436436

437437
const path = existingFileId ? `/upload/drive/v3/files/${existingFileId}` : '/upload/drive/v3/files';
@@ -469,7 +469,7 @@ _GLOBAL.downloadNoteFromGDrive = async function(fileId, noteId) {
469469
return null;
470470
}
471471

472-
const noteData = JSON.parse(response.body);
472+
const noteData = YAML.parse(response.body);
473473

474474
// Verification: Ensure content property exists
475475
if (typeof noteData.content === 'undefined') {
@@ -531,10 +531,10 @@ _GLOBAL.uploadNoteToGoogleDrive = async function(note, remoteMeta = null) {
531531
const multipartRequestBody =
532532
delimiter +
533533
'Content-Type: application/json\r\n\r\n' +
534-
JSON.stringify(metadata) +
534+
YAML.stringify(metadata) +
535535
delimiter +
536536
'Content-Type: application/json\r\n\r\n' +
537-
JSON.stringify(note) +
537+
YAML.stringify(note) +
538538
close_delim;
539539

540540
const path = existingFileId ? `/upload/drive/v3/files/${existingFileId}` : '/upload/drive/v3/files';

src/git.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,8 @@ _GLOBAL.deleteNoteFromGit = async (noteIdOrPath, creds) => {
338338

339339
_GLOBAL.uploadDeletedNotesToGit = async (deletedIds, creds) => {
340340
const filename = 'deleted-notes.json';
341-
const content = JSON.stringify({ ids: deletedIds, updatedAt: new Date().toISOString() }, null, 2);
342-
341+
const content = YAML.stringify({ ids: deletedIds, updatedAt: new Date().toISOString() });
342+
343343
await pfs.writeFile(`${GIT_DIR}/${filename}`, content, 'utf8');
344344
await git.add({ fs, dir: GIT_DIR, filepath: filename });
345345
};
@@ -358,7 +358,7 @@ _GLOBAL.downloadDeletedNotesFromGit = async (creds) => {
358358
}
359359

360360
const content = await pfs.readFile(filepath, 'utf8');
361-
const parsed = JSON.parse(content);
361+
const parsed = YAML.parse(content);
362362

363363
// Prefer the timestamp from the file content, but fall back to file system stat
364364
const stat = await pfs.stat(filepath);

src/helpers.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,35 @@ const TEXT_DECODER = TextDecoder;
99
const FETCH = _GLOBAL.fetch;
1010
const INDEXED_DB = _GLOBAL.indexedDB;
1111

12+
// --- YAML Helpers with JSON Fallback ---
13+
const YAML = {
14+
stringify(obj) {
15+
try {
16+
return jsyaml.dump(obj, {
17+
noRefs: true,
18+
lineWidth: -1,
19+
});
20+
} catch (e) {
21+
console.warn('YAML stringify failed, falling back to JSON:', e);
22+
return JSON.stringify(obj);
23+
}
24+
},
25+
26+
parse(str) {
27+
try {
28+
return jsyaml.load(str);
29+
} catch (e) {
30+
console.warn('YAML parse failed, falling back to JSON:', e);
31+
try {
32+
return JSON.parse(str);
33+
} catch (jsonError) {
34+
console.error('Both YAML and JSON parse failed:', jsonError);
35+
throw jsonError;
36+
}
37+
}
38+
}
39+
};
40+
1241
const promiseTimeout = (p, ms=30e3) => Promise.race([
1342
p,
1443
new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms))

src/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ <h1 class="text-2xl font-bold mb-2">FeatherNote Locked</h1>
138138
<div id="note-editor" class="p-4" style="height: 100vh;max-height: calc(100vh - 4.1rem);">
139139
<div class="flex justify-between items-center mb-4">
140140
<h3 class="text-lg font-semibold" x-text="noteEditorNoteId ? ('Editing: #' + noteEditorNoteId) : 'New Note'"></h3>
141-
<button @click=" (noteEditorContent != window.easyMDEInstance?.value()) && confirm('Save note before closing?') && saveNote(); cancelEdit();" class="cursor-pointer" aria-label="Close">
141+
<button @click="(noteEditorContent != window.easyMDEInstance?.value()) && saveNote(); cancelEdit();" class="cursor-pointer" aria-label="Close">
142142
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
143143
</button>
144144
</div>
@@ -490,6 +490,7 @@ <h4 class="text-sm font-bold" x-text="toast.title"></h4>
490490
<script defer src="/libs/isomorphic-git.min.js"></script>
491491
<script defer src="/libs/lightning-fs.min.js"></script>
492492
<script defer src="/libs/http.min.js"></script>
493+
<script defer src="/libs/js-yaml.min.js"></script>
493494

494495
<script>
495496
let _GLOBAL = typeof window !== 'undefined' ? window : self;

src/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ document.addEventListener('alpine:init', () => { Alpine.data('mainApp', () => ({
837837
try {
838838
const cachedNotes = localStorage.getItem('feathernote-notes-cache');
839839
if (cachedNotes) {
840-
this.notes = JSON.parse(cachedNotes);
840+
this.notes = YAML.parse(cachedNotes);
841841
// this.miniSearch?.removeAll();
842842
// this.miniSearch?.addAll(this.notes);
843843
// this.loading = false; // Stop loading indicator early
@@ -856,7 +856,7 @@ document.addEventListener('alpine:init', () => { Alpine.data('mainApp', () => ({
856856
try {
857857
let saved = this.notes?.slice?.(0, 12);
858858

859-
localStorage.setItem('feathernote-notes-cache', JSON.stringify(saved));
859+
localStorage.setItem('feathernote-notes-cache', YAML.stringify(saved));
860860
} catch (error) {
861861
console.error('Error updating notes cache:', error);
862862
}
@@ -1217,7 +1217,7 @@ document.addEventListener('alpine:init', () => { Alpine.data('mainApp', () => ({
12171217
tags: n.tags,
12181218
reminder: n.reminder
12191219
}));
1220-
const stateString = JSON.stringify({ notes: notesState, deleted: this.deletedNoteIds });
1220+
const stateString = YAML.stringify({ notes: notesState, deleted: this.deletedNoteIds });
12211221
return await calculateHash(stateString);
12221222
} catch (e) {
12231223
console.warn('Hash calculation failed', e);

src/libs/js-yaml.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nostr.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ async function fetchAndDecryptEventsFromRelays(relays, privateKey) {
150150
console.log('got event:', event);
151151
try {
152152
const decryptedContent = await nip04.decrypt(sk_bytes, event.pubkey, event.content);
153-
const parsedContent = JSON.parse(decryptedContent);
153+
const parsedContent = YAML.parse(decryptedContent);
154154
decryptedEventsMap.set(event.id, parsedContent);
155155
} catch (ex) {
156156
console.error('Error decrypting event:', ex);

src/s3.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const uploadNoteToS3 = async (note, creds) => {
4545
if (!creds?.secretAccessKey) return;
4646

4747
const s3 = await getS3Client(creds);
48-
const body = note.html || JSON.stringify(note, null, 2);
48+
const body = note.html || YAML.stringify(note);
4949

5050
const date = new Date(note.createdAt || note.updatedAt || Date.now());
5151
const y = date.getFullYear();
@@ -133,7 +133,7 @@ const downloadNoteFromS3 = async (noteOrId, creds) => {
133133
const data = await s3.getObject(params).promise();
134134
if (data?.Body) {
135135
const str = (new TextDecoder()).decode(data.Body);
136-
return JSON.parse(str);
136+
return YAML.parse(str);
137137
}
138138
} catch (err) {
139139
// If it failed and we didn't try the flat ID yet, try it
@@ -143,7 +143,7 @@ const downloadNoteFromS3 = async (noteOrId, creds) => {
143143
const data = await s3.getObject(flatParams).promise();
144144
if (data?.Body) {
145145
const str = (new TextDecoder()).decode(data.Body);
146-
return JSON.parse(str);
146+
return YAML.parse(str);
147147
}
148148
}
149149
throw err;
@@ -348,7 +348,7 @@ const uploadDeletedNotesToS3 = async (deletedIds, creds) => {
348348
const params = {
349349
Bucket: creds.bucket,
350350
Key: key,
351-
Body: JSON.stringify({ ids: deletedIds, updatedAt: new Date().toISOString() }, null, 2),
351+
Body: YAML.stringify({ ids: deletedIds, updatedAt: new Date().toISOString() }),
352352
ContentType: 'application/json',
353353
};
354354

@@ -371,7 +371,7 @@ const downloadDeletedNotesFromS3 = async (creds) => {
371371
const data = await s3.getObject(params).promise();
372372
if (data?.Body) {
373373
const str = (new TextDecoder()).decode(data.Body);
374-
const parsed = JSON.parse(str);
374+
const parsed = YAML.parse(str);
375375
// Return the full object including the updatedAt from the file content
376376
return {
377377
ids: parsed.ids || [],

src/server.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ app.post('/api/publish', async (req, res) => {
255255

256256
const noteId = crypto.randomBytes(8).toString('hex');
257257
const noteData = { title: title || 'Untitled Note', content };
258-
const noteString = JSON.stringify(noteData);
258+
const noteString = YAML.stringify(noteData);
259259
const noteSize = new TextEncoder().encode(noteString).length;
260260

261261
try {
@@ -302,7 +302,7 @@ app.get('/publish/:noteId', async (req, res) => {
302302

303303
const value = await CFKV.get(noteId);
304304
if (value) {
305-
note = JSON.parse(value);
305+
note = YAML.parse(value);
306306
}
307307
}
308308

@@ -323,7 +323,7 @@ app.get('/publish/:noteId', async (req, res) => {
323323
const filePath = path.join(publishedNotesDir, `${noteId}.json`);
324324
if (fs.existsSync(filePath)) {
325325
const data = fs.readFileSync(filePath, 'utf8');
326-
note = JSON.parse(data);
326+
note = YAML.parse(data);
327327
} else {
328328
note = PUBLISHED[noteId];
329329
}

src/serviceworker.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ importScripts('./libs/aws-sdk-2.1692.0.min.js');
44
importScripts('./libs/isomorphic-git.min.js');
55
importScripts('./libs/lightning-fs.min.js');
66
importScripts('./libs/http.min.js');
7+
importScripts('./libs/js-yaml.min.js');
78
importScripts('./s3.js');
89
importScripts('./git.js');
910
importScripts('./nostr.js');
@@ -36,6 +37,7 @@ const urlsToCache = [
3637
'/libs/isomorphic-git.min.js',
3738
'/libs/lightning-fs.min.js',
3839
'/libs/http.min.js',
40+
'/libs/js-yaml.min.js',
3941
'https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css',
4042
'https://maxcdn.bootstrapcdn.com/font-awesome/latest/fonts/fontawesome-webfont.woff2?v=4.7.0',
4143
'https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4',

0 commit comments

Comments
 (0)