Compare commits

..

2 Commits

Author SHA1 Message Date
b4fd4f344c fix: properly parse titles 2022-06-28 11:09:06 +02:00
b03ddcb428 feat: handle local urls
feat: debug mode (auto-refreshes pages)
fix: date ordering
feat: add poor person's jQuery
improvement: rename startLoading to showLoadingOverlay
fix: do not load initial page twice
improvement: allow arbitrary spaces between filename and date in files.txt
2022-06-28 11:05:59 +02:00
3 changed files with 63 additions and 19 deletions

View File

@ -1 +1,2 @@
readme.md 2022-03-03 Tickle readme.md 2022-28-06 Tickle
examples.md 2022-28-06 Examples

View File

@ -153,12 +153,47 @@
<main id="Body"></main> <main id="Body"></main>
<div id="Loading"></div> <div id="Loading"></div>
<script type="module"> <script type="module">
//@ts-check
const is_debug_mode = /^localhost|127.0.0.1/.test(
window.location.hostname
);
/** /**
* markdown parser. Remove if you don't use markdown * markdown parser. Remove if you don't use markdown
*/ */
// @ts-ignore // @ts-ignore
import { micromark } from "https://esm.sh/micromark@3?bundle"; import { micromark } from "https://esm.sh/micromark@3?bundle";
/**
* A small utility to query elements and get back an array
*/
const $ = (parent, selector) => [
...(!selector
? document.querySelectorAll(parent)
: parent.querySelectorAll(selector)),
];
/**
* Assumes a provided url is external if it begins by a known protocol
* @param {string} url
*/
const isExternal = (url) =>
/^(https?|mailto|tel|ftp|ipfs|dat):/.test(url);
const rewriteLocalUrls = (container) => {
$(container, "a").forEach((a) => {
const href = a.getAttribute("href");
if (href && !isExternal(href)) {
console.log({ href });
const rewrittenHref = "#/" + href.replace(/^\.?\//, "");
a.setAttribute("href", rewrittenHref);
console.log(a);
console.log(rewrittenHref);
}
});
};
/** /**
* useful to check for transitions while developing styles, if the loading screen disappears too fast * useful to check for transitions while developing styles, if the loading screen disappears too fast
* *
@ -177,10 +212,12 @@
*/ */
const mainTitle = document.title; const mainTitle = document.title;
const startLoading = () => document.body.classList.add("is-loading"); const showLoadingOverlay = () =>
const stopLoading = () => document.body.classList.remove("is-loading"); document.body.classList.add("is-loading");
const hideLoadingOverlay = () =>
document.body.classList.remove("is-loading");
const getCurrentPage = () => { const getCurrentHashUrl = () => {
const [path, searchStr] = ( const [path, searchStr] = (
window.location.hash[1] === "/" ? window.location.hash.slice(2) : "" window.location.hash[1] === "/" ? window.location.hash.slice(2) : ""
).split("?"); ).split("?");
@ -189,24 +226,27 @@
}; };
const onHashChange = (evt) => { const onHashChange = (evt) => {
const { path, params } = getCurrentPage(); const { path, params } = getCurrentHashUrl();
if (!path) { if (!path) {
return false; return false;
} }
startLoading(); showLoadingOverlay();
return fetch(`./${path}`) return fetch(
is_debug_mode ? `./${path}?rand=${Math.random()}` : `./${path}`
)
.then((response) => response.text()) .then((response) => response.text())
.then(wait) .then(wait)
.then((text) => { .then((text) => {
const [, title] = text.match(/^(#\s\w+)/) || const [, title] = text.match(/^#\s+(\w+.+)/) ||
text.match(/(.*?)\n===+/m) || [, path]; text.match(/(.*?)\n===+/m) || [, path];
document.title = `${title} | ${mainTitle}`; document.title = `${title} | ${mainTitle}`;
if (params.has("source")) { if (params.has("source")) {
Body.innerHTML = `<pre>${text}</pre>`; Body.innerHTML = `<pre>${text}</pre>`;
} else { } else {
Body.innerHTML = micromark(text); Body.innerHTML = micromark(text);
rewriteLocalUrls(Body);
} }
stopLoading(); hideLoadingOverlay();
}); });
}; };
@ -216,7 +256,8 @@
* Loads the article list, parses it, creates the menu items * Loads the article list, parses it, creates the menu items
*/ */
const start = () => { const start = () => {
startLoading(); let hasAutoloadedFirstPage = false;
showLoadingOverlay();
fetch("./files.txt") fetch("./files.txt")
.then((response) => response.text()) .then((response) => response.text())
.then((lines) => { .then((lines) => {
@ -225,7 +266,7 @@
.map((line, index) => { .map((line, index) => {
const today = new Date().toISOString().split("T")[0]; const today = new Date().toISOString().split("T")[0];
const result = line.match( const result = line.match(
/(?<name>.+)\.(?<ext>\w{2,3})(?:\s(?<date>[\d-]+)?(?<title>.+))?/ /(?<name>.+)\.(?<ext>\w{2,3})(?:\s+(?<date>[\d-]+)?(?<title>.+))?/
); );
if (!result) { if (!result) {
console.log(`could not parse line ${index}: [${line}]`); console.log(`could not parse line ${index}: [${line}]`);
@ -235,20 +276,22 @@
groups: { name, ext, date = today, title = name }, groups: { name, ext, date = today, title = name },
} = result; } = result;
const href = `/${name}.${ext}`; const href = `/${name}.${ext}`;
if (!getCurrentPage().path) { if (!getCurrentHashUrl().path) {
hasAutoloadedFirstPage = true;
window.location.hash = `#${href}`; window.location.hash = `#${href}`;
} }
console.log({ name, href, date, title }); const date_unix = new Date(date).getTime();
return { name, href, date, title }; return { name, href, date, title, date_unix };
}) })
.filter(Boolean) .filter(Boolean)
.sort(({ date: a }, { date: b }) => a - b) .sort(({ date_unix: a }, { date_unix: b }) => a - b)
.map( .map(
({ href, title }) => `<a data-link href="#${href}">${title}</a>` ({ href, title }) => `<a data-link href="#${href}">${title}</a>`
) )
.join(`\n`); .join(`\n`);
if (!hasAutoloadedFirstPage) {
onHashChange(); onHashChange();
}
}); });
}; };

View File

@ -31,8 +31,8 @@ We have a [neat little UI to help you do all of that](https://git.poto.cafe/yagi
Here are more detailed explanations, for different knowledge levels. Here are more detailed explanations, for different knowledge levels.
- [I do not care about tech stuff, I just want to publish](/#/tutorial-publishers.md) - [I do not care about tech stuff, I just want to publish](tutorial-publishers.md)
- [I can write some code, give me detailed explanations](/#/tutorial-hackers.md) - [I can write some code, give me detailed explanations](tutorial-hackers.md)
It's important to know that Tickle is an *idea*. Think of it as a specification. We have a few examples listed [here](examples.md) It's important to know that Tickle is an *idea*. Think of it as a specification. We have a few examples listed [here](examples.md)