#!/usr/bin/env -S node --experimental-fetch
const fs = require('fs');
const JSDOM = require('jsdom').JSDOM;
const ConfigParser = require("./Lib/config-ini-parser").ConfigIniParser;
const BlogURL = 'https://listed.to/@u8'; // Full base URL of the Listed blog (any server)
const SiteName = 'sitoctt';
//const DefaultMode = 'Include' // 'Include' or 'Exclude' | Not implemented
const PostsFileDate = true; // Append dates (YYYY-MM-DD) to posts file names
const Replacements = { // Format: { ReplaceWithString: [ToFindString] }
"## [:HNotesRefsHTML:]": "
🏷️ Note e Riferimenti
",
"", "## ": "", "### ": "", "#### ": "", "##### ": "", "###### ": "",
"": ["", "
", "", "", "", ""],
// staticoso TODO: Fix the handling of headings to remove this crap above...
};
const MetadataBlockSelect = '.MetadataBlock, .MetadataBlock + :Where(Div, Pre, Code)';
const ExtractCodeBlockSelect = '.ExtractCodeBlock, .ExtractCodeBlock + :Where(Div, Pre, Code)';
const TryReadFileSync = Path => {
if (fs.existsSync(Path)) {
return fs.readFileSync(Path, 'utf8');
};
};
const TryMkdirSync = Path => {
if (!fs.existsSync(Path)) {
return fs.mkdirSync(Path, {recursive: true});
};
};
const GetPath = URL => {
if (URL.startsWith('http://') || URL.startsWith('https://')) {
URL = URL.split('/').slice(3).join('/');
};
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);
if (TryFile) {
const Lines = TryFile.trim().toLowerCase().split('\n');
for (let i=0; i {return i != ''});
if (Tokens[1] == '%' && Tokens[2] == 'downsync' && [':', '='].includes(Tokens[3]) && ['false', 'disabled', 'off', 'no'].includes(Tokens[4])) {
DoDownsync = false;
break;
};
};
};
};
return DoDownsync;
};
const GetLinkElem = Dom => {
let Elem;
Elem = Dom.querySelector(`.Mirror-${SiteName}`);
if (!Elem) {
Elem = Dom.querySelector(`.Mirror-${SiteName}-Include`);
};
return Elem;
};
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 {
console.log('[I] Downloading...');
fetch(`${BlogURL}/all`).then(Response => Response.text()).then(Data => {
console.log('[I] Parsing...');
const Elem = JSDOM.fragment(Data).querySelector('script[data-component-name="AuthorAll"]');
const Posts = JSON.parse(Elem.childNodes[0].data).posts;
for (let i=0; i