From 84638a9ed61b6e7bed61af28de72907f8a8650b7 Mon Sep 17 00:00:00 2001 From: octospacc Date: Wed, 14 Dec 2022 18:29:28 +0100 Subject: [PATCH] Agg. Posts/Blogging-Rapido-con-Standard-Notes.md, ListedDownsync.js --- ...2-13-Blogging-Rapido-con-Standard-Notes.md | 62 +++--- Scripts/Lib/config-ini-parser.js | 9 + Scripts/ListedDownsync.js | 176 ++++++++++++++---- 3 files changed, 177 insertions(+), 70 deletions(-) create mode 100644 Scripts/Lib/config-ini-parser.js diff --git a/Posts/2022-12-13-Blogging-Rapido-con-Standard-Notes.md b/Posts/2022-12-13-Blogging-Rapido-con-Standard-Notes.md index 54705ce..a48be0f 100644 --- a/Posts/2022-12-13-Blogging-Rapido-con-Standard-Notes.md +++ b/Posts/2022-12-13-Blogging-Rapido-con-Standard-Notes.md @@ -1,78 +1,76 @@ -// % Categories = Blog Tecnologia +// % Title = ⚡️ Il blogging rapido con Standard Notes // % CreatedOn = 2022-12-13 +// % HTMLTitle = ⚡️ Il blogging rapido con Standard Notes +// % UpdatedOn = 2022-12-14 +// % Categories = Blog Tecnologia # ⚡️ Il blogging rapido con Standard Notes - - -

È da direi parecchio tempo che uso Standard Notes come app di note personali.

+

È da direi parecchio tempo che uso Standard Notes come app di note personali.
Anni fa l'avevo scelta per il suo essere libera e open-source, ma allo stesso tempo molto pulita, curata, e funzionale. Capitava a pennello in un momento in cui cercavo qualcosa che supportasse una cifratura dei dati che funziona, senza inficiare sull'usabilità.

-

Senza dilungarmi su perché poi mi è piaciuto continuare ad usarla, poi ho smesso, e poi ho ripreso fino ad arrivare ad ora, bisogna approfondire su una in particolare delle sue funzioni integrate: Listed.

+

Senza dilungarmi su perché poi mi è piaciuto continuare ad usarla, poi ho smesso, e poi ho ripreso fino ad arrivare ad ora, bisogna approfondire su una in particolare delle sue funzioni integrate: Listed.
Si tratta di una piattaforma di blogging concepita dagli stessi sviluppatori di Standard Notes, e disponibile per il self-hosting oppure l'uso gratuito sull'istanza ufficiale. Per quanto io non l'abbia mai davvero usata prima, ho trovato fin dall'inizio interessante il concetto e la sua applicazione.

Da qualche giorno fa, invece, ho iniziato a giochicchiare con ChatGPT. Questione totalmente diversa questa, si, ma centra perché mi sono posta una domanda: tutte queste conversazioni che sto facendo con l'intelligenza artificiale, dove posso metterle per tenerle integrali, organizzate, ritrovabili e accessibili a chiunque, e per me facili da caricare?

-

La scelta stava per ricadere sull'usare staticoso, il mio generatore di siti statici che già uso per il sitoctt, ma poi ci ho ripensato.

+

La scelta stava per ricadere sull'usare staticoso, il mio generatore di siti statici che già uso per il sitoctt, ma poi ci ho ripensato.

-

Ho pensato che voglio rendere effettivamente la mia collezione di esperienze ritrovabile sul Web, il problema qui però, che ho potuto amaramente constatare in tutti questi mesi, è come il sitoctt ad esempio sia, come dire... I motori di ricerca non se lo cagano. 😭

+

Ho pensato che voglio rendere effettivamente la mia collezione di esperienze ritrovabile sul Web, il problema qui però, che ho potuto amaramente constatare in tutti questi mesi, è come il mio sito ad esempio sia, come dire... I motori di ricerca non se lo cagano. 😭
Oltre ad essere pure questo un argomento a parte, va precisato che la colpa della orrenda sorte del mio sito non dipende dal suo codice; è colpa del dominio e/o dell'host. Quindi, no, non abbandonerò mai il mio staticoso: il solo cambiare generatore (e i template di conseguenza) con uno magari fatto seriamente non risolverebbe alcun problema.

