aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <mforoud86@gmail.com> 2026-01-01 11:50:48 +0330
committerGravatar Moon Flower <mforoud86@gmail.com> 2026-01-01 11:50:48 +0330
commit0cee860019a7475c46eeb68271ef62beccff4fc7 (patch)
tree0625f4395736b0a2ba1bbbd5093ffb280c9dcd98
parentupdate log update (diff)
sw+firstpaint+smooth+nostyles3
-rw-r--r--index.html23
-rw-r--r--serviceWorker.js61
-rw-r--r--styles.css56
-rw-r--r--styles3.css258
-rw-r--r--tempo.md9
5 files changed, 98 insertions, 309 deletions
diff --git a/index.html b/index.html
index 04f7bc3..c178483 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
<html lang='en'>
<head>
- <style>
+ <style id="noFlashbang">
body {
background: #000;
color: #fff;
@@ -13,7 +13,7 @@
<title>tempo</title>
<link rel="prefetch" href="/tempo.md" as="fetch">
<link rel="prefetch" href="/symbols.txt" as="fetch">
- <link rel="stylesheet" href="styles3.css">
+ <link rel="stylesheet" href="styles.css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" href="bell.png">
</head>
@@ -50,6 +50,12 @@
localStorage.setItem('theme', 'light')
}
})
+
+ window.addEventListener('load', () => {
+ noFlashbang.innerHTML += `*, body, html {
+ transition: 0.25s color, 0.25s background-color, 0.25s border;
+ }`
+ })
</script>
<noscript>
@@ -65,6 +71,7 @@
<div id='warnings'></div>
<div id='content'>
rendering content...
+ <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</div>
<div>
tempo is licensed under creative-commons.
@@ -84,8 +91,15 @@
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/serviceWorker.js')
- .then(reg => console.log('Service Worker registered'))
- .catch(err => console.log('SW registration failed', err))
+ .then(reg => console.log('sw registered'))
+ .catch(err => console.log('sw register failed', err))
+
+ navigator.serviceWorker.addEventListener('message', e => {
+ if (e.data && e.data.type === 'REFRESH') {
+ console.log(`updated content found for ${e.data.url}`)
+ window.location.reload()
+ }
+ })
})
} else {
console.log('[warn] no service worker support')
@@ -113,6 +127,7 @@
if (i % 2 === 0) {
let chunk = escapeHTML(parts[i])
chunk = chunk.replace(/\*\*(.*?)\*\*/g, '<b>$1</b>')
+ chunk = chunk.replace(/\~\~(.*?)\~\~/g, '<s>$1</s>')
chunk = chunk.replace(/__(.*?)__/g, '<u>$1</u>')
chunk = chunk.replace(/\*(.*?)\*/g, '<i>$1</i>')
chunk = chunk.replace(/\[\[(.*?)\]\]/g, '<span style="user-select:none">🔎 </span><b>"$1"</b>')
diff --git a/serviceWorker.js b/serviceWorker.js
index ba9ca7a..ce8ed7e 100644
--- a/serviceWorker.js
+++ b/serviceWorker.js
@@ -23,30 +23,59 @@ self.addEventListener('activate', e => {
e.waitUntil(self.clients.claim())
})
+const checkChange = (r1, r2) => {
+ const h1 = r1.headers
+ const h2 = r2.headers
+ if (h1.get('etag') && h2.get('etag')) return h1.get('etag') !== h2.get('etag')
+ if (h1.get('last-modified') && h2.get('last-modified')) return h1.get('last-modified') !== h2.get('last-modified')
+ return h1.get('content-length') !== h2.get('content-length')
+}
+
self.addEventListener('fetch', e => {
const url = new URL(e.request.url)
const isTarget = ASSETS.includes(url.pathname) || url.pathname.startsWith('/fonts/')
if (!isTarget) return
- e.respondWith(
- caches.open(CACHE_NAME).then(async cache => {
- const cachedResponse = await cache.match(e.request)
+ e.respondWith((async () => {
+ const cache = await caches.open(CACHE_NAME)
+ const cachedResponse = await cache.match(e.request)
+
+ const networkFetch = fetch(e.request, { cache: 'no-cache' }).then(async networkResponse => {
+ if (!networkResponse.ok) return networkResponse
+
+ const freshCopy = networkResponse.clone()
+ let changed = false
- if (cachedResponse) console.log(`cache ${url.pathname}`)
- else console.log(`fetch ${url.pathname}`)
+ if (cachedResponse) {
+ changed = checkChange(cachedResponse, networkResponse)
+ } else {
+ console.log(`fetch ${url.pathname}`)
+ }
- const networkFetch = fetch(e.request).then(networkResponse => {
- if (networkResponse.ok) {
- console.log(`updating ${url.pathname}`)
- cache.put(e.request, networkResponse.clone())
- }
- return networkResponse
- }).catch(err => {
- console.error(`failed ${url.pathname}:`, err)
- })
+ await cache.put(e.request, freshCopy)
- return cachedResponse || networkFetch
+ if (changed) {
+ console.log(`content changed, signaling refresh: ${url.pathname}`)
+ const clients = await self.clients.matchAll()
+ clients.forEach(client => {
+ client.postMessage({
+ type: 'REFRESH',
+ url: url.pathname
+ })
+ })
+ }
+ return networkResponse
+ }).catch(err => {
+ console.error(`failed ${url.pathname}:`, err)
})
- )
+
+ if (cachedResponse) {
+ console.log(`cache ${url.pathname}`)
+ e.waitUntil(networkFetch)
+ return cachedResponse
+ }
+
+ return networkFetch
+ })())
}) \ No newline at end of file
diff --git a/styles.css b/styles.css
index c150343..5368a60 100644
--- a/styles.css
+++ b/styles.css
@@ -1,29 +1,29 @@
@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Regular.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
+ font-family: 'Charter';
+ src: url('fonts/Charter/Charter Regular.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
}
@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Italic.ttf') format('truetype');
- font-weight: normal;
- font-style: italic;
+ font-family: 'Charter';
+ src: url('fonts/Charter/Charter Italic.ttf') format('truetype');
+ font-weight: normal;
+ font-style: italic;
}
@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Bold.ttf') format('truetype');
- font-weight: bold;
- font-style: normal;
+ font-family: 'Charter';
+ src: url('fonts/Charter/Charter Bold.ttf') format('truetype');
+ font-weight: bold;
+ font-style: normal;
}
@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Bold Italic.ttf') format('truetype');
- font-weight: bold;
- font-style: italic;
+ font-family: 'Charter';
+ src: url('fonts/Charter/Charter Bold Italic.ttf') format('truetype');
+ font-weight: bold;
+ font-style: italic;
}
@font-face {
@@ -81,18 +81,18 @@ body.dark-mode {
top: 20px;
right: 20px;
padding: 8px 16px;
- background: var(--code-bg);
+ background-color: var(--code-bg);
border: 1px solid var(--border);
cursor: pointer;
font-family: 'Roboto Mono', monospace;
font-size: 0.85rem;
border-radius: 4px;
z-index: 1000;
- transition: 0.5s background;
+ transition: 0.5s background-color;
}
#themeToggle:hover {
- background: var(--code-bg-faint);
+ background-color: var(--code-bg-faint);
}
a {
@@ -113,7 +113,7 @@ body {
max-width: 720px;
margin: 40px auto;
padding: 0 20px;
- background: var(--bg);
+ background-color: var(--bg);
}
h1 {
@@ -133,7 +133,7 @@ h2 {
code {
font-family: "Roboto Mono", "Charter", serif;
- background: var(--code-bg);
+ background-color: var(--code-bg);
padding: 0px 8px;
/* border-radius: 3px; */
font-size: 0.95em;
@@ -143,7 +143,7 @@ code {
}
pre {
- background: var(--code-bg);
+ background-color: var(--code-bg);
padding: 1.5rem;
border-left: 3px solid var(--accent);
overflow-x: auto;
@@ -154,7 +154,7 @@ pre {
}
pre code {
- background: transparent;
+ background-color: transparent;
padding: 0;
border: none;
font-size: 0.9rem;
@@ -175,7 +175,7 @@ block {
display: block;
margin-bottom: 1.5rem;
padding: 1rem;
- background: var(--block-bg);
+ background-color: var(--block-bg);
border: 1px solid var(--border);
}
@@ -195,7 +195,7 @@ header {
header span.def-name {
color: var(--def-name);
- background: var(--eng-bg);
+ background-color: var(--eng-bg);
padding: 0px 8px;
border: 1px solid var(--border);
font-size: 0.95em;
@@ -207,7 +207,7 @@ header span.def-name {
.eng-text {
font-weight: normal;
color: var(--eng-text);
- background: var(--eng-bg);
+ background-color: var(--eng-bg);
padding: 0px 8px;
border: 1px solid var(--border);
font-size: 0.95em;
@@ -228,7 +228,7 @@ desc {
align-items: center;
gap: 8px;
padding: 6px 12px;
- background: var(--code-bg);
+ background-color: var(--code-bg);
border: 2.3px dashed #ff6600;
border-radius: 20px;
font-family: "Roboto Mono", monospace;
@@ -252,7 +252,7 @@ body.dark-mode .timestamp-badge {
bottom: 20px;
left: 20px;
color: red;
- background: var(--code-bg);
+ background-color: var(--code-bg);
border: 2px solid var(--code-bg-faint);
padding: 5px 10px;
} \ No newline at end of file
diff --git a/styles3.css b/styles3.css
deleted file mode 100644
index c150343..0000000
--- a/styles3.css
+++ /dev/null
@@ -1,258 +0,0 @@
-@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Regular.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
-}
-
-@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Italic.ttf') format('truetype');
- font-weight: normal;
- font-style: italic;
-}
-
-@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Bold.ttf') format('truetype');
- font-weight: bold;
- font-style: normal;
-}
-
-@font-face {
- font-family: 'Charter';
- src: url('fonts/Charter/Charter Bold Italic.ttf') format('truetype');
- font-weight: bold;
- font-style: italic;
-}
-
-@font-face {
- font-family: "Roboto Mono";
- src: url("fonts/Roboto/RobotoMono-VariableFont_wght.ttf") format("truetype");
- font-weight: 100 900;
- font-style: normal;
-}
-
-@font-face {
- font-family: "Roboto Mono";
- src: url("fonts/Roboto/RobotoMono-Italic-VariableFont_wght.ttf") format("truetype");
- font-weight: 100 900;
- font-style: italic;
-}
-
-:root {
- --bg: #ffffff;
- --text: #000000;
- --accent: #000000;
- --code-bg: #fafafa;
- --code-bg-faint: #f4f4f4;
- --border: #d0d0d0;
- --def-name: #ff6600;
- --link: #00aaee;
- --link-hover: #0088ff;
- --quote-text: #333;
- --desc-text: #222;
- --badge-text: #444;
- --eng-text: #666;
- --eng-bg: #fdfdfd;
- --block-bg: #ffffff;
-}
-
-body.dark-mode {
- --bg: #050505;
- --text: #e0e0e0;
- --accent: #ffffff;
- --code-bg: #101010;
- --code-bg-faint: #2a2a2a;
- --border: #404040;
- --def-name: #ff5f33;
- --link: #33bbff;
- --link-hover: #55ccff;
- --quote-text: #b0b0b0;
- --desc-text: #d0d0d0;
- --badge-text: #cfcfcf;
- --eng-text: #999;
- --eng-bg: #111;
- --block-bg: #1f1f1f;
-}
-
-#themeToggle {
- position: fixed;
- top: 20px;
- right: 20px;
- padding: 8px 16px;
- background: var(--code-bg);
- border: 1px solid var(--border);
- cursor: pointer;
- font-family: 'Roboto Mono', monospace;
- font-size: 0.85rem;
- border-radius: 4px;
- z-index: 1000;
- transition: 0.5s background;
-}
-
-#themeToggle:hover {
- background: var(--code-bg-faint);
-}
-
-a {
- /* text-decoration: none; */
- color: var(--link);
- transition: 0.5s color;
-}
-
-a:hover {
- color: var(--link-hover);
-}
-
-body {
- font-family: "Charter", "Bitstream Charter", "Sitka Text", Georgia, serif;
- font-weight: 400;
- line-height: 1.6;
- color: var(--text);
- max-width: 720px;
- margin: 40px auto;
- padding: 0 20px;
- background: var(--bg);
-}
-
-h1 {
- font-size: 2.2rem;
- font-weight: 700;
- text-align: center;
- margin-bottom: 0.5rem;
- letter-spacing: -0.02em;
-}
-
-h2 {
- font-variant: small-caps;
- border-bottom: 2px solid #ff5b5b;
- margin-top: 2rem;
- letter-spacing: 0.05em;
-}
-
-code {
- font-family: "Roboto Mono", "Charter", serif;
- background: var(--code-bg);
- padding: 0px 8px;
- /* border-radius: 3px; */
- font-size: 0.95em;
- border: 1px solid var(--border);
- font-weight: 450 !important;
- margin: 0 2px;
-}
-
-pre {
- background: var(--code-bg);
- padding: 1.5rem;
- border-left: 3px solid var(--accent);
- overflow-x: auto;
- /* border-radius: 0 4px 4px 0; */
- white-space: pre;
- border: 1px solid var(--border);
- border-left-width: 3px;
-}
-
-pre code {
- background: transparent;
- padding: 0;
- border: none;
- font-size: 0.9rem;
-}
-
-pre * {
- font-family: "Roboto Mono", monospace !important;
-}
-
-blockquote {
- margin: 1rem 0;
- padding-left: 1.5rem;
- border-left: 2px solid var(--border);
- color: var(--quote-text);
-}
-
-block {
- display: block;
- margin-bottom: 1.5rem;
- padding: 1rem;
- background: var(--block-bg);
- border: 1px solid var(--border);
-}
-
-header {
- display: flex;
- justify-content: space-between;
- align-items: baseline;
- font-weight: bold;
- font-family: "Charter", serif;
-}
-
-.header-left {
- display: flex;
- align-items: baseline;
- gap: 8px;
-}
-
-header span.def-name {
- color: var(--def-name);
- background: var(--eng-bg);
- padding: 0px 8px;
- border: 1px solid var(--border);
- font-size: 0.95em;
- /* border-radius: 2px; */
- font-weight: normal;
- font-family: 'Roboto Mono';
-}
-
-.eng-text {
- font-weight: normal;
- color: var(--eng-text);
- background: var(--eng-bg);
- padding: 0px 8px;
- border: 1px solid var(--border);
- font-size: 0.95em;
-}
-
-desc {
- display: block;
- margin-top: 0.5rem;
- font-size: 0.95rem;
- color: var(--desc-text);
- padding-left: 32px;
-}
-
-.timestamp-badge {
- /* margin-top: -10px !important; */
- margin-bottom: -10px !important;
- display: inline-flex;
- align-items: center;
- gap: 8px;
- padding: 6px 12px;
- background: var(--code-bg);
- border: 2.3px dashed #ff6600;
- border-radius: 20px;
- font-family: "Roboto Mono", monospace;
- font-size: 0.85rem;
- color: var(--badge-text);
- margin: 1rem 0;
- user-select: none;
-}
-
-.timestamp-badge .clock {
- filter: grayscale(100%);
-}
-
-body.dark-mode .timestamp-badge {
- border-color: #ff8833;
-}
-
-#warnings {
- display: block;
- position: fixed;
- bottom: 20px;
- left: 20px;
- color: red;
- background: var(--code-bg);
- border: 2px solid var(--code-bg-faint);
- padding: 5px 10px;
-} \ No newline at end of file
diff --git a/tempo.md b/tempo.md
index 8b96af3..87ec277 100644
--- a/tempo.md
+++ b/tempo.md
@@ -29,7 +29,7 @@ in tempo, everything is interpreted as left-to-right.
an axiom can have 0 to an arbitrary number of inputs, which indicates that the axiom is basically a catch-all. arguments are taken in the format of `[arg1 arg2 arg3 ...]` in the definition.
the usage section of an axiom describes how arguments are taken in.
-the complex axiom assertion bears a cognitive load: it allows assigning names to the time slice of an axiom. for example: `A = .` returns a random (or non-random) object in the enclosing set of the context.
+the composite axiom assertion bears a cognitive load: it allows assigning names to the time slice of an axiom. for example: `A = .` returns a random (or non-random) object in the enclosing set of the context.
in our world, this could be an atom, an apple, an idea, a time, a memory, a sound, anything.
it also serves as a filter, in which `A=. A=.\prop\\me\apple` would filter the first statement, `A=.`, such that A is a property of an apple (since tempo doesn't define apples yet, we contractually import it from our own language as `\me\apple`).
@@ -243,9 +243,10 @@ def \matter\ `A=. A\neq\0 \static\\id\A A\almost\\energy\`
- more coming soon.
// Timestamp: 2026-01-01 10:36:31 UTC+3:30
-- added a git hook such that pushing the repository automatically updates the website as well.
+- added a smooth css transition for theme changing.
+- added a service worker with a serve-cache-then-update strategy. ~~this means you might need two refreshes of the website for new content~~ (the website auto-reloads on new content), but it's worth it.
- added first-paint rendering so that you get the content as fast as possible, without having to wait for a full markdown render.
-- added a service worker with a serve-cache-then-update strategy. this means you might need two refreshes of the website for new content, but it's worth it.
+- added a git hook such that pushing the repository automatically updates the website as well.
// Timestamp: 2025-12-30 22:19:43 UTC+3:30
- added a few new axioms. moved old ones around.
@@ -286,4 +287,6 @@ thank you for reading.
this website is configured in a way such that web scrapers will be able to archive all of its contents, including the <a href="tempo.md">tempo.md</a> file. a copy of tempo can be found on the wayback machine.
+this website has a git repository on <a href="https://git.coffin.ir/moon/tempo">my git mirror</a>.
+
email: moon@coffin.ir \ No newline at end of file