Ho dovuto insomma cestinare totalmente l'idea dell'hosting su GitHub e GitLab, e pensare ad altro.

Le mie idee erano finite e, dato che avevo fretta di mettere su questo sito ed iniziare a caricarci le esperienze avute con ChatGPT, considerando quanto mamma mia era comodo copiare ed incollare le cose direttamente in Standard Notes, questo era il momento buono di provare Listed.

-

A dirla tutta, mi preoccupa un po' il prospetto che il file di backup settimanale delle note possa diventare grosso decine di MB, ma ormai il dado è tratto.

+

A dirla tutta, mi preoccupa un po' il prospetto che il file di backup settimanale delle note possa diventare grosso decine di MB, ma ormai il dado è tratto.
Potrei creare un secondo account da usare solo per le note di ChatGPT, esportandole dal primario ed importandole lì, per poi cancellarle dal primo account per alleggerire la raccolta, però ci sono dei problemi. Forse riesco a trasferire l'username, ma i link ai singoli post saranno rotti, perché includono degli ID automatici, e quindi via di redirect alla home per chi ne segue uno vecchio. Inoltre, i vecchi messaggi del guestbook non vengono ricopiati, e mi sa che nemmeno le iscrizioni via email sono trasferite.

-

Tutto sommato comunque, per questo scopo limitato ho apprezzato quanto sia efficiente avere Standard Notes come parte finale del mio flusso di lavoro. Mi sembra riduca di molto l'effetto "mi scoccio".

+

Tutto sommato comunque, per questo scopo limitato ho apprezzato quanto sia efficiente avere Standard Notes come parte finale del mio flusso di lavoro. Mi sembra riduca di molto l'effetto "mi scoccio".

-

Considerato dunque il piacere della scoperta, ho per un attimo riflettuto su come il fattore "che palle" sia una delle cose che mi trattiene dall'aggiornare il sitoctt con migliore frequenza.

+

Considerato dunque il piacere della scoperta, ho per un attimo riflettuto su come il fattore "che palle" sia una delle cose che mi trattiene dall'aggiornare il sitoctt con migliore frequenza.

-

Lasciamo stare le pagine tematiche, che sono bestie a parte; lasciamo stare pure i post lunghi, che mi richiedono forte ispirazione e abbastanza tempo di stesura; però che cavolo, almeno qualcosa per il MicroBlog mi andrebbe di crearla più spesso! Però mi passa proprio la voglia, per qualche motivo, considerando tutta la trafila che devo fare.

+

Lasciamo stare le pagine tematiche, che sono bestie a parte; lasciamo stare pure i post lunghi, che mi richiedono forte ispirazione e abbastanza tempo di stesura; però che cavolo, almeno qualcosa per il MicroBlog, che va per le corte, mi andrebbe di crearla più spesso! Però mi passa proprio la voglia, per qualche motivo, considerando tutta la trafila che devo fare.
A dire il vero, avevo preso già da subito l'abitudine di iniziare a scrivere un post in Standard Notes, così da poter più flessibilmente gestire il tutto, magari passando rapidamente da un dispositivo all'altro. Però, se dovevo mettermi a scrivere qualcosa di non lungo ed elaborato, da pubblicare prima possibile, non mi veniva proprio la voglia di agire.

"Ma perché non passo a Listed almeno per il mio MicroBlog?", penso dunque. Beh, c'è un motivo se addirittura sono arrivata a farmi il mio generatore di siti statici: mi serve!... E se anche non mi servisse più e potrei dunque smettere di usarlo, non ci vorrei onestamente nemmeno pensare a fare una cosa del genere, dopo tutto il lavoro! 😖

-

Comunque, per dirla bene, Listed è parecchio scarno: permette appena di inserire CSS personalizzato, e di formattare i post in Markdown e un sottoinsieme ristretto di HTML (di cui propongo di seguito le mie analisi):

+

Comunque, per dirla bene, Listed è parecchio scarno: permette appena di inserire CSS personalizzato, e di formattare i post in Markdown e un sottoinsieme ristretto di HTML (di cui propongo di seguito le mie analisi):

È chiarissimo che non può sostituire al 100% assolutamente nessuna sezione del sitoctt, nemmeno quella del MicroBlog, e anche se potesse andrebbe a creare frammentazione: il sito principale non conterrebbe più tutti tutti i post in modo centralizzato, e chi ne avesse interesse dovrebbe quindi seguire ben 2 siti diversi.

-

Mi stavo quasi per rassegnare, ma per fortuna ho il lampo di genio: Ma posso scrivere su Standard Notes, ed avere le note che in automatico si sincronizzano come file sul sito? ...No, non c'è verso. No, aspe, e chi lo ha detto? Io dico che c'è verso.

+

Mi stavo quasi per rassegnare, ma per fortuna ho il lampo di genio: Ma posso scrivere su Standard Notes, ed avere le note che in automatico si sincronizzano come file sul sito? ...No, non c'è verso. No, aspè, e chi lo ha detto? Io dico che c'è verso.

-

Ora, Standard Notes, come ho detto, usa un sistema di cifratura client-side dei dati, quindi per accedere alle note dal proprio account va usato un software un minimo specializzato.

+

Ora, Standard Notes, come ho detto, usa un sistema di cifratura client-side dei dati, quindi per accedere alle note dal proprio account va usato un software un minimo specializzato.
C'è sn-cli, il client ufficiale a riga di comando, che potrebbe essere utile per creare script... però pare proprio sia stato abbandonato: niente da fare.

-

E allora, anche qui io quindi parlo, e dico: Chi lo ha detto che devo fare le cose per bene e usare le API "vere"?

-Io dico che, visto che per qualche motivo l'HTML di un blog su Listed (nello specifico, la pagina /all, l'unica che mi sembra includere davvero tutto, e non solo gli ultimi X posts) include come stringa JSON i dati di tutti i post, allora io posso semplicemente pubblicare su Listed da Standard Notes ed avere un programma che fa lo sporco - ma in questo caso davvero semplice, visto che deve solo scaricare e parsare 1 file - lavoro dello scraping.

+

E allora, anche qui io quindi parlo, e dico: Chi lo ha detto che devo fare le cose per bene e usare le API "vere"?
+Io dico che, visto che per qualche motivo l'HTML di un blog su Listed (nello specifico, la pagina /all, l'unica che mi sembra includere davvero tutto, e non solo gli ultimi X post) include come stringa JSON i dati di tutti i post, allora io posso semplicemente pubblicare su Listed da Standard Notes ed avere un programma che fa lo sporco - ma in questo caso davvero semplice, visto che deve solo scaricare e parsare 1 file - lavoro dello scraping.

-

E script fu scripto. Lo lascio qui: https://gitlab.com/octtspacc/sitoctt/-/blob/main/Scripts/ListedDownsync.js; attenzione però che non c'è niente di bello da leggere, anche perché non ho ancora implementato tutto quello che dovrebbe servirmi a lungo termine, ma per chi vuole usarlo sta là.

+

E script fu scripto. Lo lascio qui: gitlab.com/octtspacc/sitoctt/Scripts/ListedDownsync.js; attenzione però che non c'è niente di bello da leggere, anche perché non ho ancora implementato tutto quello che dovrebbe servirmi a lungo termine, ma per chi vuole usarlo sta là.
È tecnicamente indipendente dal sitoctt e da staticoso, in quanto salva semplici file Markdown su disco (anche se la sintassi delle righe di metadati in essi scritti è quella mia; per cui, in caso, andrebbe cambiata qualche stringa di testo nel programma per supportare il più classico formato dei metadati YAML).

-

Non voglio dire che ho pensato davvero a tutto, però ci sono andata vicina.

-No non mi so ancora decidere - per colpa di mie paturnie - su che standard usare per indicare blocchi speciali (di metadati, o di HTML da non far interpretare al SSG di Listed).

-No, non ho ancora fatto lo script da avviare come cronjob sul server, che ogni tanto dovrebbe scaricare i dati dal blog di Listed e aggiornare i file nella repository Git se ci sono aggiornamenti.

+

Non voglio dire che ho pensato davvero a tutto, però ci sono andata vicina.
+No non mi so ancora decidere - per colpa di mie paturnie - su che standard usare per indicare blocchi speciali (di metadati, o di HTML da non far interpretare al SSG di Listed).
+No, non ho ancora fatto lo script da avviare come cronjob sul server, che ogni tanto dovrebbe scaricare i dati dal blog di Listed e aggiornare i file nella repository Git se ci sono aggiornamenti.
Però, ho pensato alle cose veramente inderogabili, tipo la possibilità per il programma di sincronizzazione di non sovrascrivere un file già nella repo se questo specifica la cosa nei metadati. Metti che succede un qualunque casino, e io devo modificare i dati del post per il sitoctt senza toccare quelli della nota su Standard Notes: impostando questa flag, lo script di sincronizzazione non lo sostituirà la prossima volta che gira.

-

Come concludere, dunque.

-Oggi ho già scritto troppo, e la chiudo qui. Però spero vivamente che tutta questa nuova efficienza e comodità, l'avere ulteriore tecnologia che lavora per me, e non obbliga me a lavorare per lei (in teoria, tanto i problemi devono uscire fuori, altrimenti io non sono io!), possa farmi scrivere di più e con più piacere. Che sia sul sitoctt, o sulle lastre di pietra.

- -

Ah, si, questo qui è stato il primo post sul mio blog Listed, è giusto precisarlo per chi legge dal sitoctt.

- - +

Come concludere, dunque.
+Oggi ho già scritto troppo, e la chiudo qui. Però spero vivamente che tutta questa nuova efficienza e comodità, l'avere ulteriore tecnologia che lavora per me, e non obbliga me a lavorare per lei (in teoria, tanto comunque i problemi devono uscire fuori, altrimenti io non sono io!), possa farmi scrivere di più e con più piacere. Che sia sul sitoctt, o sulle lastre di pietra.

+

Ah, si, questo qui è stato il primo post sul mio blog Listed, è giusto precisarlo per chi legge dal sitoctt... ma io spero che almeno la versione Listed del blog possa venire indicizzata per bene e scoperta da più persone, già che ci siamo.

diff --git a/Scripts/Lib/config-ini-parser.js b/Scripts/Lib/config-ini-parser.js new file mode 100644 index 0000000..c7de2ec --- /dev/null +++ b/Scripts/Lib/config-ini-parser.js @@ -0,0 +1,9 @@ +/** + * Created by Erxin, Shang(Edwin) on 6/21/2016. + * JavaScript Configuration file(.ini) content parser, similar to python ConfigParser without I/O operations + * The license is under GPL-3.0 + * Git repo:https://github.com/shangerxin/config-ini + * Author homepage: http://www.shangerxin.com + * Version, 1.6.1 + */ +!function(t){var n=Object.assign(new Error,{name:"ConfigIniParser Error",message:"Parse config ini file error"}),r=Object.assign(new Error,{name:"ConfigIniParser Error",message:"The specify section not found"}),e=Object.assign(new Error,{name:"ConfigIniParser Error",message:"The specify option not found"}),i=Object.assign(new Error,{name:"ConfigIniParser Error",message:"Found duplicated section in the given ini file"}),o=Object.assign(new Error,{name:"ConfigIniParser Error",message:"Multiple call parse on the same parser instance"}),s=Object.assign(new TypeError,{name:"ConfigIniParser Error",message:"The argument type is not correct"}),a="__DEFAULT_SECTION__",u=/^\s*\[\s*([^\]]+?)\s*\]\s*$/,p=/\s*([^=:\s]+)\s*[=:]\s*(.*)\s*/,f=/^\s*[#;].*/,c=/^\s*$/,h=-1;function l(t,n){for(var r=t.sections,e=0;e0&&i.push("")}return i.join(t||this.delimiter)},y.prototype.parse=function(t){if(this._calledParse)throw o;this._calledParse=!0;for(var r=t.split(this.delimiter),e=l(this._ini,a),s=0;s { if (fs.existsSync(Path)) { return fs.readFileSync(Path, 'utf8'); @@ -22,7 +23,7 @@ const TryReadFileSync = Path => { }; const TryMkdirSync = Path => { if (!fs.existsSync(Path)) { - return fs.mkdirSync(Path, {recursive:true}); + return fs.mkdirSync(Path, {recursive: true}); }; }; @@ -33,6 +34,12 @@ const GetPath = URL => { return URL; }; +const GetFragHTML = Frag => { + let Dom = new JSDOM(''); + Dom.window.document.body.appendChild(Frag); + return Dom.window.document.body.innerHTML; +}; + const CheckDoDownsync = File => { let DoDownsync = true; const TryFile = TryReadFileSync(File); @@ -41,11 +48,10 @@ const CheckDoDownsync = File => { for (let i=0; i {return e != ''}); - if (Tokens[1] == '%' && Tokens[2] == 'downsync') { - if (['false', 'disabled', 'off', 'no'].includes(Tokens[4])) { - DoDownsync = false; - }; + const Tokens = Line.split(' ').filter(i => {return i != ''}); + if (Tokens[1] == '%' && Tokens[2] == 'downsync' && [':', '='].includes(Tokens[3]) && ['false', 'disabled', 'off', 'no'].includes(Tokens[4])) { + DoDownsync = false; + break; }; }; }; @@ -53,27 +59,89 @@ const CheckDoDownsync = File => { return DoDownsync; }; -const HandlePost = PostSrc => { +const GetLinkElem = Dom => { let Elem; - let Post = {}; - - Post['Title'] = PostSrc.title; - Post['CreatedOn'] = PostSrc.created_at.split('T')[0]; - console.log(`[I] => [${Post['CreatedOn']}] ${Post['Title']}`); - - const Dom = JSDOM.fragment(PostSrc.rendered_text); Elem = Dom.querySelector(`.Mirror-${SiteName}`); if (!Elem) { Elem = Dom.querySelector(`.Mirror-${SiteName}-Include`); }; - if (!Elem) { // Post content has no mirror-flagging element, skip it - console.log(`[I] : No mirror flag in source body; Skipping!`); - return; // TODO: Exclusion mode instead of inclusion? Aka automatically handle posts without the element - }; + return Elem; +}; - const Path = GetPath(JSDOM.fragment(Elem.outerHTML).querySelector('[href]').href); - Post['Categories'] = ''; - const Classes = Elem.classList; +const ParseMeta = Raw => { + let Mid = {"Meta": "", "Macros": ""}; + let Data = {"Meta": {}, "Macros": {}}; + const Lines = Raw.trim().split('\n'); + for (let i=0; i { + let Str = ''; + const Types = ['Meta', 'Macros']; + for (let i=0; i { + let LinkElem, ContentDom; + let Post = {"Meta": {}, "Macros": {}}; + + Post.Meta.Title = PostSrc.title; + Post.Meta.CreatedOn = PostSrc.created_at.split('T')[0]; + Post.Content = PostSrc.rendered_text; + console.log(`[I] => [${Post.Meta.CreatedOn}] ${Post.Meta.Title}`); + + ContentDom = JSDOM.fragment(Post.Content); + + LinkElem = GetLinkElem(ContentDom); + if (!LinkElem) { // Post content has no mirror-flagging element, skip it + // TODO: Exclusion mode instead of inclusion? Aka automatically handle posts without the element + // TODO: Check flagging via MetadataBlock? + console.log(`[I] : No mirror flag in source body; Skipping!`); + return; + }; + const LinkPath = GetPath(JSDOM.fragment(LinkElem.outerHTML).querySelector('[href]').href); + +/* + // Get post categories + Post.Categories = ''; + const Classes = LinkElem.classList; for (let i=0; i { Post['Categories'] = '// % Categories = ' + Class.substring(Key.length).replaceAll('|', ' '); }; }; +*/ - Post['Content'] = PostSrc.rendered_text.replace(Elem.outerHTML, ''); + // Do string replacements const ReplacementsKeys = Object.keys(Replacements); for (let i=0; i { FromItems = [FromItems]; }; for (let i=0; i