aboutsummaryrefslogtreecommitdiff
path: root/assets
diff options
context:
space:
mode:
Diffstat (limited to 'assets')
-rw-r--r--assets/css/default-fast.css5
-rw-r--r--assets/css/default-mathml.css26
-rw-r--r--assets/css/default-simple.css79
-rw-r--r--assets/css/default-syntax.css (renamed from assets/css/syntax-highlight-default.css)92
-rw-r--r--assets/css/default.css2389
-rw-r--r--assets/data/media/logo.pngbin170667 -> 9839 bytes
-rw-r--r--assets/js/index.js1153
-rw-r--r--assets/schemas/atom-v1.0.rng605
-rw-r--r--assets/schemas/jsonfeed-v1.1.json297
-rw-r--r--assets/schemas/rss-v2.0.rng86
-rw-r--r--assets/schemas/rss-v2.0.xsd383
-rw-r--r--assets/schemas/sitemap-v0.9.xsd111
-rw-r--r--assets/schemas/sitemapindex-v0.9.xsd71
-rw-r--r--assets/templates/author.yaml15
-rw-r--r--assets/templates/markdown-feed.yaml19
15 files changed, 4319 insertions, 1012 deletions
diff --git a/assets/css/default-fast.css b/assets/css/default-fast.css
new file mode 100644
index 0000000..8d9d4d1
--- /dev/null
+++ b/assets/css/default-fast.css
@@ -0,0 +1,5 @@
+@keyframes paint {
+ 0% {
+ opacity: 1;
+ }
+}
diff --git a/assets/css/default-mathml.css b/assets/css/default-mathml.css
new file mode 100644
index 0000000..4aa437a
--- /dev/null
+++ b/assets/css/default-mathml.css
@@ -0,0 +1,26 @@
+@namespace mathml url(http://www.w3.org/1998/Math/MathML);
+
+mathml|math {
+ display: block;
+ display: block math;
+}
+
+mathml|mtd {
+ display: flex;
+ justify-content: center;
+ padding-right: 0.4em;
+ padding-left: 0.4em;
+ padding-bottom: 0.5rem;
+ padding-top: 0.5rem;
+}
+
+@-moz-document url-prefix() {
+ mathml|mtd {
+ display: flex;
+ justify-content: center;
+ padding-right: 0.4em;
+ padding-left: 0.4em;
+ padding-bottom: 0.5ex;
+ padding-top: 0.5ex;
+ }
+}
diff --git a/assets/css/default-simple.css b/assets/css/default-simple.css
new file mode 100644
index 0000000..29f7c0d
--- /dev/null
+++ b/assets/css/default-simple.css
@@ -0,0 +1,79 @@
+column-base[position="left"],
+column-base[position="right"] {
+ opacity: 0.1;
+ transition: 2s;
+}
+
+column-base[position="left"]:hover,
+column-base[position="right"]:hover {
+ opacity: 0.9;
+ transition: 0.1s;
+}
+
+micro-card[id] > header,
+micro-card[id] article math-ml figcaption {
+ display: block;
+}
+
+micro-card[id] {
+ flex-direction: row;
+ padding: 1.25rem 1rem;
+}
+
+micro-card[id] > article {
+ margin: auto 0;
+ min-width: 0;
+}
+
+micro-card[id] > article > * {
+ width: 100%;
+}
+
+micro-card[id] > article > :nth-last-child(2) {
+ margin-bottom: 0;
+}
+
+micro-card[id] micro-tags,
+micro-card[id] > header meta-data,
+micro-card[id] > article figcaption,
+[data-kind="page"] micro-card[id]:first-child > a {
+ display: none;
+}
+
+micro-card[id]
+ > article
+ footer:not(blockquote footer):not(code-block + footer) {
+ display: none;
+}
+
+micro-card[id] > a {
+ display: inline;
+ height: 100%;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ z-index: 1;
+}
+
+micro-card[id] > a:focus {
+ background-color: transparent !important;
+ outline-offset: -0.15rem !important;
+}
+
+micro-card[id] article p,
+micro-card[id] article ul,
+micro-card[id] article dl,
+micro-card[id] article h1,
+micro-card[id] article h2,
+micro-card[id] article h3,
+micro-card[id] article video,
+micro-card[id] article iframe,
+micro-card[id] article article,
+micro-card[id] article details,
+micro-card[id] article figcaption,
+micro-card[id] header picture {
+ pointer-events: all;
+ position: relative;
+ z-index: 2;
+}
diff --git a/assets/css/syntax-highlight-default.css b/assets/css/default-syntax.css
index 0208323..e6f7021 100644
--- a/assets/css/syntax-highlight-default.css
+++ b/assets/css/default-syntax.css
@@ -1,63 +1,89 @@
-/* ----- Colors ----- */
-
/* ----- Format ----- */
.chroma .hl {
- display: block;
padding: 0 0.5rem;
margin: 0 -0.5rem;
}
+.chroma .line {
+ display: block;
+}
+
+.chroma .hl > .cl:before,
+.chroma .ln a:hover:before,
+.chroma .ln:target a:before,
+.chroma .line > .cl:hover:before {
+ content: "";
+ position: absolute;
+ height: 1.5rem;
+ width: 100%;
+ left: 0;
+ z-index: -1;
+}
+
.chroma .ln a {
- background-color: #edf2f7;
- padding: 0.25rem 0.75rem;
+ padding: 0.05rem 0.75rem;
margin: 0 1rem 0 -0.75rem;
user-select: none;
+ text-decoration: none;
+ display: inline-block;
}
-.chroma .ln a:hover {
+.chroma .ln a:hover,
+.chroma .ln:target a {
outline: 0.15rem solid !important;
outline-offset: -0.3rem;
}
+.chroma .line .cl:hover {
+ text-shadow: 0 0 currentColor;
+}
+
+.chroma .ln a:hover:before,
+.chroma .ln:target a:before,
+.chroma .line > .cl:hover:before {
+ background-color: #f2f2f2;
+}
+
+code-block code {
+ position: relative;
+}
+
code-block button {
border: 1px solid #ccc;
- display: none;
}
-.chroma .line:hover {
- background-color: #f2f2f2;
- display: block;
+code-block header language-label a,
+code-block header language-label a:hover {
+ color: #111;
}
/* ------ Tokens ------ */
:root {
- --code-chroma-background: #ffffff;
- --code-chroma-foreground: #333333;
- --code-chroma-error-background: #960050;
- --code-chroma-error-foreground: #960050;
- --code-chroma-label-background: #006894;
- --code-chroma-label-foreground: #e6e6e6;
- --code-chroma-line-highlight: #d9ddf2;
- --code-chroma-line-number: #375462;
- --code-chroma-line: var(--code-chroma-foreground);
-}
-
-/* ChromaForeground */ code-block, .chroma, .highlight { color: #333333; color: var(--code-chroma-foreground); }
-/* ChromaBackground */ code-block button, .chroma { background-color: #ffffff; background-color: var(--code-chroma-background); }
-/* ChromaErrorBackground */ .chroma .err { color: #960050; color: var(--code-chroma-error-background); }
-/* ChromaErrorForeground */ .chroma .err { color: #960050; color: var(--code-chroma-error-foreground); }
-/* ChromaLabelBackground */ .chroma code:before { background-color: #006894; background-color: var(--code-chroma-label-background); }
-/* ChromaLabelForeground */ .chroma code:before { color: #e6e6e6; color: var(--code-chroma-label-foreground); }
-/* ChromaLine */ .chroma .line { color: #333333; color: var(--code-chroma-line); }
-/* ChromaLineHighlight */ .chroma .hl { background-color: #d9ddf2; background-color: var(--code-chroma-line-highlight); }
-/* ChromaLineNumber */ .chroma .ln a { color: #375462 !important; color: var(--code-chroma-line-number) !important; }
-
-.chroma .hl {
- background-color: #fff8c5;
+--code-chroma-background: #ffffff;
+--code-chroma-foreground: #333333;
+--code-chroma-error-background: #960050;
+--code-chroma-error-foreground: #960050;
+--code-chroma-label-background: #006894;
+--code-chroma-label-foreground: #e6e6e6;
+--code-chroma-line-highlight: #fff8c5;
+--code-chroma-line-number: #375462;
+--code-chroma-line-number-background: #edf2f7;
+--code-chroma-line: var(--code-chroma-foreground);
}
+/* ChromaForeground */ code-block, .chroma, .highlight { color: #333333; color: var(--code-chroma-foreground); }
+/* ChromaBackground */ code-block button, .chroma { background-color: #ffffff; background-color: var(--code-chroma-background); }
+/* ChromaErrorBackground */ .chroma .err { color: #960050; color: var(--code-chroma-error-background); }
+/* ChromaErrorForeground */ .chroma .err { color: #960050; color: var(--code-chroma-error-foreground); }
+/* ChromaLabelBackground */ .chroma code:before { background-color: #006894; background-color: var(--code-chroma-label-background); }
+/* ChromaLabelForeground */ .chroma code:before { color: #e6e6e6; color: var(--code-chroma-label-foreground); }
+/* ChromaLine */ .chroma .line { color: #333333; color: var(--code-chroma-line); }
+/* ChromaLineHighlight */ .chroma .hl > span:before { background-color: #fff8c5; background-color: var(--code-chroma-line-highlight); }
+/* ChromaLineNumber */ .chroma .ln a { color: #375462 !important; color: var(--code-chroma-line-number) !important; }
+/* ChromaLineNumberBackground */ .chroma .ln a { background-color: #edf2f7; background-color: var(--code-chroma-line-number-background); }
+
:root {
--code-comment: #4f4f4f;
--code-comment-hashbang: var(--code-comment);
diff --git a/assets/css/default.css b/assets/css/default.css
index 157543d..d3d2b6f 100644
--- a/assets/css/default.css
+++ b/assets/css/default.css
@@ -20,79 +20,109 @@
text-shadow: 0 0 currentColor;
}
+@media (prefers-color-scheme: dark) {
+ ::selection {
+ color: #000;
+ background-color: #aaa;
+ text-shadow: 0 0 currentColor;
+ }
+
+ ::-webkit-selection {
+ color: #000;
+ background-color: #aaa;
+ text-shadow: 0 0 currentColor;
+ }
+
+ ::-moz-selection {
+ color: #000;
+ background-color: #aaa;
+ text-shadow: 0 0 currentColor;
+ }
+}
+
/* ----- Colors ----- */
:root {
- color-scheme: light dark;
- --active-background-alternate: #cce1ff;
- --background-bolder: #fff;
- --background-transparent: rgba(255, 255, 255, 0.9);
- --background: #fefefe;
- --border-darker: #ccc;
- --border-lighter: #eee;
- --button-background: #fff;
+ --primary: 230;
+ --secondary: 258;
+ --accent: 217;
+ --background-bolder: hsl(var(--secondary), 99%, 98%);
+ --background: hsl(var(--secondary), 99%, 99%);
+ --border-darker: hsl(var(--primary), 35%, 80%);
+ --border-darkest: hsl(var(--primary), 35%, 70%);
+ --border-lighter: hsl(var(--primary), 35%, 92%);
+ --button-background: hsl(var(--primary), 0%, 100%);
--danger-background-lighter: #fff5f5;
--danger-background: #fcd2cf;
--danger: #8f0000;
- --disabled: #999;
- --fade: #555;
- --focus-within-background: #f0ecf9;
- --foreground: #111;
- --hover-background-alternate: #ebf3ff;
- --hover-background: #eee;
- --input-background: #eff3f4;
- --link: #0149bc;
- --shadow: #999;
- --spoiler: #333;
+ --fade: hsl(var(--primary), 35%, 30%);
+ --focus-within-background: hsl(var(--secondary), 52%, 95%);
+ --foreground: hsl(var(--primary), 99%, 5%);
+ --hover-background-alternate: hsl(var(--accent), 100%, 96%);
+ --hover-background: hsl(var(--secondary), 25%, 94%);
+ --icon-focus-background: var(--icon-hover-background);
+ --icon-hover-background: hsl(var(--accent), 100%, 90%);
+ --link: hsl(var(--accent), 99%, 37%);
+ --shadow: #00000060;
+ --spoiler: hsl(var(--primary), 0%, 27%);
--success-background: #d5f3c4;
--success: #1d3c0c;
- --table-row-even-background: #f9f9f9;
- --table-row-odd-background: #f3f3f3;
+ --table-even-background: hsl(var(--secondary), 25%, 99%);
+ --table-odd-background: hsl(var(--secondary), 25%, 97%);
+ --text-background: var(--background);
--warning-background: #ffe699;
--warning: #332600;
- --widget-background: #f9f9f9;
+ --widget-background: hsl(var(--secondary), 25%, 97%);
+ color-scheme: light;
}
@media (prefers-color-scheme: dark) {
:root {
- --active-background-alternate: #425a8a;
- --background-bolder: #0d0d0d;
- --background-transparent: rgba(28, 28, 28, 0.9);
- --background: #111;
- --border-darker: #555;
- --border-lighter: #262626;
- --button-background: #333;
- --danger-background-lighter: #1b0404;
+ --primary: 0;
+ --secondary: 0;
+ --accent: 219;
+ --background-bolder: hsl(var(--secondary), 0%, 5%);
+ --background: hsl(var(--secondary), 0%, 7%);
+ --border-darker: hsl(var(--secondary), 0%, 33%);
+ --border-darkest: hsl(var(--secondary), 0%, 60%);
+ --border-lighter: hsl(var(--secondary), 0%, 15%);
+ --button-background: hsl(var(--secondary), 0%, 20%);
+ --danger-background-lighter: #261717;
--danger-background: #4f1c1c;
--danger: #ff9494;
- --disabled: #999;
- --fade: #aaa;
+ --fade: hsl(var(--secondary), 0%, 66%);
--focus-within-background: #291933;
- --foreground: #ddd;
+ --foreground: hsl(var(--secondary), 0%, 87%);
--hover-background-alternate: #1c263a;
- --hover-background: #303030;
- --input-background: #333;
- --link: #a3c3ff;
- --shadow: #000;
- --spoiler: #aaa;
+ --hover-background: hsl(var(--secondary), 0%, 14%);
+ --icon-focus-background: #88aefb;
+ --icon-hover-background: hsl(var(--accent), 35%, 25%);
+ --link: hsl(var(--accent), 100%, 82%);
+ --shadow: hsl(var(--secondary), 0%, 0%);
+ --spoiler: hsl(var(--secondary), 0%, 67%);
--success-background: #2d3e0f;
--success: #d5f3c4;
- --table-row-even-background: #273030;
- --table-row-odd-background: #2e3838;
+ --table-even-background: hsl(var(--secondary), 0%, 12%);
+ --table-odd-background: hsl(var(--secondary), 0%, 9%);
+ --text-background: hsl(var(--secondary), 0%, 17%);
--warning-background: #a89700;
--warning: #000;
- --widget-background: #171717;
+ --widget-background: hsl(var(--secondary), 0%, 9%);
+ color-scheme: dark;
}
- img {
+ kbd,
+ img,
+ video,
+ figure span {
filter: brightness(75%);
}
- code-block {
+ code-block pre,
+ code-block header {
filter: invert(90%);
- display: block;
}
}
-/* ----- Psuedo ----- */
+/* ----- Pseudo ----- */
*,
::before,
@@ -106,37 +136,52 @@
vertical-align: inherit;
}
-:target::before {
- content: "";
- display: block;
- height: 4rem;
- margin-top: -4rem;
- visibility: hidden;
+html,
+:target:not(nav span) {
+ scroll-margin-top: 6rem;
}
-:not(#main):target micro-summary,
-:not(#main):target micro-summary:hover {
- background-color: transparent;
+sup:target [role="doc-noteref"][href^="#fn\:"],
+li:target [role="doc-backlink"][href^="#fnref\:"],
+:focus:not(html):not(body):not(svg):not(pre):not(#search) {
+ outline: 0.15rem solid;
+ outline-offset: 0.05rem;
+ text-decoration: none;
border-radius: 0.5rem;
- outline-offset: -6px;
- outline: 2px dashed #ccc;
- outline: 2px dashed var(--border-darker);
}
-:focus:not(html):not(body):not(svg) {
+sup:target [role="doc-noteref"][href^="#fn\:"],
+li:target [role="doc-backlink"][href^="#fnref\:"] {
+ outline-offset: 1px;
+}
+
+nav a:focus,
+button:focus,
+menu a:focus,
+code-block a:focus,
+gallery-images a:focus {
+ outline-offset: -0.2rem !important;
+}
+
+pre:hover,
+pre:focus,
+pre:focus-within {
outline: 0.15rem solid;
- outline-offset: -0.15rem;
text-decoration: none;
}
-:focus:not(html):not(body):not(pre):not(svg):not(button):not(input) {
- background-color: #ffe699;
- background-color: var(--warning-background);
- color: #111;
- color: var(--warning);
+sup:target [role="doc-noteref"][href^="#fn\:"],
+li:target [role="doc-backlink"][href^="#fnref\:"],
+:focus:not(html):not(body):not(pre):not(svg):not(button):not(input):not(video) {
+ background-color: #ffe699 !important;
+ background-color: var(--warning-background) !important;
+ color: #111 !important;
+ color: var(--warning) !important;
}
-:hover:not(a):not(s):not(img):not(summary):not(nav):not(abbr):not(form):not(code):not(mark) {
+:hover:not(a):not(s):not(span):not(img):not(summary):not(nav):not(abbr):not(
+ form
+ ):not(code):not(mark):not(td):not(nav):not(p):not(object):not(tab-bar) {
border-radius: 0.5rem;
}
@@ -157,81 +202,364 @@ skip-link a:focus {
border-radius: 0.5rem;
}
-/* ----- Elements ----- */
+/* ----- Typography ----- */
-html {
- font-size: 95%;
- line-height: 1.5;
- word-break: break-word;
- text-rendering: optimizeSpeed;
- margin-left: calc(100vw - 100%);
- margin-right: 0;
+h1,
+h2,
+h3 {
+ font-size: 100%;
+ margin: 0;
+}
+
+math {
+ font-family: "CMU Serif", serif;
+ font-size: 110%;
+}
+
+micro-card[id] article h1,
+micro-card[id] article h2,
+micro-card[id] article h3 {
+ font-family: Charter, Georgia, "Book Antiqua", serif;
+ font-size: 125%;
+ font-weight: 700;
+}
+
+micro-card[id] article h2,
+micro-card[id] article h3 {
+ font-size: 115%;
+}
+
+micro-card[id] article h3 {
+ font-style: italic;
}
html,
-samp {
+samp,
+blockquote span {
font-family: "Noto Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans",
"Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
}
-body,
-dl dl,
-dl ol,
-dl ul,
-ol dl,
-ul dl,
-ol ol,
-ol ul,
-ul ol,
-ul ul,
+pre,
+kbd,
+code,
+svg text,
+following-list details summary:after,
+micro-card article details[data-disclosure] summary:after {
+ font-size: 0.95rem;
+ font-family: "Fira Code", "Lucida Console", "Andale Mono", "Roboto Mono",
+ "Ubuntu Monospace", "Noto Mono", "Oxygen Mono", "Liberation Mono", monospace,
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+}
+
+p:not(:last-child),
+ol:not(:last-child),
+ul:not(:last-child),
+dl:not(:last-child),
+table:not(:last-child),
+figure:not(:last-child),
+code-block:not(:last-child),
+blockquote:not(:last-child),
+article > mark[id]:not(:last-child) {
+ margin-bottom: 0.75rem;
+}
+
+dd {
+ margin: 0;
+}
+
+dl {
+ margin: 0 0 0 1rem;
+}
+
+dt {
+ font-weight: 700;
+}
+
+dt:not(:first-child) {
+ margin-top: 0.5rem;
+}
+
+footer,
+figcaption {
+ color: #444;
+ color: var(--fade);
+ font-size: 85%;
+ margin: 0.5rem 0;
+ text-align: center;
+}
+
+sup,
+sub {
+ display: inline-block;
+ vertical-align: bottom;
+}
+
+sup {
+ vertical-align: text-top;
+ font-size: 85%;
+}
+
+sub {
+ font-size: 85%;
+}
+
+article > mark[id] {
+ display: block;
+}
+
+mark:target a {
+ color: inherit;
+ text-decoration-thickness: 2px;
+}
+
+mark[id] {
+ background: none;
+ color: inherit;
+}
+
+mark,
+mark:target span {
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ #ffe699 10%,
+ #ffe699 90%,
+ transparent 90%
+ );
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ var(--warning-background) 10%,
+ var(--warning-background) 90%,
+ transparent 90%
+ );
+ color: #000;
+}
+
+ins {
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ #d5f3c4 10%,
+ #d5f3c4 90%,
+ transparent 90%
+ );
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ var(--success-background) 10%,
+ var(--success-background) 90%,
+ transparent 90%
+ );
+ color: #1d3c0c;
+ color: var(--success);
+ text-decoration: none;
+}
+
+del {
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ #fcd2cf 10%,
+ #fcd2cf 90%,
+ transparent 90%
+ );
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ var(--danger-background) 10%,
+ var(--danger-background) 90%,
+ transparent 90%
+ );
+ color: #8f0000;
+ color: var(--danger);
+}
+
+s {
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ #444 10%,
+ #444 90%,
+ transparent 90%
+ );
+ background: linear-gradient(
+ to bottom,
+ transparent 10%,
+ var(--spoiler) 10%,
+ var(--spoiler) 90%,
+ transparent 90%
+ );
+ color: transparent;
+ text-decoration: none;
+}
+
+input[type="checkbox"]:checked + s {
+ background: inherit;
+ color: inherit;
+}
+
+input[type="checkbox"] {
+ -webkit-appearance: none;
+ appearance: none;
+ background-color: transparent;
+ border-radius: 25%;
+ border: 1px solid;
+ border-color: inherit;
+ height: 1.25rem;
+ margin: 0 0.25rem;
+ vertical-align: middle;
+ vertical-align: text-bottom;
+ width: 1.25rem;
+}
+
+input[type="checkbox"]:checked {
+ color: inherit;
+}
+
+input[type="checkbox"]:checked:after {
+ border-bottom-style: solid;
+ border-left-style: solid;
+ border-width: 0.4rem;
+ content: "";
+ display: block;
+ height: 100%;
+ margin: auto;
+ transform: scale(0.5, -0.5) rotateZ(145deg);
+ width: 70%;
+}
+
+blockquote {
+ color: #444;
+ color: var(--fade);
+ margin: 0;
+}
+
+blockquote p,
+blockquote p:not(:last-child) {
+ padding-left: 1rem;
+ margin: 0 0 0 1rem;
+ border-left: 2px solid;
+ border-color: #eee;
+ border-color: var(--border-darker);
+}
+
+blockquote footer {
+ text-align: right;
+ font-size: 100%;
+}
+
+video {
+ width: 100%;
+ color: #000;
+ border-radius: 0.5rem;
+ background-color: #000;
+ vertical-align: middle;
+ box-shadow: 0 0 3px #00000060;
+ box-shadow: 0 0 3px var(--shadow);
+}
+
+video[data-orientation="portrait"] {
+ width: 50%;
+}
+
+video:focus {
+ filter: brightness(100%);
+}
+
+video-container {
+ display: block;
+ text-align: center;
+}
+
+kbd {
+ background-color: #fff;
+ border-radius: 0.25rem;
+ border: 1px solid #bbb;
+ color: #333;
+ display: inline-block;
+ font-size: 0.85em;
+ font-weight: 700;
+ line-height: 1;
+ padding: 0.1rem 0.25rem;
+ white-space: nowrap;
+}
+
+/* ----- Elements ----- */
+
button,
-input,
-select,
textarea {
margin: 0;
}
ol {
- counter-reset: ol;
padding-left: 3.5rem;
+ list-style: none;
+ margin: 0;
}
ol li {
overflow-wrap: break-word;
word-break: break-word;
- list-style: none;
+ position: relative;
+ min-height: 1rem;
+}
+
+ol li + li {
+ margin-top: 0.5rem;
}
ol li:before {
- border-radius: 100%;
+ border-radius: 0.5rem;
border: 1px solid;
- content: counter(ol);
- counter-increment: ol;
- margin-left: -2rem;
+ border-color: #111;
+ border-color: var(--foreground);
font-size: 85%;
- padding: 0 0.35rem;
+ font-weight: 700;
+ opacity: 0.85;
+ padding: 0 0.5rem;
position: absolute;
+ right: 0;
+ margin-right: 100%;
+ margin-left: -100%;
+ font-variant-numeric: tabular-nums lining-nums slashed-zero;
+ height: 100%;
+ max-height: 1.5rem;
+ display: flex;
+ align-items: center;
}
-ol li + li {
- margin-top: 0.5rem;
+ol:not([start]) {
+ counter-reset: ol;
}
-main {
- min-height: 100%;
+ol:not([start]) li:before {
+ content: counter(ol);
+ counter-increment: ol;
+}
+
+ol[start] li:before {
+ content: counter(list-item);
}
-main,
details,
+summary,
code-block,
+figure span,
diagram-container {
display: block;
}
-summary {
- display: list-item;
+main {
+ display: block;
+ min-height: 80vh;
+}
+
+summary::-webkit-details-marker {
+ display: none;
}
cite {
@@ -239,13 +567,13 @@ cite {
}
ul {
- list-style: disc;
- padding-left: 2rem;
+ list-style: none;
+ padding-left: 0;
+ margin: 0;
}
nav ol,
nav ul {
- list-style: none;
display: inline-block;
padding: 0;
}
@@ -267,22 +595,16 @@ q:after {
content: "\201D";
}
-object {
- width: 100%;
- border: 1px solid #ccc;
- border: 1px solid var(--border-lighter);
- min-height: 16rem;
- border-radius: 0.5rem;
+pre code {
+ white-space: pre-line;
}
-details {
+summary,
+abbr[title] label,
+menu label {
cursor: pointer;
}
-details:hover summary span {
- text-decoration: underline;
-}
-
a {
color: #0149bc;
color: var(--link);
@@ -293,24 +615,46 @@ a {
a:hover {
color: #111;
color: var(--foreground);
+}
+
+a:hover,
+menu:hover span,
+meta-view a:hover span,
+meta-draft a:hover span,
+meta-handle a:hover span {
text-decoration-thickness: 0.15rem !important;
+ text-decoration-color: inherit !important;
}
-a:hover img {
- box-shadow: 0 0 14px #999;
- box-shadow: 0 0 14px var(--shadow);
- filter: unset;
+a[data-internal] {
+ text-decoration-color: #aaa;
+ text-decoration-thickness: 0.15rem;
+}
+
+document-attachment object {
+ width: 100%;
+ border: 2px solid #ccc;
+ border: 2px solid var(--border-darker);
+ min-height: 16rem;
+ border-radius: 0.5rem;
+ display: flex;
+ align-items: center;
+ text-align: center;
}
-column-left nav {
+document-attachment object p {
+ margin: 1rem;
+}
+
+column-base[position="left"] nav {
position: sticky;
position: -webkit-sticky;
- align-self: flex-start;
top: 0.5rem;
text-align: right;
+ font-size: 100%;
}
-column-left nav a {
+column-base[position="left"] nav a {
align-items: center;
color: inherit;
color: var(--foreground);
@@ -322,32 +666,34 @@ column-left nav a {
border-radius: 0.5rem;
}
-column-left nav li {
+column-base[position="left"] nav li {
margin-bottom: 0.25rem;
}
-column-left nav li:hover a {
+column-base[position="left"] nav li:hover a {
background-color: #eee;
background-color: var(--hover-background);
border-radius: 0.5rem;
}
-column-left nav li:hover svg {
+column-base[position="left"] nav a:hover svg {
+ fill: #cce0ff;
+ fill: var(--icon-hover-background);
+ stroke-width: 0.1rem;
+}
+
+column-base[position="left"] nav a:focus svg {
fill: #cce1ff;
- fill: var(--active-background-alternate);
+ fill: var(--icon-focus-background);
}
-column-left nav a span {
+column-base[position="left"] nav a span {
padding: 0 1rem;
}
-pre,
-kbd,
-code,
-svg text {
- font-family: "Fira Code", "Lucida Console", "Andale Mono", "Roboto Mono",
- "Ubuntu Monospace", "Noto Mono", "Oxygen Mono", "Liberation Mono", monospace,
- "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+column-base[position="left"] nav a svg {
+ height: 1.5em;
+ width: 1.5em;
}
abbr[title] {
@@ -359,10 +705,18 @@ abbr[title]:hover {
border-bottom: 2px dashed;
}
-[type="checkbox"]:checked ~ abbr[title]::after {
+input[type="checkbox"]:checked ~ abbr[title]::after {
content: " (" attr(title) ")";
}
+input[type="checkbox"]:checked ~ input[type="checkbox"] ~ abbr[title] {
+ cursor: text;
+}
+
+input[type="checkbox"]:checked ~ input[type="checkbox"] ~ abbr[title] label {
+ pointer-events: none;
+}
+
samp {
font-variant: all-small-caps;
letter-spacing: 0.05rem;
@@ -378,35 +732,35 @@ small {
opacity: 0.85;
}
-audio,
-canvas,
-iframe,
-img,
-svg,
-video {
+canvas {
vertical-align: middle;
}
-video,
audio {
width: 100%;
-}
-
-audio {
margin: 0.75rem 0;
+ vertical-align: middle;
}
figure {
text-align: center;
+ margin: 0;
+}
+
+figure object {
+ pointer-events: none;
}
iframe {
- width: 100%;
+ width: 1px;
+ min-width: 100%;
border: 2px solid #ccc;
border: 2px solid var(--border-darker);
background-color: #fefefe;
- border-radius: 0.5rem !important;
+ border-radius: 0.5rem;
min-height: 16rem;
+ user-select: none;
+ vertical-align: middle;
}
self-embed iframe {
@@ -414,27 +768,39 @@ self-embed iframe {
max-height: 11rem;
}
-img {
+img,
+figure object {
height: auto;
max-width: 100%;
- border: 1px solid #ccc;
- border: 1px solid var(--border-darker);
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
border-radius: 0.5rem;
object-fit: cover;
display: block;
+ display: flex;
+ justify-content: center;
+ align-items: center;
background-color: #fefefe;
+ user-select: none;
+ vertical-align: middle;
}
-img,
-iframe {
- user-select: none;
+img:hover,
+video:hover,
+figure span:hover {
+ box-shadow: 0 0 14px #00000060;
+ box-shadow: 0 0 14px var(--shadow);
+ filter: brightness(90%);
}
p {
- line-height: 1.35;
+ margin: 0;
}
svg {
+ vertical-align: middle;
stroke-width: 0.08rem;
}
@@ -446,31 +812,35 @@ svg:not(:root) {
overflow: hidden;
}
-button,
input {
+ margin: 0;
overflow: visible;
}
-button,
select {
text-transform: none;
+ margin: 0;
}
button,
+summary:after,
[type="reset"],
[type="button"],
[type="submit"],
micro-tags a,
-paginator-navigation a,
-micro-author micro-summary > a {
+nav[data-type="pagination"] a,
+micro-author micro-card > a {
align-items: center;
- appearance: button;
+ appearance: none;
background-color: #fff;
background-color: var(--button-background);
+ border: 1px solid;
border-radius: 0.5rem;
- border: 1px solid #ccc;
- border: 1px solid var(--border-lighter);
- box-shadow: 0 1px 1px #999;
+ border-color: #eee;
+ border-color: var(--border-darker);
+ border-top-color: var(--border-lighter);
+ border-left-color: var(--border-lighter);
+ border-right-color: var(--border-lighter);
color: inherit;
cursor: pointer;
display: flex;
@@ -478,16 +848,43 @@ micro-author micro-summary > a {
height: 1.95rem;
padding: 0.125rem 0.5rem;
text-decoration: none;
+ text-transform: none;
+ overflow: visible;
+}
+
+button:hover,
+[type="reset"]:hover,
+[type="button"]:hover,
+[type="submit"]:hover,
+micro-tags a:hover,
+nav[data-type="pagination"] a:hover,
+micro-author micro-card > a:hover {
+ border: 1px solid;
+ border-color: #aaa;
+ border-color: var(--border-darkest);
}
button svg,
-micro-author micro-summary > a svg {
+micro-author micro-card a svg,
+nav[data-type="pagination"] a svg {
height: 1.25rem;
- margin: 0 0.25rem;
+ width: 1.25rem;
+}
+
+micro-author a svg ~ span,
+micro-author a span ~ svg,
+nav[data-type="pagination"] a svg ~ span,
+nav[data-type="pagination"] a span ~ svg {
+ margin-left: 0.25rem;
}
hr {
+ border: 0;
border-top: 1px solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
+ opacity: 0.4;
+ margin: 0.5rem 0;
}
/* ----- Tables ----- */
@@ -497,7 +894,6 @@ table {
border-spacing: 0;
border: 1px solid #ccc;
border: 1px solid var(--border-darker);
- padding: 0.5rem 0 0 0;
width: 100%;
background-color: #fefefe;
background-color: var(--background);
@@ -506,20 +902,19 @@ table {
th {
border-bottom: 1px solid #ccc;
border-bottom: 1px solid var(--border-darker);
- padding: 0 0.5rem 0.5rem 0.5rem;
- text-align: left;
}
+th,
td {
- padding: 0.5rem 0 0.5rem 0.5rem;
border-right: 1px solid #ccc;
border-right: 1px solid var(--border-darker);
border-bottom: 1px solid #ccc;
border-bottom: 1px solid var(--border-darker);
+ padding: 0.5rem 1rem;
}
-td:last-child {
- padding-right: 0.5rem;
+td:last-child,
+th:last-child {
border-right: none;
}
@@ -529,12 +924,12 @@ tr:last-child td {
tbody tr:nth-child(odd) td {
background-color: #f3f3f3;
- background-color: var(--table-row-odd-background);
+ background-color: var(--table-odd-background);
}
tbody tr:nth-child(even) td {
background-color: #f9f9f9;
- background-color: var(--table-row-even-background);
+ background-color: var(--table-even-background);
}
tbody tr:hover td {
@@ -552,6 +947,10 @@ tr:last-child td:last-child {
/* ----- Print ----- */
+article a[href*="pdf"]::after {
+ content: " [pdf]";
+}
+
@media print {
a[href^="http"]::after {
content: " (" attr(href) ")";
@@ -564,53 +963,75 @@ tr:last-child td:last-child {
/* ----- Base ----- */
+html {
+ font-size: 95%;
+ height: 100%;
+ line-height: 1.5;
+ margin: 0;
+ overflow-y: scroll;
+ text-rendering: optimizeSpeed;
+ word-break: break-word;
+}
+
+html[data-document="html"],
+html[data-document="xhtml"] {
+ height: auto;
+ margin-left: calc(100vw - 100%);
+ margin-right: 0;
+ overflow-y: visible;
+}
+
+html[data-document="html"] body,
+html[data-document="xhtml"] body {
+ display: flex;
+ margin: 0 auto;
+ max-width: 1250px;
+}
+
body {
background-color: #fefefe;
background-color: var(--background);
color: #111;
color: var(--foreground);
- display: flex;
- margin: 0 auto;
- max-width: 1250px;
+ margin: 0;
+ max-width: 600px;
min-height: 100%;
overflow-x: hidden;
-webkit-text-size-adjust: none;
}
-column-left {
- display: flex;
- flex: 1;
- justify-content: flex-end;
+column-base[position="left"] {
+ width: 14.25%;
}
-column-right {
- flex: 2;
- max-width: 400px;
+column-base[position="right"] {
+ width: 28%;
}
-column-left,
-column-right {
+column-base[position="left"],
+column-base[position="right"] {
margin: 0.5rem 2rem;
}
-column-middle {
- flex: 6;
+column-base[position="middle"] {
max-width: 600px;
min-height: 100vh;
width: 100%;
+ height: fit-content;
}
micro-card,
micro-tags,
-micro-expires,
-micro-article {
+profile-box {
display: block;
}
-message-archive h1 {
+source-files h1,
+archive-list h1 {
text-align: center;
font-weight: 400;
font-size: 150%;
+ font-variant: all-small-caps;
}
micro-tags {
@@ -625,53 +1046,90 @@ micro-tags a {
margin: 0 0.25rem 0.5rem 0;
}
-micro-summary,
-micro-article {
+micro-card {
border-bottom: 1px solid;
border-color: #eee;
border-color: var(--border-lighter);
display: flex;
+ flex-direction: column;
padding: 1rem;
position: relative;
}
-micro-summary:hover {
+micro-card > a {
+ display: none;
+}
+
+micro-card:target {
+ border-radius: 0.5rem;
+ outline-offset: -6px;
+ outline: 2px dashed #ccc;
+ outline: 2px dashed var(--border-darker);
+}
+
+micro-card:hover {
background-color: #f5f9ff;
background-color: var(--hover-background-alternate);
}
-micro-summary:focus-within {
+micro-card:focus-within {
background-color: #f0ecf9;
background-color: var(--focus-within-background);
}
-micro-author micro-summary {
+micro-author micro-card {
+ flex-direction: row;
justify-content: start;
align-items: center;
border: none;
}
-micro-author micro-thumbnail {
- flex: none;
+micro-author micro-card header,
+micro-author micro-card > a,
+micro-author micro-card > article,
+micro-author micro-card > p:not(:last-child) {
+ margin: 0 0.5rem;
}
-micro-author micro-header {
- line-height: 1;
- margin: 0 1.25rem 0 0.5rem;
+micro-author micro-card p:not(:last-child) {
+ flex: 1.75;
+ color: #444;
+ color: var(--fade);
+ max-width: 20rem;
+}
+
+micro-author article {
flex: 1;
- height: 3rem;
- padding: 0 0.5rem;
+ min-width: 3rem;
}
-micro-thumbnail a {
- display: block;
+micro-author article h2 {
+ line-height: 1.25;
+}
+
+micro-author article h3 {
+ font-weight: 400;
}
-micro-thumbnail figure {
+micro-author micro-card header figure:first-child {
+ margin: 0;
+}
+
+micro-card header figure:first-child {
margin: 0 0.75rem 0 0;
}
-micro-thumbnail figure img {
+micro-card header figure > a,
+micro-card header figure > a:hover {
+ color: #000;
+ display: block;
+ text-decoration: none;
+}
+
+tag-card figure img,
+micro-card header figure img,
+micro-card header figure span,
+micro-card header figure object {
border-radius: 100%;
min-width: 3.5rem;
min-height: 3.5rem;
@@ -679,111 +1137,214 @@ micro-thumbnail figure img {
max-height: 3.5rem;
}
-micro-content {
- flex: 8;
- width: 0;
+micro-card > article {
+ margin-left: 4.25rem;
}
-micro-content > figure img {
+micro-card article ul {
+ list-style-type: "\2012";
+ padding-left: 2rem;
+}
+
+micro-card article li {
+ padding-left: 0.5rem;
+}
+
+micro-card article li::marker {
+ opacity: 0.85;
+}
+
+micro-card article ul li + li {
+ margin-top: 0.25rem;
+}
+
+micro-card article figure img {
border: none;
margin: 0 auto;
+ box-shadow: 0 0 3px #00000060;
+ box-shadow: 0 0 3px var(--shadow);
}
-micro-content > figure > a {
- background-color: #000;
+micro-card article figure img:before {
+ background-color: #fefefe;
+ background-color: var(--background);
border-radius: 0.5rem;
+ box-shadow: 0 1px 6px #00000060;
+ box-shadow: 0 1px 6px var(--shadow);
+ color: #111;
+ color: var(--foreground);
+ padding: 0.5rem 0.75rem;
+ margin: 1rem;
+}
+
+micro-card article figure > a {
+ border-radius: 0.5rem;
+ display: inline-block;
+}
+
+micro-card article figure > a[data-orientation="landscape"] {
display: block;
}
-micro-metadata {
- align-items: center;
+micro-card article figure > a[data-orientation="landscape"] img {
+ width: 100%;
+}
+
+micro-card header {
color: #444;
color: var(--fade);
display: flex;
- line-height: 1.25;
- margin-bottom: 0.5rem;
+ align-items: center;
+ margin-bottom: 0.25rem;
}
-micro-metadata h2 {
+micro-card header h2 {
display: inline;
}
-micro-metadata section a {
+micro-card header meta-data {
+ word-break: break-all;
+ word-break: break-word;
+}
+
+micro-card header meta-data a {
color: inherit;
}
-micro-metadata expiry-date,
-micro-metadata word-limit em,
-micro-metadata draft-label em {
+micro-card header meta-data > *:not(:last-child) {
+ margin-right: 0.5rem;
+}
+
+micro-card header meta-data > *:hover {
+ color: #111;
+ color: var(--foreground);
+}
+
+meta-expiry,
+meta-draft em,
+meta-wordcount word-limit em {
color: #8f0000;
color: var(--danger);
font-style: normal;
}
-micro-metadata draft-label em {
+meta-draft em {
font-variant: all-small-caps;
}
-micro-header footer svg,
-micro-metadata expiry-date svg,
-micro-metadata anchored-entry svg,
-micro-metadata unlisted-entry svg {
+profile-box footer svg,
+micro-card header meta-data svg {
height: 1rem;
width: 1rem;
- stroke-width: 0.1rem;
+ stroke-width: 0.105rem;
}
-micro-metadata unlisted-entry {
+meta-unlisted {
font-variant: all-small-caps;
}
s label,
abbr[title],
-abbr[title] label,
-micro-metadata read-time,
-micro-metadata word-limit,
-micro-metadata expiry-date,
-micro-metadata unlisted-entry {
+meta-expiry,
+meta-readtime,
+meta-datetime,
+meta-unlisted,
+meta-wordcount {
cursor: help;
}
-anchored-entry {
+meta-anchored {
display: flex;
- align-items: center;
margin-bottom: 0.25rem;
- margin-top: -0.5rem;
+ width: 100%;
+}
+
+meta-anchored > * {
+ margin-right: 0.5rem;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ text-decoration: none;
}
-anchored-entry svg {
+meta-anchored svg {
margin-right: 0.25rem;
}
-anchored-entry span {
+meta-anchored a[data-anchored="pinned"] svg {
+ fill: #9ed1fa;
+}
+
+meta-anchored a[data-anchored="marked"] svg {
+ fill: #cd5c5c;
+}
+
+menu {
+ display: inline-block;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ position: relative;
+}
+
+menu context-menu {
+ min-width: 10rem;
+}
+
+menu context-menu svg {
margin-right: 0.25rem;
}
-anchored-entry span:not(:last-child):after {
- content: "\00B7";
- margin-left: 0.25rem;
+menu context-menu a {
+ display: block;
+ padding: 0.5rem 1rem;
}
-anchored-pinned svg {
- fill: #9ed1fa;
+menu context-menu a:hover {
+ background-color: #eee;
+ background-color: var(--hover-background);
+ border-radius: 0.25rem;
}
-anchored-liked svg {
- fill: #cd5c5c;
+micro-card[id] article h1 a,
+micro-card[id] article h2 a,
+micro-card[id] article h3 a {
+ color: inherit;
}
-micro-header micro-header-image img {
+meta-view a,
+meta-name a,
+meta-draft a,
+meta-handle a,
+micro-card[id] article h1 a,
+micro-card[id] article h2 a,
+micro-card[id] article h3 a,
+micro-card header a:focus > span,
+micro-card menu context-menu a,
+micro-card menu context-menu a span {
+ text-decoration: none;
+}
+
+menu span,
+meta-view a span,
+meta-name a:hover,
+meta-draft a span,
+meta-handle a span,
+micro-card[id] article h1 a:hover,
+micro-card[id] article h2 a:hover,
+micro-card[id] article h3 a:hover {
+ text-decoration: underline;
+}
+
+profile-box picture[data-type="banner"] img {
background-color: transparent;
border-radius: 0.125rem;
- height: 12rem;
+ height: 10rem;
width: 100%;
border: none;
}
-micro-header micro-header-picture img {
+profile-box picture[data-type="profile"] img {
border-radius: 100%;
height: 8rem;
margin: -4rem 2rem 0 2rem;
@@ -792,123 +1353,144 @@ micro-header micro-header-picture img {
padding: 0.25rem;
}
-micro-header section {
+profile-box section {
margin: 1rem 2rem 0 2rem;
- line-height: 1;
display: flex;
align-items: baseline;
}
-micro-header-title {
- margin-right: 1rem;
+profile-box section aside {
flex: 1;
+ line-height: 1.25;
+ margin-right: 1rem;
+ display: inline;
}
-micro-header-description {
+profile-box section p {
flex: 6;
}
-micro-header h2 {
- margin-bottom: 0.25rem;
- font-size: 700;
-}
-
-micro-header h3 {
+profile-box h3 {
font-weight: 400;
color: #444;
color: var(--fade);
- margin: 0;
}
-micro-header footer,
-micro-header footer code {
+profile-box footer,
+profile-box footer code {
color: #444;
color: var(--fade);
}
-micro-header footer {
+profile-box footer {
margin: 1.25rem 2rem 0.25rem 2rem;
text-align: center;
font-size: 95%;
}
-micro-header footer p {
+profile-box footer p {
margin: 0.75rem 0.5rem 0.25em 0;
display: inline;
}
-micro-unsafe-content * {
- visibility: hidden;
- opacity: 0;
- pointer-events: none;
+micro-card details[data-disclosure] summary {
+ display: inline-block;
+ margin: 0 -0.25rem 0.5rem -0.25rem;
+ padding: 0.25rem;
}
-micro-unsafe details svg {
- stroke-width: 0.1rem;
- margin-right: 0.15rem;
+micro-card details[data-disclosure] summary:focus a {
+ color: inherit;
}
-micro-unsafe details summary {
- font-variant: all-small-caps;
- letter-spacing: 0.025rem;
- line-height: 1.25;
- color: #8f0000;
- color: var(--danger);
- list-style: none;
+following-list details summary:focus:after,
+following-list details[open] summary:focus:after,
+micro-card details[data-disclosure] summary:focus:after,
+micro-card details[data-disclosure][open] summary:focus:after {
+ color: #111;
+ color: var(--foreground);
+ border-color: #111;
}
-micro-unsafe details > summary::-webkit-details-marker {
- display: none;
+following-list details summary:after,
+following-list details[open] summary:after,
+micro-card details[data-disclosure] summary:after,
+micro-card details[data-disclosure][open] summary:after {
+ border-radius: 0.5rem;
+ display: inline;
+ vertical-align: bottom;
}
-micro-unsafe-content {
- border-radius: 0.25rem;
- display: block;
- background: repeating-linear-gradient(
- 180deg,
- #ff9999,
- #ff9999 1rem,
- #eee 1rem,
- #eee 2rem
- );
+micro-card details[data-disclosure] summary:hover,
+micro-card details[data-disclosure] summary:hover:after {
+ text-shadow: 0 0 currentColor;
}
-micro-unsafe details[open] + micro-unsafe-content * {
- filter: none;
- transition: 1s;
- visibility: visible;
- opacity: 1;
- background: none;
- outline: none;
- pointer-events: auto;
+micro-card details[data-disclosure] summary:hover:after {
+ text-decoration: underline;
}
-micro-unsafe details[open] + micro-unsafe-content {
- background: none;
+micro-card details[data-disclosure] summary:after {
+ content: "HIDDEN";
}
-@supports (filter: blur(2rem)) {
- micro-unsafe-content * {
- filter: blur(2rem);
- visibility: unset;
- opacity: unset;
- }
- micro-unsafe-content {
- outline: none;
- background: unset;
- }
+micro-card details[data-disclosure][open] summary:after {
+ content: "OPENED";
+}
+
+micro-card details[data-disclosure][open] ~ details summary:after {
+ content: none;
+}
+
+micro-card details[data-disclosure][open] ~ *:not(details):not(micro-tags) {
+ display: inherit;
+}
+
+micro-card
+ details[data-disclosure][open]
+ ~ *:not(details):not(micro-tags):not(math-ml) {
+ color: #444;
+ color: var(--fade);
+}
+
+micro-card details[data-disclosure][open] ~ details summary {
+ cursor: text;
+}
+
+micro-card details[data-disclosure] ~ *:not(details):not(micro-tags) {
+ display: none;
+}
+
+micro-thread related-content footer {
+ font-size: 100%;
+ border-bottom: 1px solid;
+ border-color: #eee;
+ border-color: var(--border-lighter);
+ margin: 0;
+ padding: 0.5rem 0;
}
-tab-list {
+micro-thread nav[data-type="pagination"] {
+ padding: 0.5rem 0;
+ border-bottom: 1px solid;
+ border-color: #eee;
+ border-color: var(--border-lighter);
+}
+
+micro-thread > nav[data-type="pagination"]:last-child {
+ border: none;
+}
+
+tab-bar {
display: inline-block;
overflow-x: auto;
- text-overflow: ellipsis;
+ overflow-y: hidden;
vertical-align: top;
white-space: nowrap;
width: 100%;
}
-tab-list aside {
+tab-bar nav {
display: flex;
justify-content: center;
border-bottom: 1px solid;
@@ -917,7 +1499,7 @@ tab-list aside {
min-width: 450px;
}
-tab-list aside a {
+tab-bar nav a {
border-left: 1px solid;
border-right: 1px solid;
border-top-left-radius: 0.5rem;
@@ -925,32 +1507,53 @@ tab-list aside a {
border-top: 1px solid;
border-color: #ddd;
border-color: var(--border-darker);
- color: #555;
+ color: #444;
color: var(--fade);
padding: 0.5rem 1rem;
margin-top: 0.5rem;
position: relative;
text-decoration: none;
top: 1px;
- border-bottom: 2px solid var(--background);
+ border-bottom: 2px solid transparent;
}
-tab-list aside a:not(:last-child) {
+tab-bar nav a:not(:last-child) {
margin-right: 0.5rem;
}
-tab-list aside a:last-child {
+tab-bar nav a[data-draft] {
color: #8f0000;
color: var(--danger);
}
-tab-list aside a:hover {
- background-color: #eee;
- background-color: var(--hover-background);
- color: inherit;
+tab-bar nav a:after {
+ content: attr(data-label);
+ display: block;
+ font-weight: 700;
+ height: 0;
+ overflow: hidden;
+ pointer-events: none;
+ user-select: none;
+ visibility: hidden;
}
-column-middle nav {
+tab-bar nav a:hover {
+ text-decoration: underline;
+}
+
+tab-bar nav a span[data-scroll] {
+ position: absolute;
+ top: -4.75rem;
+ left: 200%;
+ width: 0;
+ height: 0;
+}
+
+tab-bar nav a:nth-child(-n + 3) span[data-scroll] {
+ left: -200%;
+}
+
+column-base[position="middle"] > nav:first-child {
align-items: center;
background-color: #fefefe;
background-color: var(--background);
@@ -963,29 +1566,39 @@ column-middle nav {
top: 0;
width: 100%;
z-index: 100;
- height: 4rem;
+ height: inherit;
}
-column-middle nav section h2,
-column-middle nav section small {
+column-base[position="middle"] > nav:first-child section h2,
+column-base[position="middle"] > nav:first-child section small {
margin: 0;
}
-micro-author micro-header,
-column-middle nav section h2,
-column-middle nav section small {
- white-space: nowrap;
+micro-author article > *,
+column-base[position="middle"] > nav:first-child section h2,
+column-base[position="middle"] > nav:first-child section small {
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
}
-column-middle nav section {
+column-base[position="middle"] > nav:first-child section {
line-height: 1.25;
padding: 0 0.5rem;
+ margin-right: 0.5rem;
}
-column-middle main > footer {
- margin: 1rem 0;
+column-base[position="middle"] > footer:last-child {
+ margin: 1rem 0.25rem 3rem 0.25rem;
+}
+
+column-base[position="middle"] main > footer:last-child {
+ padding: 2rem 0 1rem 0;
+}
+
+icon-button,
+icon-navigator {
+ height: 4rem;
}
icon-button a {
@@ -1000,9 +1613,16 @@ icon-button a {
padding: 0.5rem 0;
}
-icon-button,
-icon-navigator {
- height: 4rem;
+icon-button a svg:nth-of-type(2),
+icon-button a small:nth-of-type(2),
+icon-button a[data-update="refresh"] svg:nth-of-type(1),
+icon-button a[data-update="refresh"] small:nth-of-type(1) {
+ display: none;
+}
+
+icon-button a[data-update="refresh"] svg:nth-of-type(2),
+icon-button a[data-update="refresh"] small:nth-of-type(2) {
+ display: block;
}
icon-button a:hover {
@@ -1018,11 +1638,31 @@ icon-button p {
margin: 0;
}
+code-block pre {
+ border-radius: 0.5rem;
+ border: 1px solid #ccc;
+ border: 1px solid var(--border-darker);
+ display: block;
+ font-size: 95%;
+ margin: 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+ padding: 2.65rem 0 0 0;
+ tab-size: 2;
+ word-break: break-word;
+ white-space: pre;
+ resize: both;
+ position: relative;
+ z-index: 2;
+}
+
code-block pre code {
display: inline-block;
min-width: 100%;
- border-top: 1px solid #bbb;
+ border-top: 1px solid #ccc;
+ border-top: 1px solid var(--border-darker);
padding: 0.75rem;
+ white-space: pre;
}
code-block[data-lines] pre code {
@@ -1031,69 +1671,51 @@ code-block[data-lines] pre code {
code-block header {
position: relative;
- top: 1.85rem;
+ top: 2.125rem;
margin-top: -1rem;
height: 1rem;
padding: 0 0.5rem;
display: flex;
justify-content: space-between;
align-items: center;
+ z-index: 3;
}
code-block header language-label {
- padding: 0.125rem 1rem;
font-variant: all-small-caps;
}
-code-block pre {
- border-radius: 0.5rem;
- border: 1px solid #ccc;
- border: 1px solid var(--border-darker);
- display: block;
- font-size: 95%;
- margin: 0;
- overflow-x: auto;
- overflow-y: hidden;
- padding: 2.65rem 0 0 0;
- tab-size: 2;
- word-break: break-word;
- white-space: pre;
+code-block header language-label a {
+ text-decoration: none;
+ padding: 0.125rem 1rem;
+}
+
+code-block header language-label a:hover {
+ text-decoration: underline;
+}
+
+code-content {
+ width: 100%;
}
-paginator-navigation {
- padding: 1rem 1rem 0 1rem;
+nav[data-type="pagination"] {
+ padding: 1rem 0;
display: flex;
align-items: center;
justify-content: center;
+ flex-wrap: wrap;
}
-paginator-navigation a,
-paginator-navigation button {
- margin: 0 0.25rem;
+nav[data-type="pagination"] a {
+ margin: 0.5rem 0.25rem;
font-size: 85%;
display: flex;
align-items: center;
justify-content: center;
}
-paginator-navigation svg {
- height: 1.316rem;
-}
-
-web-ring,
-author-list,
-gallery-images {
- padding-bottom: 1rem;
- display: block;
-}
-
-web-ring > h1,
-author-list > h1,
-gallery-images > h1 {
- font-size: 95%;
- margin: 0.5rem 0 1rem 0;
- text-align: center;
- text-transform: uppercase;
+nav[data-type="pagination"] a[title="hidden"] {
+ visibility: hidden;
}
gallery-images aside {
@@ -1103,16 +1725,24 @@ gallery-images aside {
position: relative;
}
-gallery-images picture {
+gallery-images a {
display: flex;
- flex-basis: 33.33%;
+ flex-basis: 25%;
flex-grow: 1;
height: 6rem;
- width: 33.333%;
+ width: 25%;
}
+gallery-images picture,
gallery-images picture img {
+ border-color: #ccc;
border-radius: 0;
+ height: 100%;
+ width: 100%;
+}
+
+gallery-images picture img:hover {
+ box-shadow: none;
}
gallery-overlay {
@@ -1122,81 +1752,145 @@ gallery-overlay {
outline: 4px solid #fefefe;
outline: 4px solid var(--background);
position: absolute;
+ left: 0;
+ top: 0;
width: 100%;
z-index: 1;
+ pointer-events: none;
+ border: 1px solid;
+ border-color: #eee;
+ border-color: var(--border-lighter);
}
-main web-ring {
- display: none;
-}
-
-web-ring {
+web-ring,
+[data-kind="home"] author-list,
+[data-kind="term"] author-list,
+[data-kind="taxonomy"] author-list {
border-radius: 1rem;
position: sticky;
position: -webkit-sticky;
top: 1rem;
}
-web-ring a {
- text-decoration: none;
-}
-
-anchored-entry a:hover,
-web-ring a[href^="http"]:hover {
- text-decoration: underline;
-}
-
-web-ring time {
- font-variant: small-caps;
+web-ring time,
+micro-author article time {
+ display: block;
color: #444;
color: var(--fade);
}
-web-ring header {
- font-weight: 700;
+web-ring p:not(:last-child) {
+ margin-bottom: 0;
}
-web-ring p {
- margin-bottom: 0 !important;
+web-ring article:not(:last-child) {
+ margin-bottom: 1.5rem;
}
-web-ring-item:not(:last-child) {
- margin-bottom: 2rem;
- display: block;
+web-ring aside {
+ padding: 1rem;
}
web-ring aside,
-author-list section {
+author-list aside,
+following-list aside {
background-color: #f9f9f9;
background-color: var(--widget-background);
+ border-radius: 0.5rem;
}
-web-ring aside {
- border-radius: 1rem;
- padding: 1rem;
+web-ring aside footer,
+author-list aside footer,
+following-list aside footer {
+ background-color: #fefefe;
+ background-color: var(--background);
}
-author-list section {
+web-ring,
+author-list,
+following-list,
+gallery-images {
+ padding-bottom: 1rem;
display: block;
- border-radius: 1rem;
}
-search-entry {
+web-ring > h1,
+author-list > h1,
+gallery-images > h1,
+following-list details {
+ font-size: 95%;
+ margin: 0.5rem 0 1rem 0;
+ text-align: center;
+ text-transform: uppercase;
+}
+
+following-list details h1 {
+ display: inline-block;
+}
+
+following-list aside micro-author {
+ display: none;
+}
+
+following-list details[open] + aside micro-author,
+following-list aside micro-author:nth-child(-n + 3) {
+ display: inherit;
+}
+
+following-list:hover details[open] + aside {
+ outline: 2px solid #ccc;
+ outline: 2px solid var(--border-darker);
+}
+
+following-list details[data-expand="more"] summary:after {
+ content: "+";
+}
+
+following-list details[open][data-expand="more"] summary:after {
+ content: "-";
+}
+
+following-list details[data-expand="more"] summary:after,
+following-list details[open][data-expand="more"] summary:after {
+ padding: 0 0.5rem;
+ font-size: 100%;
+ margin-left: 0.25rem;
+}
+
+author-list:hover h1,
+following-list:hover details h1 {
+ text-decoration: underline;
+}
+
+author-list h1 a {
+ color: inherit;
+}
+
+author-list aside {
+ display: block;
+}
+
+author-list p {
+ display: none;
+}
+
+search-box {
display: inherit;
width: 100%;
+ z-index: 1;
}
-search-entry[data-focus],
-search-entry:focus-within {
+search-box[data-focus],
+search-box:focus-within {
position: absolute;
}
-search-entry:focus-within form {
+search-box:focus-within form {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
-search-entry form {
+search-box form {
background-color: #fefefe;
background-color: var(--background);
border-radius: 0.5rem;
@@ -1204,12 +1898,12 @@ search-entry form {
border-color: #ccc;
border-color: var(--border-darker);
display: inline-flex;
- margin: 0 1rem;
width: 100%;
position: relative;
+ margin: 0 0.5rem;
}
-search-entry form button {
+search-box form button[type="submit"] {
background-color: transparent;
border: none;
box-shadow: none;
@@ -1225,32 +1919,32 @@ search-entry form button {
line-height: 1;
}
-search-entry form input {
+search-box form input {
-webkit-appearance: none;
- background-color: #fefefe;
- background-color: var(--background);
border-bottom-left-radius: 0.5rem;
border-top-left-radius: 0.5rem;
border: none;
font-size: 100%;
- line-height: 1.5;
+ line-height: inherit;
padding-left: 1rem;
padding-right: 1rem;
width: 100%;
color: inherit;
}
-search-entry form button svg {
- stroke-width: 0.1rem;
+search-box form input,
+search-box form input:focus {
+ outline: none;
+ background-color: #fefefe;
+ background-color: var(--text-background);
}
-search-entry form input:focus {
- outline: none;
- background-color: #fefefe !important;
- background-color: var(--background) !important;
+search-box form button svg {
+ stroke-width: 0.1rem;
+ width: 100%;
}
-search-entry ul {
+search-box ul {
position: absolute;
background-color: inherit;
padding-top: 2.9rem;
@@ -1259,15 +1953,17 @@ search-entry ul {
border-radius: 0.5rem;
z-index: -1;
margin-right: 1rem;
- margin-left: -0.05rem;
+ margin-left: -0.065rem;
width: 100.3%;
+ box-shadow: 0 4px 6px #00000060;
+ box-shadow: 0 4px 6px var(--shadow);
}
-search-entry ul li a span {
+search-box ul li a span {
font-weight: 400;
}
-search-entry ul li a {
+search-box ul li a {
font-weight: 700;
color: inherit;
text-decoration: none;
@@ -1275,12 +1971,18 @@ search-entry ul li a {
padding: 0.25rem 0.75rem;
}
-search-entry ul li:first-child a {
+search-box ul li:first-child a {
background-color: #ebf3ff;
background-color: var(--hover-background-alternate);
}
-search-entry ul li a:hover {
+search-box ul li:only-child a,
+search-box ul li:last-child a:hover {
+ border-bottom-right-radius: 0.5rem;
+ border-bottom-left-radius: 0.5rem;
+}
+
+search-box ul li a:hover {
background-color: #eee;
background-color: var(--hover-background);
}
@@ -1295,7 +1997,6 @@ item-list h1 {
item-list ul {
padding: 0 0.5rem 0 0.5rem;
- list-style: none;
}
item-list li:hover {
@@ -1307,7 +2008,7 @@ item-list li:hover span:last-child {
text-decoration: underline;
}
-item-list li a {
+item-list li > a {
display: flex;
text-decoration: none;
align-items: baseline;
@@ -1315,25 +2016,120 @@ item-list li a {
padding: 0.5rem;
}
-item-list a span:first-child {
+item-list span:first-child {
flex: 1;
text-transform: uppercase;
}
-item-list a span:nth-child(2) {
+item-list span:nth-child(2) {
flex: 3;
margin: 0 0.5rem;
}
-item-list a span:last-child {
+item-list span:last-child {
flex: 1;
text-align: right;
}
-item-list a span:first-child,
-item-list a span:last-child {
+item-list span:first-child,
+item-list span:last-child {
+ color: #444;
+ color: var(--fade);
+}
+
+item-list a:focus span:first-child,
+item-list a:focus span:last-child {
+ color: inherit;
+}
+
+time-line h1 {
+ padding: 1rem;
+}
+
+time-line ul {
+ padding: 0 0.5rem;
+}
+
+time-line li:hover {
+ background-color: #eee;
+ background-color: var(--hover-background);
+}
+
+time-line li a {
+ position: relative;
+ border-left: 1px solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
+ padding: 0.75rem 0.5rem;
+ display: flex;
+ text-decoration: none;
+}
+
+time-line li a:before {
+ position: absolute;
+ background-color: #0149bc;
+ background-color: var(--link);
+ border-radius: 100%;
+ content: "";
+ height: 1rem;
+ width: 1rem;
+ top: 1rem;
+ left: -0.5rem;
+ border: 0.3rem solid #fefefe;
+ border: 0.3rem solid var(--background);
+}
+
+time-line a:focus time,
+time-line a:focus section p {
+ color: inherit;
+}
+
+time-line time,
+time-line section p {
+ color: #444;
+ color: var(--fade);
+}
+
+time-line time {
+ text-transform: uppercase;
+ white-space: nowrap;
+ margin: 0 1rem;
+}
+
+tag-deck {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0.5rem 0;
+ justify-content: space-between;
+}
+
+tag-card {
+ border: 1px solid;
+ border-color: #eee;
+ border-color: var(--border-lighter);
+ border-radius: 0.5rem;
+ box-shadow: 0 0 1rem -0.85rem #00000060;
+ box-shadow: 0 0 1rem -0.85rem var(--shadow);
+ display: block;
+ padding: 2rem;
+ text-align: center;
+ width: 49%;
+ margin: 1% 0;
+}
+
+tag-card h2 {
+ margin: 0 0 0.5rem 0;
+}
+
+tag-card img {
+ margin: 0 auto;
+}
+
+tag-card time {
color: #444;
color: var(--fade);
+ display: block;
+ margin-bottom: 0.5rem;
}
source-files footer {
@@ -1356,35 +2152,42 @@ context-menu {
background-color: #fff;
background-color: var(--background-bolder);
border: 1px solid;
- border-color: #ddd;
+ border-color: #eee;
border-color: var(--border-lighter);
- border-radius: 4px;
- box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.1),
- 0 0 0 1px rgba(10, 10, 10, 0.02);
- padding-bottom: 0.5rem;
- padding-top: 0.5rem;
+ border-radius: 0.5rem;
+ box-shadow: 0 0 1rem -0.5rem #00000060;
+ box-shadow: 0 0 1rem -0.5rem var(--shadow);
min-width: 6.25rem;
position: absolute;
z-index: 99;
- max-width: 20rem;
visibility: hidden;
opacity: 0;
}
-context-profile context-menu {
- color: #111;
- color: var(--foreground);
- display: block;
- padding: 1rem;
- text-align: left;
+context-menu[position="right"] {
+ right: 0;
}
-context-profile a {
- display: inline;
+context-menu[position="left"] {
+ left: 0;
+}
+
+context-menu[position="anchor"] {
+ left: -125%;
+ top: 0;
+}
+
+context-menu[position="left"],
+context-menu[position="right"] {
+ top: 1rem;
+}
+
+context-profile p a {
+ text-decoration: underline;
}
context-profile aside p {
- color: #555;
+ color: #444;
color: var(--fade);
margin: 0;
}
@@ -1392,18 +2195,34 @@ context-profile aside p {
context-profile div {
display: flex;
align-items: center;
+ margin-bottom: 0.5rem;
}
context-profile aside:nth-child(2) {
line-height: 1.25;
}
-micro-thumbnail figure:hover context-menu {
- visibility: visible;
+context-profile context-menu {
+ color: #111;
+ color: var(--foreground);
+ display: block;
+ padding: 0.9rem;
+ left: 0.5rem;
+ top: 0.5rem;
+ text-align: left;
+ max-width: 20rem;
+ transition-delay: 0.5s;
+}
+
+micro-card figure:hover context-menu,
+input[type="checkbox"]:checked + context-menu {
+ margin-right: 1rem;
opacity: 1;
+ visibility: visible;
}
diagram-container svg {
+ width: 100%;
border: 2px solid;
border-radius: 0.5rem;
border-color: #ccc;
@@ -1413,151 +2232,111 @@ diagram-container svg {
background-color: var(--background);
}
-twitter-tweet {
- min-height: 20rem;
- max-height: 20rem;
- display: block;
- overflow-y: auto;
-}
-
-twitter-tweet iframe {
- border: none;
-}
-
-/* ----- Typography ----- */
-
-h1,
-h2,
-h3 {
- font-size: 100%;
- margin: 0;
-}
-
-p,
-ul,
-dd,
-dl,
-ol,
-figure,
-blockquote {
- margin: 0;
-}
-
-p:not(:last-child),
-ol:not(:last-child),
-ul:not(:last-child),
-dl:not(:last-child),
-table:not(:last-child),
-figure:not(:last-child),
-code-block:not(:last-child),
-blockquote:not(:last-child) {
- margin-bottom: 0.75rem;
-}
-
-footer,
-figcaption {
- color: #444;
- color: var(--fade);
- font-size: 85%;
- margin: 0.5rem 0;
- text-align: center;
-}
-
-sup {
- vertical-align: super;
- font-size: 85%;
+tool-tip[data-type="reaction"] {
+ text-decoration: underline;
+ -webkit-text-decoration-style: dotted;
+ text-decoration-style: dotted;
+ text-decoration-thickness: 0.05rem;
+ cursor: default;
+ position: relative;
+ display: inline-block;
}
-sub {
- vertical-align: sub;
- font-size: 85%;
+tool-tip[data-type="reaction"]:hover {
+ text-decoration-thickness: 0.1rem;
}
-s,
-del,
-mark,
-ins {
- padding: 0 0.15rem;
- line-height: 1.5;
+tool-tip[data-type="reaction"]:hover img {
+ opacity: 1;
+ visibility: visible;
+ width: 100%;
}
-mark {
- background-color: #ffe699;
- background-color: var(--warning-background);
- color: #332600;
- color: var(--warning);
+tool-tip[data-type="reaction"] img {
+ position: absolute;
+ z-index: 99;
+ visibility: hidden;
+ opacity: 0;
+ max-height: 80px;
+ object-fit: cover;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ max-width: fit-content;
+ border: none;
+ transition-delay: 0.5s;
}
-ins {
- background-color: #d5f3c4;
- background-color: var(--success-background);
- color: #1d3c0c;
- color: var(--success);
- text-decoration: none;
+body micro-card:first-of-type tool-tip[data-type="reaction"] img,
+main micro-card:first-of-type tool-tip[data-type="reaction"] img {
+ bottom: 0;
+ top: 100%;
}
-del {
- background-color: #fcd2cf;
- background-color: var(--danger-background);
- color: #8f0000;
- color: var(--danger);
+link-card {
+ display: flex;
+ border: 1px solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
+ border-radius: 0.5rem;
+ margin-bottom: 0.75rem;
}
-s {
- text-decoration: none;
- background-color: #333;
- background-color: var(--spoiler);
- color: transparent;
+link-card a img {
+ min-width: 5rem;
+ max-width: 5rem;
+ border: none;
}
-[type="checkbox"]:checked ~ s {
- background-color: inherit;
- color: inherit;
+link-card > a {
+ border-right: 1px solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
+ display: flex;
+ align-items: center;
+ padding: 1rem;
}
-blockquote {
- color: #555;
- color: var(--fade);
- padding-left: 2rem;
+link-card article {
+ padding: 1rem;
+ width: 100%;
}
-blockquote p {
- font-style: italic;
- font-family: Charter, Georgia, "Book Antiqua", serif;
- font-size: 125%;
+link-card article a {
+ word-break: break-all;
+ display: block;
}
-blockquote p span {
- display: block;
- text-align: right;
- color: #111;
- color: var(--foreground);
- font-style: normal;
- font-size: 80%;
- margin-top: 0.75rem;
+math-ml:not(:last-child) {
+ margin-bottom: 0.75rem;
}
-video {
+math-ml figure[id] figure {
+ overflow-x: auto;
+ overflow-y: hidden;
border-radius: 0.5rem;
+ padding: 0.75rem 0.5rem;
+ background-color: #f9f9f9;
+ background-color: var(--widget-background);
+ border: 1px solid;
+ border-color: #ccc;
+ border-color: var(--border-darker);
}
-video:hover {
- box-shadow: 0 0 14px #999;
- box-shadow: 0 0 14px var(--shadow);
+math-ml figure[id] a:first-child {
+ margin: 0 0.125rem;
+ padding: 0 0.25rem;
+ font-weight: 700;
+ color: #0149bc;
+ color: var(--link);
}
-kbd {
- background-color: #eee;
- border-radius: 3px;
- border: 1px solid #b4b4b4;
- box-shadow: 0 1px 1px #737373, 0 2px 0 0 #f2f2f2 inset;
- color: #333;
- display: inline-block;
- font-size: 0.85em;
- font-weight: 700;
- line-height: 1;
- padding: 2px 4px;
- white-space: nowrap;
+math-ml figure[id]:target figure {
+ background-color: #ffe699;
+ background-color: var(--warning-background);
+ color: #000;
+ outline: 2px solid;
+ border-radius: 0.5rem;
}
/* ----- Attributes ----- */
@@ -1566,30 +2345,32 @@ kbd {
outline: none;
}
-[hidden] {
+[hidden],
+nav[hidden] {
display: none;
}
-[data-invisible] {
- visibility: hidden;
-}
-
[data-hover] {
text-decoration: none;
}
+[data-hover]:hover {
+ text-decoration: underline;
+}
+
[draft] {
background-color: #fff5f5;
background-color: var(--danger-background-lighter);
+ border-color: #fcd2cf;
border-color: var(--danger-background);
}
[disabled] {
cursor: not-allowed;
- border-color: #ddd;
+ border-color: #eee;
border-color: var(--border-lighter);
- color: #999;
- color: var(--disabled);
+ color: #444;
+ color: var(--fade);
}
[role="doc-endnotes"] {
@@ -1597,126 +2378,474 @@ kbd {
}
[role="doc-endnotes"] hr {
- border-top: 1px solid #ccc;
margin-bottom: 0.75rem;
}
[role="doc-endnotes"] ol {
+ font-size: 90%;
padding-left: 2rem;
}
+[data-xml] micro-card {
+ flex-direction: row;
+ align-items: center;
+}
+
+[data-xml] micro-card article {
+ margin-left: 0;
+}
+
+[data-xml] micro-card header figure {
+ display: block;
+}
+
+[data-xml] column-base[position="middle"] nav section {
+ flex-grow: 1;
+}
+
+[data-xml="sitemap"] main section {
+ padding: 1rem;
+}
+
+[data-xml="sitemap"] section a {
+ text-decoration: none;
+}
+
+[data-xml="sitemap"] section a:hover {
+ text-decoration: underline;
+}
+
/* ----- Responsive ----- */
@media screen and (max-width: 1220px) {
- column-left {
+ column-base[position="right"] {
+ width: 38%;
+ }
+ column-base[position="left"] {
flex: none;
- margin: 0.5rem;
+ width: auto;
}
- column-left nav a {
+ column-base[position="left"] nav a {
flex-direction: column-reverse;
justify-content: center;
white-space: nowrap;
overflow: hidden;
}
- column-left nav a span {
+ column-base[position="left"] nav a span {
padding-top: 0.5rem;
}
+ micro-author micro-card {
+ flex-direction: column;
+ text-align: center;
+ }
+ micro-author micro-card > *:not(:last-child),
+ micro-author micro-card > p:not(:last-child) {
+ margin-bottom: 0.5rem;
+ }
+ micro-author article {
+ flex: none;
+ }
+ micro-author article > * {
+ white-space: normal;
+ }
+ time-line ul {
+ padding: 0 2rem;
+ }
}
-@media screen and (max-width: 1055px) {
- column-left,
- search-entry,
- column-middle nav section {
+@media screen and (max-width: 1080px) {
+ search-box,
+ column-base[position="left"],
+ column-base[position="middle"] > nav:first-child section {
display: none;
}
- column-middle nav {
+ column-base[position="middle"] > nav:first-child {
justify-content: space-between;
overflow-x: auto;
overflow-y: hidden;
}
- icon-navigator {
- display: inline !important;
+ column-base[position="middle"] > nav:first-child icon-navigator[hidden] {
+ display: inline;
+ }
+ tag-deck {
+ margin: 0.5rem 0.75rem;
}
}
-@media screen and (max-width: 925px) {
- column-right {
- display: none;
+@media screen and (max-width: 920px) {
+ html[data-document="html"],
+ html[data-document="xhtml"] {
+ margin: 0;
}
- micro-metadata {
- line-height: inherit;
+ nav + main,
+ profile-box {
+ margin-top: 4rem;
}
- micro-header section {
- display: block;
+ column-base[position="right"] {
+ display: none;
}
- column-middle {
+ column-base[position="middle"] {
display: block;
max-width: 100%;
}
- column-middle nav {
+ column-base[position="middle"] > nav:first-child {
position: fixed;
- }
- navigation-separator hr[hidden] {
- border-color: transparent;
- display: flex;
- height: 0;
- margin: 0;
- padding-top: 4rem;
- border: none;
+ box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.2);
}
micro-card {
max-width: 600px;
margin: 0 auto;
}
- html {
- margin: 0;
+ micro-card header {
+ line-height: inherit;
}
- body {
+ profile-box section {
display: block;
- overflow-y: scroll;
}
- nav {
- box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.2);
+ micro-author micro-card {
+ flex-direction: column;
+ text-align: center;
+ border-bottom: 1px solid #eee;
+ border-bottom: 1px solid var(--border-lighter);
+ }
+ micro-author micro-card article,
+ micro-author micro-card header figure,
+ micro-author micro-card p:not(:last-child) {
+ flex: auto;
+ margin: 0 0 0.75rem 0;
}
- nav:active,
- nav:hover,
- nav:focus,
- nav:focus-within,
- nav:focus-visible {
- box-shadow: 15px 0 15px -15px inset, -15px 0 15px -15px inset;
+ tab-bar:active,
+ tab-bar:hover,
+ tab-bar:focus,
+ tab-bar:focus-within,
+ tab-bar:focus-visible,
+ column-base[position="middle"] > nav:first-child:active,
+ column-base[position="middle"] > nav:first-child:hover,
+ column-base[position="middle"] > nav:first-child:focus,
+ column-base[position="middle"] > nav:first-child:focus-within,
+ column-base[position="middle"] > nav:first-child:focus-visible {
+ box-shadow: 1rem -0.2rem 1rem -1rem inset, -1rem -0.2rem 1rem -1rem inset;
}
}
@media screen and (max-width: 460px) {
- micro-card micro-summary > micro-thumbnail {
- display: none;
+ micro-card > article {
+ margin-left: 0;
}
- micro-metadata micro-thumbnail[hidden],
- micro-author micro-card micro-summary > micro-thumbnail {
- display: block;
+ tag-card {
+ width: 100%;
+ margin: 0.5rem;
}
}
/* ----- Self Frames ----- */
@media (max-height: 12rem) {
+ nav + main {
+ margin-top: 0;
+ }
micro-card {
width: 100vw;
padding-right: 1rem;
}
- micro-summary {
+ micro-card {
min-height: 14rem;
}
- :not(#main):target micro-summary,
- :not(#main):target micro-summary:hover {
+ :not(#main):target micro-card,
+ :not(#main):target micro-card:hover {
outline: none;
}
:target::before {
display: none;
}
- main > footer,
- column-middle nav,
- navigation-separator hr[hidden] {
+ column-base[position="middle"] > nav:first-child,
+ column-base[position="middle"] > footer:last-child {
display: none;
}
}
+
+/* ----- Animations ----- */
+
+text-animation {
+ height: 0;
+ cursor: default;
+}
+
+text-animation,
+text-animation span {
+ display: inline-block;
+ text-decoration: underline;
+ -webkit-text-decoration-style: double;
+ text-decoration-style: double;
+}
+
+text-animation:hover,
+text-animation:hover span {
+ text-decoration: none;
+}
+
+text-animation[rattle]:hover,
+text-animation[default]:hover {
+ animation: tilt-rightward 0.1s infinite, tilt-leftward 0.15s infinite;
+}
+
+text-animation[hang]:hover {
+ animation: tilt-rightward 1.3s infinite, tilt-leftward 1.8s infinite;
+}
+
+text-animation[squeeze]:hover {
+ animation: squeeze 1s infinite;
+}
+
+text-animation[twitch]:hover {
+ animation: quiver 2.25s infinite, quiver 1.45s infinite;
+}
+
+text-animation[tremble]:hover {
+ animation: leftward 0.1s infinite, quiver 0.75s infinite,
+ quiver 1.35s infinite;
+}
+
+text-animation[grow]:hover {
+ animation: maximize 1.4s infinite;
+}
+
+text-animation[shrink]:hover {
+ animation: minimize 1.25s infinite;
+}
+
+text-animation[grow]:hover,
+text-animation[shrink]:hover {
+ transform-origin: right 1rem;
+}
+
+text-animation[distort]:hover span {
+ animation: distort 0.25s infinite, distort 0.55s infinite,
+ distort 0.75s infinite;
+}
+
+text-animation[roll]:hover span {
+ animation: rotateY 1.5s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[flip]:hover span {
+ animation: rotateX 1.5s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[twirl]:hover span {
+ animation: rotateZ 1.5s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[wave]:hover span {
+ animation: up 1s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[skip]:hover span {
+ animation: skip 1s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[jiggle]:hover span {
+ animation: up 0.2s infinite, down 0.3s infinite, leftward 0.25s infinite;
+ animation-delay: calc(0.1s * var(--frame));
+}
+
+text-animation[float]:hover span {
+ animation: up 1s infinite;
+}
+
+text-animation[hop]:hover span {
+ animation: hop 1s infinite;
+}
+
+text-animation[shake]:hover span {
+ animation: left 0.15s infinite;
+}
+
+text-animation[waggle]:hover span {
+ animation: left 0.5s infinite;
+}
+
+text-animation[jump]:hover span {
+ animation: up 0.15s infinite;
+}
+
+text-animation[vibrate]:hover span {
+ animation: up 0.125s infinite, left 0.15s infinite;
+}
+
+main > * {
+ animation: paint ease-in 0.3s;
+}
+
+tab-bar,
+profile-box {
+ animation: paint ease-in 0.25s;
+}
+
+column-base[position="right"] time {
+ animation: paint ease-in 0.15s;
+}
+
+@keyframes paint {
+ 0%,
+ 90% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes rotateY {
+ 0%,
+ 10% {
+ transform: rotateY(360deg);
+ }
+}
+
+@keyframes rotateX {
+ 0%,
+ 10% {
+ transform: rotateX(360deg);
+ }
+}
+
+@keyframes rotateZ {
+ 0%,
+ 10% {
+ transform: rotateZ(360deg);
+ }
+}
+
+@keyframes tilt-rightward {
+ 50% {
+ transform: rotateZ(5deg);
+ }
+}
+
+@keyframes tilt-leftward {
+ 50% {
+ transform: rotateZ(-5deg);
+ }
+}
+
+@keyframes up {
+ 50% {
+ transform: translateY(-0.15rem);
+ }
+}
+
+@keyframes down {
+ 50% {
+ transform: translateY(0.15rem);
+ }
+}
+
+@keyframes left {
+ 50% {
+ transform: translateX(-0.15rem);
+ }
+}
+
+@keyframes leftward {
+ 50% {
+ transform: translateX(-0.05rem);
+ }
+}
+
+@keyframes squeeze {
+ 50% {
+ transform: scale(0.95, 1);
+ }
+}
+
+@keyframes maximize {
+ 0% {
+ transform: scale(1, 1.25);
+ }
+ 10% {
+ transform: scale(1, 1.05);
+ }
+ 20% {
+ transform: scale(1, 1.25);
+ }
+ 30% {
+ transform: scale(1, 1.1);
+ }
+ 40% {
+ transform: scale(1, 1.25);
+ }
+ 50% {
+ transform: none;
+ }
+}
+
+@keyframes minimize {
+ 0% {
+ transform: scale(0.75);
+ }
+ 10% {
+ transform: scale(0.95);
+ }
+ 20% {
+ transform: scale(0.75);
+ }
+ 30% {
+ transform: scale(0.85);
+ }
+ 40% {
+ transform: scale(0.75);
+ }
+ 50% {
+ transform: none;
+ }
+}
+
+@keyframes skip {
+ 0%,
+ 50%,
+ 100% {
+ transform: translateY(0);
+ }
+ 10% {
+ transform: translateY(-0.25rem);
+ }
+}
+
+@keyframes hop {
+ 0%,
+ 30%,
+ 50% {
+ transform: translateY(0);
+ }
+ 10%,
+ 40% {
+ transform: translateY(-0.25rem);
+ }
+}
+
+@keyframes quiver {
+ 5% {
+ transform: translateY(-0.025rem) skewX(-5deg) scale(0.9);
+ }
+ 10% {
+ transform: none;
+ }
+}
+
+@keyframes distort {
+ 20% {
+ text-shadow: 4px 0 var(--background);
+ }
+ 50% {
+ text-shadow: -4px 0 var(--background);
+ }
+ 100% {
+ text-shadow: none;
+ }
+}
diff --git a/assets/data/media/logo.png b/assets/data/media/logo.png
index 51baf7d..98b4003 100644
--- a/assets/data/media/logo.png
+++ b/assets/data/media/logo.png
Binary files differ
diff --git a/assets/js/index.js b/assets/js/index.js
index 1c2715b..d698127 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -1,52 +1,168 @@
-// deno-fmt-ignore-file
-// deno-lint-ignore-file
-// This code was bundled using `deno bundle` and it's not recommended to edit it manually
-
(function() {
- const url = self.location.href.split("#")[0];
- let settings = {
- pager: {}
+ const cookiesDisabled = !navigator.cookieEnabled;
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Pager disabled due to cookie restrictions");
+ }
+ let seek;
+ let pager = {};
+ const key = "config.scroll.pager.urls";
+ if (!localStorage[key]) localStorage[key] = JSON.stringify(pager);
+ let url = function() {
+ return self.location.href.split("#")[0].split("?")[0];
};
- self.addEventListener("DOMContentLoaded", function() {
- if (history.scrollRestoration) history.scrollRestoration = "manual";
- if (localStorage["settings"]) {
- settings = JSON.parse(localStorage["settings"]);
+ const scrollHash = function(url) {
+ const hash = self.location.hash;
+ const fragment = hash.slice(1) && document.getElementById(hash.slice(1));
+ const fragmented = hash.length > 0;
+ const hashed = fragmented && document.body.contains(fragment);
+ if (hashed) {
+ self.location.hash = hash;
+ self.location.href = hash;
+ if ("scroll-margin-top" in document.body.style === false && fragment.textContent !== "") {
+ self.scrollBy(0, -6 * parseFloat(getComputedStyle(document.documentElement).fontSize));
+ }
}
- if (self.location.hash.length > 0) {
- settings["pager"][url] = self.pageYOffset;
- localStorage["settings"] = JSON.stringify(settings);
- document.getElementById(location.hash.slice(1)).scrollIntoView();
- self.addEventListener("load", function() {
- document.getElementById(location.hash.slice(1)).scrollIntoView();
- });
- return;
+ return hashed;
+ };
+ const scrollRestore = function(url) {
+ if (history.scrollRestoration) history.scrollRestoration = "manual";
+ if (scrollHash(url)) return;
+ pager = JSON.parse(localStorage[key]);
+ if (pager[url] > 0) {
+ clearInterval(seek);
+ self.scrollTo(0, pager[url]);
+ let i1 = 0;
+ return seek = setInterval(function(position) {
+ i1++;
+ if (i1 > 100) clearInterval(seek);
+ if (document.documentElement.scrollHeight >= position + document.documentElement.clientHeight) {
+ clearInterval(seek);
+ self.scrollTo(0, position);
+ }
+ }, 4, pager[url]);
+ } else self.scrollTo(0, 0);
+ pager[url] = self.pageYOffset;
+ localStorage[key] = JSON.stringify(pager);
+ };
+ const scrollTrack = function(url) {
+ const currentPosition = self.pageYOffset;
+ pager = JSON.parse(localStorage[key]);
+ pager[url] = currentPosition;
+ localStorage[key] = JSON.stringify(pager);
+ };
+ const scrollReverse = function(back, up, event) {
+ if (document.body.contains(up) && up.contains(event.target)) {
+ event.preventDefault();
+ window.scrollTo(0, 0);
}
- if (settings["pager"][url] > 0) {
- self.scrollTo(0, settings["pager"][url]);
- return;
+ if (document.body.contains(back) && back.contains(event.target)) {
+ if (history.length < 2) return;
+ event.preventDefault();
+ history.go(-1);
}
- settings["pager"][url] = self.pageYOffset;
- localStorage["settings"] = JSON.stringify(settings);
+ };
+ [
+ "DOMContentLoaded",
+ "pageshow",
+ "hashchange",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ if (event.type === "pageshow") {
+ return event.persisted && self.scrollTo(0, pager[url()]);
+ }
+ if (event.type === "DOMContentLoaded") {
+ self.addEventListener("click", function(event) {
+ const up = document.getElementById("top");
+ const back = document.getElementById("back");
+ scrollReverse(back, up, event);
+ });
+ }
+ scrollRestore(url());
+ });
});
- self.addEventListener("scroll", function() {
- const currentPosition = self.pageYOffset;
- settings["pager"][url] = currentPosition;
- localStorage["settings"] = JSON.stringify(settings);
+ [
+ "click",
+ "touchstart",
+ "scroll"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ scrollTrack(url());
+ });
});
- self.addEventListener("DOMContentLoaded", function() {
- const up = document.getElementById("top");
- const back = document.getElementById("back");
- self.addEventListener("click", function(event) {
- if (document.body.contains(up) && up.contains(event.target)) {
- event.preventDefault();
- window.scrollTo(0, 0);
- }
- if (document.body.contains(back) && back.contains(event.target)) {
- if (history.length < 2) return;
- event.preventDefault();
- history.go(-1);
+})();
+(function() {
+ const cookiesDisabled = !navigator.cookieEnabled;
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Update check disabled due to cookie restrictions");
+ }
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200) {
+ if (callback) callback(http);
+ }
+ };
+ http.open(method, url);
+ http.setRequestHeader("Pragma", "no-cache");
+ http.setRequestHeader("Cache-Control", "no-cache");
+ http.send();
+ return http;
+ }
+ const key = "config.update";
+ let stamps = {};
+ if (!sessionStorage[key + ".urls"]) sessionStorage[key + ".urls"] = JSON.stringify(stamps);
+ function update() {
+ const url = self.location.href.split("#")[0].split("?")[0];
+ const indicator = document.querySelector("a[data-update]");
+ if (indicator === null || indicator.dataset.update === "refresh") return;
+ indicator.cloneNode();
+ fetch(url, "HEAD", function(request) {
+ const local = document.querySelector('meta[name="last-modified"]').content || document.lastModified;
+ const remote = request.getResponseHeader("last-modified") || '';
+ const modified = Date.parse(remote || local) > Date.parse(local);
+ const drift = Date.parse(remote || local) - Date.parse(local);
+ if (drift < 10000) return;
+ stamps = JSON.parse(sessionStorage[key + ".urls"]);
+ if (stamps[url] === remote) return;
+ stamps[url] = remote;
+ sessionStorage[key + ".urls"] = JSON.stringify(stamps);
+ if (remote && modified) {
+ fetch(url, "GET", function() {
+ indicator.href = url.replace(/^https:/, "http:");
+ indicator.removeAttribute("id");
+ indicator.dataset.update = "refresh";
+ console.log("INFO: R: " + remote);
+ console.log("INFO: L: " + local);
+ console.log("INFO: D: " + drift);
+ console.log("INFO: M: " + modified);
+ });
}
});
+ }
+ let scrolled;
+ let delay = 1000;
+ let delayed = 0;
+ self.addEventListener("scroll", function() {
+ if (scrolled) clearTimeout(scrolled);
+ scrolled = setTimeout(function() {
+ update();
+ delay = delay + delayed;
+ delayed = delay - delayed;
+ }, delay);
+ });
+ [
+ "focus",
+ "load",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ update();
+ });
});
})();
(function() {
@@ -81,350 +197,709 @@
}
})();
(function() {
- self.addEventListener("DOMContentLoaded", function() {
- let mouseoverTimer;
- let lastTouchTimestamp;
- const prefetches = new Set();
- const prefetchElement = document.createElement("link");
- const isSupported = prefetchElement.relList && prefetchElement.relList.supports && prefetchElement.relList.supports("prefetch") && window.IntersectionObserver && "isIntersecting" in IntersectionObserverEntry.prototype;
- const allowQueryString = "instantAllowQueryString" in document.body.dataset;
- const allowExternalLinks = "instantAllowExternalLinks" in document.body.dataset;
- const useWhitelist = "instantWhitelist" in document.body.dataset;
- const mousedownShortcut = "instantMousedownShortcut" in document.body.dataset;
- let delayOnHover = 65;
- let useMousedown = false;
- let useMousedownOnly = false;
- let useViewport = false;
- if ("instantIntensity" in document.body.dataset) {
- const intensity = document.body.dataset.instantIntensity;
- if (intensity.substr(0, "mousedown".length) == "mousedown") {
- useMousedown = true;
- if (intensity == "mousedown-only") {
- useMousedownOnly = true;
- }
- } else if (intensity.substr(0, "viewport".length) == "viewport") {
- if (!(navigator.connection && (navigator.connection.saveData || navigator.connection.effectiveType && navigator.connection.effectiveType.includes("2g")))) {
- if (intensity == "viewport") {
- if (document.documentElement.clientWidth * document.documentElement.clientHeight < 450000) {
- useViewport = true;
- }
- } else if (intensity == "viewport-all") {
- useViewport = true;
- }
- }
- } else {
- const milliseconds = parseInt(intensity);
- if (!isNaN(milliseconds)) {
- delayOnHover = milliseconds;
- }
- }
+ if (typeof Element !== "undefined") {
+ if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
}
- if (isSupported) {
- const eventListenersOptions = {
- capture: true,
- passive: true
+ if (!Element.prototype.closest) {
+ Element.prototype.closest = function(s) {
+ var el = this;
+ do {
+ if (el.matches(s)) return el;
+ el = el.parentElement || el.parentNode;
+ }while (el !== null && el.nodeType === 1)
+ return null;
};
- if (!useMousedownOnly) {
- document.addEventListener("touchstart", touchstartListener, eventListenersOptions);
- }
- if (!useMousedown) {
- document.addEventListener("mouseover", mouseoverListener, eventListenersOptions);
- } else if (!mousedownShortcut) {
- document.addEventListener("mousedown", mousedownListener, eventListenersOptions);
- }
- if (mousedownShortcut) {
- document.addEventListener("mousedown", mousedownShortcutListener, eventListenersOptions);
- }
- if (useViewport) {
- let triggeringFunction;
- if (window.requestIdleCallback) {
- triggeringFunction = function(callback) {
- requestIdleCallback(callback, {
- timeout: 1500
- });
- };
- } else {
- triggeringFunction = function(callback) {
- callback();
- };
- }
- triggeringFunction(function() {
- const intersectionObserver = new IntersectionObserver(function(entries) {
- entries.forEach(function(entry) {
- if (entry.isIntersecting) {
- const linkElement = entry.target;
- intersectionObserver.unobserve(linkElement);
- preload(linkElement.href);
- }
- });
- });
- document.querySelectorAll("a").forEach(function(linkElement) {
- if (isPreloadable(linkElement)) {
- intersectionObserver.observe(linkElement);
- }
- });
- });
- }
}
- function touchstartListener(event) {
- lastTouchTimestamp = performance.now();
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
- return;
+ }
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200) {
+ if (callback) callback(http);
+ }
+ };
+ http.open(method, url);
+ http.send();
+ return http;
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ [
+ "mouseout",
+ "mousedown",
+ "touchstart"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ const url = event.target.closest("a");
+ if (preloadable(url) === undefined) return;
+ preload(url.href);
+ });
+ });
+ function preloadable(url) {
+ switch(true){
+ case url === null || url.href === null:
+ return;
+ case url.origin !== location.origin:
+ return;
+ case [
+ "http:",
+ "https:"
+ ].includes(url.protocol) === null:
+ return;
+ case url.protocol === "http:" && location.protocol === "https:":
+ return;
+ case url.hash && url.pathname + url.search == location.pathname + location.search:
+ return;
+ default:
+ return true;
}
- preload(linkElement.href);
}
- function mouseoverListener(event) {
- if (performance.now() - lastTouchTimestamp < 1111) {
- return;
- }
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
+ function preload(url) {
+ const prefetcher = document.createElement("link");
+ prefetcher.rel = "custom-prefetch";
+ prefetcher.href = url;
+ const selector = 'link[rel="'.concat(prefetcher.rel, '"][href="').concat(prefetcher.href, '"]');
+ const prefetched = document.head.contains(document.querySelector(selector));
+ if (prefetched) {
return;
}
- linkElement.addEventListener("mouseout", mouseoutListener, {
- passive: true
- });
- mouseoverTimer = setTimeout(function() {
- preload(linkElement.href);
- mouseoverTimer = undefined;
- }, delayOnHover);
+ document.head.appendChild(prefetcher);
+ fetch(url, "GET", function() {});
}
- function mousedownListener(event) {
- const linkElement = event.target.closest("a");
- if (!isPreloadable(linkElement)) {
- return;
- }
- preload(linkElement.href);
+ });
+})();
+(function() {
+ const hide = function(triggers) {
+ for(let i1 = 0; i1 < triggers.length; i1++){
+ triggers[i1].checked = false;
}
- function mouseoutListener(event) {
- if (event.relatedTarget && event.target.closest("a") == event.relatedTarget.closest("a")) {
- return;
+ };
+ const hideIfClickedOutside = function(menus, triggers, event) {
+ for(let i1 = 0; i1 < menus.length; i1++){
+ const active = triggers[i1].checked === true;
+ const outside = !menus[i1].contains(event.target);
+ if (outside && active) hide(triggers);
+ }
+ };
+ self.addEventListener("scroll", function() {
+ const triggers = document.querySelectorAll("menu input");
+ hide(triggers);
+ });
+ [
+ "click",
+ "touchstart"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ const menus = document.querySelectorAll("menu");
+ const triggers = document.querySelectorAll("menu input");
+ hideIfClickedOutside(menus, triggers, event);
+ });
+ });
+})();
+(function() {
+ [
+ "DOMContentLoaded",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ const container = document.querySelector("search-box");
+ const dropdown = document.querySelector("search-box ul");
+ const form = document.querySelector("search-box form");
+ const query = document.querySelector("search-box input");
+ const submit = document.querySelector("search-box button");
+ function first(element) {
+ if (element.firstChild.nextElementSibling) {
+ return element.firstChild.nextElementSibling.firstChild.nextElementSibling;
+ }
}
- if (mouseoverTimer) {
- clearTimeout(mouseoverTimer);
- mouseoverTimer = undefined;
+ function last(element) {
+ return element.lastElementChild.firstChild.nextElementSibling;
}
- }
- function mousedownShortcutListener(event1) {
- if (performance.now() - lastTouchTimestamp < 1111) {
- return;
+ function next(element) {
+ return element.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus();
}
- const linkElement = event1.target.closest("a");
- if (event1.which > 1 || event1.metaKey || event1.ctrlKey) {
- return;
+ function previous(element) {
+ return element.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus();
}
- if (!linkElement) {
- return;
+ function press(keyname) {
+ document.dispatchEvent(new KeyboardEvent("keydown", {
+ "key": keyname
+ }));
}
- linkElement.addEventListener("click", function(event) {
- if (event.detail == 1337) {
- return;
+ let selected;
+ if (submit === null) return;
+ submit.addEventListener("click", function(event) {
+ if (selected) {
+ event.preventDefault();
+ selected.focus();
+ return selected.click();
}
+ first(dropdown).focus();
+ press("ArrowDown");
+ document.activeElement.click();
+ });
+ [
+ "keyup",
+ "click"
+ ].forEach(function(event) {
+ form.addEventListener(event, function() {
+ if (document.activeElement.nodeName === "A") {
+ return selected = document.activeElement;
+ }
+ selected = undefined;
+ });
+ });
+ form.addEventListener("focusin", function() {
+ container.setAttribute("data-focus", "");
+ initialize();
+ });
+ form.addEventListener("submit", function(event) {
event.preventDefault();
- }, {
- capture: true,
- passive: false,
- once: true
+ return false;
});
- const customEvent = new MouseEvent("click", {
- view: window,
- bubbles: true,
- cancelable: false,
- detail: 1337
+ form.addEventListener("keydown", function(event) {
+ if (form.contains(event.target)) {
+ if (event.keyCode == 27) {
+ document.activeElement.blur();
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
+ }
+ }
+ if (event.keyCode == 8) {
+ if (document.activeElement != query) {
+ event.preventDefault();
+ query.focus();
+ }
+ }
+ const head = first(dropdown);
+ const tail = last(dropdown);
+ if (event.keyCode == 40) {
+ event.preventDefault();
+ if (document.activeElement == query) head.focus();
+ else if (document.activeElement == tail) query.focus();
+ else next(document);
+ }
+ if (event.keyCode == 38) {
+ event.preventDefault();
+ if (document.activeElement == query) tail.focus();
+ else if (document.activeElement == head) query.focus();
+ else previous(document);
+ }
+ if (event.keyCode == 13) {
+ if (dropdown && document.activeElement == query) {
+ event.preventDefault();
+ head.focus();
+ head.click();
+ }
+ }
});
- linkElement.dispatchEvent(customEvent);
- }
- function isPreloadable(linkElement) {
- if (!linkElement || !linkElement.href) {
- return;
- }
- if (useWhitelist && !("instant" in linkElement.dataset)) {
- return;
- }
- if (!allowExternalLinks && linkElement.origin != location.origin && !("instant" in linkElement.dataset)) {
- return;
- }
- if (![
- "http:",
- "https:"
- ].includes(linkElement.protocol)) {
- return;
+ let scrolls = 0;
+ self.addEventListener("scroll", function() {
+ if (scrolls > 3) {
+ scrolls = 0;
+ document.activeElement.blur();
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
+ }
+ scrolls++;
+ });
+ self.addEventListener("click", function(event) {
+ if (!form.contains(event.target) && !(document.activeElement === query) && !(document.activeElement === submit)) {
+ dropdown.setAttribute("hidden", "");
+ container.removeAttribute("data-focus");
+ }
+ });
+ function fetch(url, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (http.readyState === 4 && http.status === 200 && callback) {
+ callback(http);
+ }
+ };
+ http.open("GET", url);
+ http.send();
+ }
+ function script(url) {
+ return new Promise(function(resolve, reject) {
+ const script = document.createElement("script");
+ script.onerror = reject;
+ script.onload = resolve;
+ if (document.currentScript) {
+ document.currentScript.parentNode.insertBefore(script, document.currentScript);
+ } else document.head.appendChild(script);
+ script.src = url;
+ });
}
- if (linkElement.protocol == "http:" && location.protocol == "https:") {
- return;
+ let data = {};
+ let boot = true;
+ const options = {
+ key: [
+ "title"
+ ]
+ };
+ function isEmpty(obj) {
+ return Object.keys(obj).length === 0;
}
- if (!allowQueryString && linkElement.search && !("instant" in linkElement.dataset)) {
- return;
+ function appendItemsTo(local, remote) {
+ const paginated = Object.keys(remote).includes("next_url");
+ if (isEmpty(local)) {
+ local = remote;
+ } else {
+ local.items = local.items.concat(remote.items);
+ }
+ if (paginated) {
+ fetch(remote.next_url, function(request) {
+ appendItemsTo(local, JSON.parse(request.responseText));
+ });
+ } else search(query.value, data.items, options);
+ data = local;
+ }
+ function initialize() {
+ if (boot) {
+ script(window.location.origin + "/js/fuzzysort.js").then(function() {
+ fetch("/index.json", function(request) {
+ appendItemsTo({}, JSON.parse(request.responseText));
+ search("", data.items, options);
+ boot = false;
+ });
+ [
+ "keyup",
+ "focusin"
+ ].forEach(function(event) {
+ query.addEventListener(event, function() {
+ if (data.items) search(query.value, data.items, options);
+ else {
+ boot = true;
+ initialize();
+ }
+ });
+ });
+ }).catch(function(error) {
+ console.error("ERROR: Failed to load fuzzy search", error);
+ });
+ }
}
- if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) {
- return;
+ function escape(text) {
+ const escaped = document.createElement("textarea");
+ escaped.textContent = text;
+ return escaped.innerHTML;
+ }
+ function search(term, data, options) {
+ const results = fuzzysort.go(term, data, options);
+ let items = "";
+ if (results.length === 0 && term.length >= 0) {
+ let separator = "—";
+ if (term.length === 0) separator = "";
+ items = '<li><a tabindex="0">'.concat(escape(term), " ").concat(separator, " No Results Found</a></li>");
+ dropdown.removeAttribute("hidden");
+ container.setAttribute("data-focus", "");
+ } else {
+ dropdown.removeAttribute("hidden");
+ for(var string in results.slice(0, 10)){
+ const title = results[string].obj.title;
+ let highlight = fuzzysort.highlight(fuzzysort.single(escape(term), escape(title)), "<span>", "</span>");
+ if (highlight === null) highlight = title;
+ items = items + '\n<li>\n<a href="'.concat(results[string].obj.url, '" tabindex="0">').concat(highlight, "</a>\n</li>\n");
+ }
+ }
+ dropdown.innerHTML = items;
}
- if ("noInstant" in linkElement.dataset) {
- return;
+ });
+ });
+})();
+(function() {
+ function viewport(element) {
+ const options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
+ offset: {
+ top: -50,
+ left: 0,
+ bottom: -50,
+ right: 0
+ }
+ };
+ const view = element.getBoundingClientRect();
+ return view.top >= -options.offset.top && view.left >= -options.offset.left && view.bottom <= (self.innerHeight || document.documentElement.clientHeight) + options.offset.bottom && view.right <= (self.innerWidth || document.documentElement.clientWidth) + options.offset.right;
+ }
+ [
+ "scroll",
+ "DOMContentLoaded"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ let first = true;
+ let videos = document.querySelectorAll("video");
+ for(i = 0; i < videos.length; i++){
+ videos[i].autoplay = true;
+ videos[i].controls = true;
+ videos[i].loop = true;
+ videos[i].muted = true;
+ videos[i].playsinline = true;
+ videos[i].setAttribute("autoplay", true);
+ videos[i].setAttribute("controls", true);
+ videos[i].setAttribute("loop", true);
+ videos[i].setAttribute("muted", true);
+ videos[i].setAttribute("playsinline", true);
+ const onscreen = viewport(videos[i]);
+ if (first && onscreen) {
+ videos[i].play();
+ first = false;
+ } else {
+ videos[i].pause();
+ }
}
- return true;
+ });
+ });
+})();
+(function() {
+ if (typeof Element !== "undefined") {
+ if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
}
- function preload(url) {
- if (prefetches.has(url)) {
- return;
- }
- const prefetcher = document.createElement("link");
- prefetcher.rel = "prefetch";
- prefetcher.href = url;
- document.head.appendChild(prefetcher);
- prefetches.add(url);
+ if (!Element.prototype.closest) {
+ Element.prototype.closest = function(s) {
+ var el = this;
+ do {
+ if (el.matches(s)) return el;
+ el = el.parentElement || el.parentNode;
+ }while (el !== null && el.nodeType === 1)
+ return null;
+ };
+ }
+ }
+ const disabled = "0s";
+ function walk(children, callback) {
+ for(let i1 = 0; i1 < children.length; i1++){
+ callback(children[i1]);
+ walk(children[i1].children, callback);
+ }
+ }
+ self.addEventListener("mousemove", function(event) {
+ if (typeof event.target.closest !== "function") return;
+ tree = event.target.closest("figure") || event.target.closest("article");
+ if (tree !== null) {
+ walk(tree.children, function(element) {
+ const delay = self.getComputedStyle(element).getPropertyValue("transition-delay");
+ if (delay !== disabled) {
+ element.style.setProperty("visibility", "hidden");
+ }
+ });
+ walk(tree.children, function(element) {
+ const delay = self.getComputedStyle(element).getPropertyValue("transition-delay");
+ if (delay !== disabled) {
+ element.style.removeProperty("visibility");
+ }
+ });
}
});
})();
(function() {
- self.addEventListener("DOMContentLoaded", function() {
- const form = document.getElementById("search-form");
- const query = document.getElementById("search-input");
- document.getElementById("search-submit");
- const dropdown = document.getElementById("search-results");
- const container = document.getElementById("search-frame");
- form.addEventListener("focusin", function() {
- initialize();
- });
- form.addEventListener("submit", function(event) {
- event.preventDefault();
- return false;
- });
- form.addEventListener("keydown", function(event) {
- const head = dropdown.firstChild.nextElementSibling.firstChild.nextElementSibling;
- const tail = dropdown.lastElementChild.firstChild.nextElementSibling;
- if (query.contains(event.target)) {
- if (event.keyCode == 27) {
- document.activeElement.blur();
- dropdown.setAttribute("hidden", "");
- }
- }
- if (event.keyCode == 40) {
- event.preventDefault();
- if (document.activeElement == query) head.focus();
- else if (document.activeElement == tail) query.focus();
- else {
- document.activeElement.parentElement.nextElementSibling.firstChild.nextElementSibling.focus();
+ const cookiesDisabled = !navigator.cookieEnabled;
+ if (cookiesDisabled) {
+ document.cookie = "disabled";
+ document.cookie.indexOf("disabled");
+ return console.warn("WARNING: Cannot persist form state due to cookie restrictions");
+ }
+ const storage = document.createEvent("Event");
+ storage.initEvent("storage", true, true);
+ [
+ "pageshow",
+ "URLChangedCustomEvent",
+ "DOMContentLoaded"
+ ].forEach(function(event) {
+ self.addEventListener(event, function(event) {
+ const input = Array.prototype.slice.call(document.querySelectorAll("form input"));
+ const select = Array.prototype.slice.call(document.querySelectorAll("form select"));
+ const textarea = Array.prototype.slice.call(document.querySelectorAll("form textarea"));
+ const summary = Array.prototype.slice.call(document.querySelectorAll("details summary"));
+ const states = input.concat(select).concat(textarea);
+ for(var i1 = 0; i1 < states.length; i1++){
+ const state = states[i1];
+ const sync = i1 === states.length - 1;
+ if (localStorage[state.id]) {
+ if (state.type === "radio" || state.type === "checkbox") {
+ if (localStorage[state.id] === "on") state.checked = true;
+ } else state.value = localStorage[state.id];
}
+ if (sync) self.dispatchEvent(storage);
+ state.addEventListener("change", function(event) {
+ localStorage[event.target.id] = event.target.value;
+ const group = document.querySelectorAll("input[name='".concat(event.target.name, "']"));
+ for(var j = 0; j < group.length; j++){
+ const member = group[j];
+ if ((member.type === "radio" || member.type === "checkbox") && !member.checked) {
+ localStorage[member.id] = "off";
+ }
+ }
+ self.dispatchEvent(new Event("storage"));
+ });
}
- if (event.keyCode == 38) {
- event.preventDefault();
- if (document.activeElement == query) tail.focus();
- else if (document.activeElement == head) query.focus();
- else {
- document.activeElement.parentElement.previousElementSibling.firstChild.nextElementSibling.focus();
+ for(var k = 0; k < summary.length; k++){
+ let child = summary[k];
+ let details = child.parentElement;
+ if (details.id && details.nodeName === "DETAILS") {
+ sessionStorage[details.id] === "false" && details.removeAttribute("open");
+ sessionStorage[details.id] === "true" && details.setAttribute("open", true);
+ child.addEventListener("click", function(event) {
+ let child = event.target.nodeName === "SUMMARY" && event.target || event.target.parentElement;
+ let details = child.parentElement;
+ if (details.id && details.nodeName === "DETAILS") {
+ sessionStorage[details.id] = !details.open;
+ }
+ });
}
}
- if (event.keyCode == 8) {
- if (document.activeElement != query) {
- event.preventDefault();
- query.focus();
+ });
+ });
+ [
+ "storage"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ let stylesheet;
+ stylesheet = document.querySelector('link[href$="default-simple.css"]');
+ if (localStorage["config.layout.simple"] === "on") stylesheet.rel = "stylesheet";
+ if (localStorage["config.layout.default"] === "on") stylesheet.rel = "alternate stylesheet";
+ stylesheet = document.querySelector('link[href$="default-fast.css"]');
+ if (localStorage["config.navigation.fast"] === "on") stylesheet.rel = "stylesheet";
+ if (localStorage["config.navigation.slow"] === "on") stylesheet.rel = "alternate stylesheet";
+ for(var i1 = 0; i1 < document.styleSheets.length; i1++){
+ let stylesheet = document.styleSheets[i1];
+ for(var k = 0; k < stylesheet.rules.length; k++){
+ let media = stylesheet.rules[k].media;
+ if (media && media.mediaText.includes("prefers-color-scheme")) {
+ if (localStorage["config.theme.light"] === "on") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ if (getComputedStyle(document.body).getPropertyValue("color-scheme") === "dark") {
+ media.mediaText = "(prefers-color-scheme: light)";
+ }
+ }
+ if (localStorage["config.theme.auto"] === "on") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ }
+ if (localStorage["config.theme.dark"] === "on") {
+ media.mediaText = "(prefers-color-scheme: light)";
+ if (getComputedStyle(document.body).getPropertyValue("color-scheme") === "light") {
+ media.mediaText = "(prefers-color-scheme: dark)";
+ }
+ }
+ }
}
}
- if (event.keyCode == 13) {
- if (dropdown && document.activeElement == query) {
- event.preventDefault();
- head.focus();
- self.window.location = document.activeElement.href;
+ });
+ });
+ const early = setInterval(persistence, 4);
+ function persistence() {
+ if (document.styleSheets.length > 0) {
+ self.dispatchEvent(storage);
+ clearInterval(early);
+ }
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ self.dispatchEvent(storage);
+ clearInterval(early);
+ });
+})();
+(function() {
+ const timeout = 300;
+ const state = "on";
+ const key = "config.navigation.fast";
+ function fetch(url, method, callback) {
+ const http = new XMLHttpRequest();
+ http.onreadystatechange = function() {
+ if (callback && http.readyState === 4) {
+ if (http.status === 200) callback(http);
+ else {
+ console.error("ERROR: Unable to navigate", http);
+ self.location.href = url;
}
}
- });
- let scrolls = 0;
- self.addEventListener("scroll", function() {
- if (scrolls > 3) {
- scrolls = 0;
- document.activeElement.blur();
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
+ };
+ http.open(method, url);
+ http.timeout = timeout;
+ http.send();
+ return http;
+ }
+ function styles(node) {
+ return node.nodeName === "LINK" && node.rel && node.rel.includes("stylesheet");
+ }
+ function scripts(node) {
+ return node.nodeName === "SCRIPT" && node.hasAttribute("src");
+ }
+ function filter(url, http) {
+ let live = document;
+ let node = live.head.childNodes.length;
+ let next = new DOMParser().parseFromString(http.responseText, "text/html");
+ if (next.doctype === null || !http.getResponseHeader("content-type").includes("text/html")) return false;
+ while(node--){
+ if (styles(live.head.childNodes[node]) || scripts(live.head.childNodes[node])) {} else {
+ live.head.removeChild(live.head.childNodes[node]);
}
- scrolls++;
- });
- document.addEventListener("click", function(event) {
- if (!form.contains(event.target)) {
- dropdown.setAttribute("hidden", "");
- container.removeAttribute("data-focus");
+ }
+ while(next.head.firstChild){
+ if (styles(next.head.firstChild) || scripts(next.head.firstChild)) {
+ next.head.removeChild(next.head.firstChild);
+ } else {
+ live.head.appendChild(next.head.firstChild);
}
- });
- function fetch_JSON(path, callback) {
- const httpRequest = new XMLHttpRequest();
- httpRequest.onreadystatechange = function() {
- if (httpRequest.readyState === 4) {
- if (httpRequest.status === 200) {
- const data = JSON.parse(httpRequest.responseText);
- if (callback) callback(data);
- }
- }
- };
- httpRequest.open("GET", path);
- httpRequest.send();
}
- function load_script(url) {
- return new Promise(function(resolve, reject) {
- const script = document.createElement("script");
- script.onerror = reject;
- script.onload = resolve;
- if (document.currentScript) {
- document.currentScript.parentNode.insertBefore(script, document.currentScript);
- } else {
- document.head.appendChild(script);
- }
- script.src = url;
- });
+ while(live.documentElement.attributes.length > 0){
+ live.documentElement.removeAttribute(live.documentElement.attributes[live.documentElement.attributes.length - 1].name);
}
- let first_run = true;
- function initialize() {
- if (first_run) {
- load_script(window.location.origin + "/js/fuzzysort.js").then(()=>{
- first_run = false;
- fetch_JSON("/index.json", function(data) {
- const options = {
- key: [
- "title"
- ]
- };
- query.addEventListener("keyup", function() {
- search(query.value, data.items, options);
- });
- query.addEventListener("focusin", function() {
- search(query.value, data.items, options);
- });
- search(query.value, data.items, options);
- });
- }).catch((error)=>{
- console.log("Error failed to load fuzzy sort: " + error);
+ while(next.documentElement.attributes.length > 0){
+ live.documentElement.setAttribute(next.documentElement.attributes[next.documentElement.attributes.length - 1].name, next.documentElement.attributes[next.documentElement.attributes.length - 1].value);
+ next.documentElement.removeAttribute(next.documentElement.attributes[next.documentElement.attributes.length - 1].name);
+ }
+ live.body.parentElement.replaceChild(next.body, live.body);
+ }
+ function persist() {
+ let persist = document.createElement("link");
+ persist.rel = "location";
+ persist.target = JSON.stringify(self.location);
+ document.head.appendChild(persist);
+ }
+ self.addEventListener("DOMContentLoaded", function() {
+ if (localStorage[key] !== state) return;
+ persist();
+ });
+ self.addEventListener("popstate", function(event) {
+ if (localStorage[key] !== state) return;
+ const link = JSON.parse(document.querySelector('link[rel="location"]').target);
+ const url = event.target.location;
+ const hashed = link.pathname === url.pathname;
+ if (hashed) return;
+ fetch(url, "GET", function(http) {
+ if (filter(url, http) === false) return self.location.href = url;
+ persist();
+ self.document.dispatchEvent(new CustomEvent("URLChangedCustomEvent", {
+ bubbles: true
+ }));
+ });
+ });
+ self.addEventListener("click", function(event) {
+ if (localStorage[key] !== state) return;
+ const links = document.querySelectorAll("a");
+ for(let i1 = 0; i1 < links.length; i1++){
+ const active = links[i1].contains(event.target);
+ const change = self.location.href !== links[i1].href;
+ const view = links[i1].attributes.hasOwnProperty("download") === false;
+ const local = self.location.origin === links[i1].origin && links[i1].target !== "_self";
+ const hashed = self.location.pathname === links[i1].pathname && links[i1].href.includes("#");
+ if (active && local && change && view && hashed === false) {
+ event.preventDefault();
+ const url = links[i1].href;
+ links[i1].style.cursor = "wait";
+ fetch(url, "GET", function(http) {
+ links[i1].removeAttribute("style");
+ if (filter(url, http) === false) return self.location.href = url;
+ history.pushState({}, "", links[i1].href);
+ persist();
+ self.document.dispatchEvent(new CustomEvent("URLChangedCustomEvent", {
+ bubbles: true
+ }));
});
}
}
- function search(term, data, options) {
- const results = fuzzysort.go(term, data, options);
- let items = "";
- if (results.length === 0 && term.length >= 0) {
- let separator = "—";
- if (term.length === 0) separator = "";
- items = `
- <li>
- <a href="javascript: void(0)" tabindex="0">${term} ${separator} No Results Found</a>
- </li>
- `;
- dropdown.removeAttribute("hidden");
- container.setAttribute("data-focus", "");
- } else {
- dropdown.removeAttribute("hidden");
- for(const string in results.slice(0, 10)){
- let highlight = fuzzysort.highlight(fuzzysort.single(term, results[string].obj.title), "<span>", "</span>");
- if (highlight === null) {
- highlight = results[string].obj.title;
+ });
+})();
+(function() {
+ const relative = new Intl.RelativeTimeFormat("en", {
+ localeMatcher: "best fit",
+ numeric: "always",
+ style: "long"
+ });
+ function viewport(element) {
+ const options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
+ offset: 250
+ };
+ const view = element.getBoundingClientRect();
+ return view.top >= -options.offset && view.left >= -options.offset && view.bottom <= (self.innerHeight || document.documentElement.clientHeight) + options.offset && view.right <= (self.innerWidth || document.documentElement.clientWidth) + options.offset;
+ }
+ const date = function(update) {
+ const elements = document.querySelectorAll("time");
+ for(let i1 = 0; i1 < elements.length; ++i1){
+ const offscreen = !viewport(elements[i1]);
+ const hidden = elements[i1].offsetParent === null;
+ if (update === "viewport" && (offscreen || hidden)) continue;
+ (function(element) {
+ try {
+ if (element.dataset.type === "disabled") return;
+ const time = new Date(element.dateTime) || new Date();
+ const interval = (new Date().getTime() - time.getTime()) / 1000;
+ const seconds = Math.round(interval);
+ const minutes = Math.round(seconds / 60);
+ const hours = Math.round(minutes / 60);
+ const days = Math.round(hours / 24);
+ const past = Math.sign(seconds) === 1;
+ const future = Math.sign(seconds) === -1;
+ let tiny = function(string, place) {
+ return string.split(" ").slice(0, place).join(" ") + string.split(" ")[place].charAt(0);
+ };
+ if (element.dataset.type === "default") {
+ tiny = function(string) {
+ return string;
+ };
+ }
+ if (element.dataset.type === "localDate") {
+ return element.textContent = new Intl.DateTimeFormat([], {
+ dateStyle: "medium"
+ }).format(time).replace(",", "");
}
- items = items + `
- <li>
- <a href="${results[string].obj.url}" tabindex="0">${highlight}</a>
- </li>
- `;
+ if (element.dataset.type === "localTime") {
+ return element.textContent = new Intl.DateTimeFormat([], {
+ hour12: false,
+ timeStyle: "short"
+ }).format(time) + " " + new Intl.DateTimeFormat([], {
+ timeZoneName: "short"
+ }).format(time).split(" ")[1];
+ }
+ if (past) {
+ if (seconds <= 60) {
+ return element.textContent = tiny(relative.format(-1 * seconds, "second"), 1);
+ }
+ if (minutes <= 120) {
+ return element.textContent = tiny(relative.format(-1 * minutes, "minute"), 1);
+ }
+ if (hours <= 48) {
+ return element.textContent = tiny(relative.format(-1 * hours, "hour"), 1);
+ }
+ if (days <= 7) {
+ return element.textContent = tiny(relative.format(-1 * days, "day"), 1);
+ }
+ }
+ if (future) {
+ if (-1 * days >= 4) {
+ return element.textContent = tiny(relative.format(-1 * days, "day"), 2);
+ }
+ if (-1 * hours >= 3) {
+ return element.textContent = tiny(relative.format(-1 * hours, "hour"), 2);
+ }
+ if (-1 * minutes >= 2) {
+ return element.textContent = tiny(relative.format(-1 * minutes, "minute"), 2);
+ }
+ if (-1 * seconds >= 1) {
+ return element.textContent = tiny(relative.format(-1 * seconds, "second"), 2);
+ }
+ }
+ } catch (error) {
+ console.error("ERROR: Relative time resolution failed", error);
}
- }
- dropdown.innerHTML = items;
+ })(elements[i1]);
}
+ };
+ const substitution = setInterval(date, 4);
+ [
+ "scroll",
+ "URLChangedCustomEvent"
+ ].forEach(function(event) {
+ self.addEventListener(event, function() {
+ date("viewport");
+ });
+ });
+ self.addEventListener("DOMContentLoaded", function() {
+ setTimeout(function() {
+ clearInterval(substitution);
+ setInterval(function() {
+ date("viewport");
+ }, 1000);
+ }, 1000);
});
})();
-console.log("Surface Control: OK");
+console.log("INFO: Surface Control Complete"); \ No newline at end of file
diff --git a/assets/schemas/atom-v1.0.rng b/assets/schemas/atom-v1.0.rng
new file mode 100644
index 0000000..da47078
--- /dev/null
+++ b/assets/schemas/atom-v1.0.rng
@@ -0,0 +1,605 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ -*- rnc -*-
+ RELAX NG Compact Syntax Grammar for the
+ Atom Format Specification Version 11
+-->
+<grammar
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns:s="http://www.ascc.net/xml/schematron"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml"
+ xmlns="http://relaxng.org/ns/structure/1.0"
+ ns="http://www.w3.org/1999/xhtml"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
+ >
+ <start>
+ <choice>
+ <ref name="atomFeed"/>
+ <ref name="atomEntry"/>
+ </choice>
+ </start>
+ <!-- Common attributes -->
+ <define name="atomCommonAttributes">
+ <optional>
+ <attribute name="xml:base">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="xml:lang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <ref name="undefinedAttribute"/>
+ </zeroOrMore>
+ </define>
+ <!-- Text Constructs -->
+ <define name="atomPlainTextConstruct">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <choice>
+ <value>text</value>
+ <value>html</value>
+ </choice>
+ </attribute>
+ </optional>
+ <text/>
+ </define>
+ <define name="atomXHTMLTextConstruct">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="type">
+ <value>xhtml</value>
+ </attribute>
+ <ref name="xhtmlDiv"/>
+ </define>
+ <define name="atomTextConstruct">
+ <choice>
+ <ref name="atomPlainTextConstruct"/>
+ <ref name="atomXHTMLTextConstruct"/>
+ </choice>
+ </define>
+ <!-- Person Construct -->
+ <define name="atomPersonConstruct">
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <element name="atom:name">
+ <text/>
+ </element>
+ <optional>
+ <element name="atom:uri">
+ <ref name="atomUri"/>
+ </element>
+ </optional>
+ <optional>
+ <element name="atom:email">
+ <ref name="atomEmailAddress"/>
+ </element>
+ </optional>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </define>
+ <!-- Date Construct -->
+ <define name="atomDateConstruct">
+ <ref name="atomCommonAttributes"/>
+ <data type="dateTime"/>
+ </define>
+ <!-- atom:feed -->
+ <define name="atomFeed">
+ <element name="atom:feed">
+ <s:rule context="atom:feed">
+ <s:assert test="atom:author or not(atom:entry[not(atom:author)])">An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author.</s:assert>
+ </s:rule>
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomGenerator"/>
+ </optional>
+ <optional>
+ <ref name="atomIcon"/>
+ </optional>
+ <ref name="atomId"/>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomLogo"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSubtitle"/>
+ </optional>
+ <ref name="atomTitle"/>
+ <ref name="atomUpdated"/>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ <zeroOrMore>
+ <ref name="atomEntry"/>
+ </zeroOrMore>
+ </element>
+ </define>
+ <!-- atom:entry -->
+ <define name="atomEntry">
+ <element name="atom:entry">
+ <s:rule context="atom:entry">
+ <s:assert test="atom:link[@rel='alternate'] or atom:link[not(@rel)] or atom:content">An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content.</s:assert>
+ </s:rule>
+ <s:rule context="atom:entry">
+ <s:assert test="atom:author or ../atom:author or atom:source/atom:author">An atom:entry must have an atom:author if its feed does not.</s:assert>
+ </s:rule>
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomContent"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <ref name="atomId"/>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomPublished"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSource"/>
+ </optional>
+ <optional>
+ <ref name="atomSummary"/>
+ </optional>
+ <ref name="atomTitle"/>
+ <ref name="atomUpdated"/>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+ <!-- atom:content -->
+ <define name="atomInlineTextContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <choice>
+ <value>text</value>
+ <value>html</value>
+ </choice>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <text/>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="atomInlineXHTMLContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="type">
+ <value>xhtml</value>
+ </attribute>
+ <ref name="xhtmlDiv"/>
+ </element>
+ </define>
+ <define name="atomInlineOtherContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="atomOutOfLineContent">
+ <element name="atom:content">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <attribute name="src">
+ <ref name="atomUri"/>
+ </attribute>
+ <empty/>
+ </element>
+ </define>
+ <define name="atomContent">
+ <choice>
+ <ref name="atomInlineTextContent"/>
+ <ref name="atomInlineXHTMLContent"/>
+ <ref name="atomInlineOtherContent"/>
+ <ref name="atomOutOfLineContent"/>
+ </choice>
+ </define>
+ <!-- atom:author -->
+ <define name="atomAuthor">
+ <element name="atom:author">
+ <ref name="atomPersonConstruct"/>
+ </element>
+ </define>
+ <!-- atom:category -->
+ <define name="atomCategory">
+ <element name="atom:category">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="term"/>
+ <optional>
+ <attribute name="scheme">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="label"/>
+ </optional>
+ <ref name="undefinedContent"/>
+ </element>
+ </define>
+ <!-- atom:contributor -->
+ <define name="atomContributor">
+ <element name="atom:contributor">
+ <ref name="atomPersonConstruct"/>
+ </element>
+ </define>
+ <!-- atom:generator -->
+ <define name="atomGenerator">
+ <element name="atom:generator">
+ <ref name="atomCommonAttributes"/>
+ <optional>
+ <attribute name="uri">
+ <ref name="atomUri"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="version"/>
+ </optional>
+ <text/>
+ </element>
+ </define>
+ <!-- atom:icon -->
+ <define name="atomIcon">
+ <element name="atom:icon">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:id -->
+ <define name="atomId">
+ <element name="atom:id">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:logo -->
+ <define name="atomLogo">
+ <element name="atom:logo">
+ <ref name="atomCommonAttributes"/>
+ <ref name="atomUri"/>
+ </element>
+ </define>
+ <!-- atom:link -->
+ <define name="atomLink">
+ <element name="atom:link">
+ <ref name="atomCommonAttributes"/>
+ <attribute name="href">
+ <ref name="atomUri"/>
+ </attribute>
+ <optional>
+ <attribute name="rel">
+ <choice>
+ <ref name="atomNCName"/>
+ <ref name="atomUri"/>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="type">
+ <ref name="atomMediaType"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="hreflang">
+ <ref name="atomLanguageTag"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="title"/>
+ </optional>
+ <optional>
+ <attribute name="length"/>
+ </optional>
+ <ref name="undefinedContent"/>
+ </element>
+ </define>
+ <!-- atom:published -->
+ <define name="atomPublished">
+ <element name="atom:published">
+ <ref name="atomDateConstruct"/>
+ </element>
+ </define>
+ <!-- atom:rights -->
+ <define name="atomRights">
+ <element name="atom:rights">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:source -->
+ <define name="atomSource">
+ <element name="atom:source">
+ <ref name="atomCommonAttributes"/>
+ <interleave>
+ <zeroOrMore>
+ <ref name="atomAuthor"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomCategory"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="atomContributor"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomGenerator"/>
+ </optional>
+ <optional>
+ <ref name="atomIcon"/>
+ </optional>
+ <optional>
+ <ref name="atomId"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="atomLink"/>
+ </zeroOrMore>
+ <optional>
+ <ref name="atomLogo"/>
+ </optional>
+ <optional>
+ <ref name="atomRights"/>
+ </optional>
+ <optional>
+ <ref name="atomSubtitle"/>
+ </optional>
+ <optional>
+ <ref name="atomTitle"/>
+ </optional>
+ <optional>
+ <ref name="atomUpdated"/>
+ </optional>
+ <zeroOrMore>
+ <ref name="extensionElement"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+ <!-- atom:subtitle -->
+ <define name="atomSubtitle">
+ <element name="atom:subtitle">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:summary -->
+ <define name="atomSummary">
+ <element name="atom:summary">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:title -->
+ <define name="atomTitle">
+ <element name="atom:title">
+ <ref name="atomTextConstruct"/>
+ </element>
+ </define>
+ <!-- atom:updated -->
+ <define name="atomUpdated">
+ <element name="atom:updated">
+ <ref name="atomDateConstruct"/>
+ </element>
+ </define>
+ <!-- Low-level simple types -->
+ <define name="atomNCName">
+ <data type="string">
+ <param name="minLength">1</param>
+ <param name="pattern">[^:]*</param>
+ </data>
+ </define>
+ <!-- Whatever a media type is, it contains at least one slash -->
+ <define name="atomMediaType">
+ <data type="string">
+ <param name="pattern">.+/.+</param>
+ </data>
+ </define>
+ <!-- As defined in RFC 3066 -->
+ <define name="atomLanguageTag">
+ <data type="string">
+ <param name="pattern">[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*</param>
+ </data>
+ </define>
+ <!--
+ Unconstrained; it's not entirely clear how IRI fit into
+ xsd:anyURI so let's not try to constrain it here
+ -->
+ <define name="atomUri">
+ <text/>
+ </define>
+ <!-- Whatever an email address is, it contains at least one @ -->
+ <define name="atomEmailAddress">
+ <data type="string">
+ <param name="pattern">.+@.+</param>
+ </data>
+ </define>
+ <!-- Simple Extension -->
+ <define name="simpleExtensionElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <text/>
+ </element>
+ </define>
+ <!-- Structured Extension -->
+ <define name="structuredExtensionElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <choice>
+ <group>
+ <oneOrMore>
+ <attribute>
+ <anyName/>
+ </attribute>
+ </oneOrMore>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </group>
+ <group>
+ <zeroOrMore>
+ <attribute>
+ <anyName/>
+ </attribute>
+ </zeroOrMore>
+ <group>
+ <optional>
+ <text/>
+ </optional>
+ <oneOrMore>
+ <ref name="anyElement"/>
+ </oneOrMore>
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </group>
+ </group>
+ </choice>
+ </element>
+ </define>
+ <!-- Other Extensibility -->
+ <define name="extensionElement">
+ <choice>
+ <ref name="simpleExtensionElement"/>
+ <ref name="structuredExtensionElement"/>
+ </choice>
+ </define>
+ <define name="undefinedAttribute">
+ <attribute>
+ <anyName>
+ <except>
+ <name>xml:base</name>
+ <name>xml:lang</name>
+ <nsName ns=""/>
+ </except>
+ </anyName>
+ </attribute>
+ </define>
+ <define name="undefinedContent">
+ <zeroOrMore>
+ <choice>
+ <text/>
+ <ref name="anyForeignElement"/>
+ </choice>
+ </zeroOrMore>
+ </define>
+ <define name="anyElement">
+ <element>
+ <anyName/>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="anyForeignElement">
+ <element>
+ <anyName>
+ <except>
+ <nsName ns="http://www.w3.org/2005/Atom"/>
+ </except>
+ </anyName>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyElement"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <!-- XHTML -->
+ <define name="anyXHTML">
+ <element>
+ <nsName/>
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyXHTML"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+ <define name="xhtmlDiv">
+ <element name="xhtml:div">
+ <zeroOrMore>
+ <choice>
+ <attribute>
+ <anyName/>
+ </attribute>
+ <text/>
+ <ref name="anyXHTML"/>
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+</grammar>
+<!-- EOF -->
diff --git a/assets/schemas/jsonfeed-v1.1.json b/assets/schemas/jsonfeed-v1.1.json
new file mode 100644
index 0000000..0d6653d
--- /dev/null
+++ b/assets/schemas/jsonfeed-v1.1.json
@@ -0,0 +1,297 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "title": "JSON Feed",
+ "description": "JSON Feed Version 1.1",
+ "type": "object",
+ "properties": {
+ "version": {
+ "description": "The URL of the version of the format the feed uses. This should appear at the very top.",
+ "type": "string",
+ "format": "uri",
+ "enum": [
+ "https://jsonfeed.org/version/1",
+ "https://jsonfeed.org/version/1.1"
+ ]
+ },
+ "title": {
+ "description": "The name of the feed, which will often correspond to the name of the website (blog, for instance), though not necessarily.",
+ "type": "string"
+ },
+ "home_page_url": {
+ "description": "The URL of the resource that the feed describes. This resource may or may not actually be a “home” page, but it should be an HTML page. If a feed is published on the public web, this should be considered as required.",
+ "type": "string",
+ "format": "uri"
+ },
+ "feed_url": {
+ "description": "The URL of the feed, serves as the unique identifier for the feed. This should be considered required for feeds on the public web.",
+ "type": "string",
+ "format": "uri"
+ },
+ "description": {
+ "description": "Provides more detail, beyond the title, on what the feed is about. A feed reader may display this text.",
+ "type": "string"
+ },
+ "user_comment": {
+ "description": "A description of the purpose of the feed. This is for the use of people looking at the raw JSON, and should be ignored by feed readers.",
+ "type": "string"
+ },
+ "next_url": {
+ "description": "The URL of a feed that provides the next n items, where n is determined by the publisher. This allows for pagination, but with the expectation that reader software is not required to use it and probably won’t use it very often.",
+ "type": "string",
+ "format": "uri"
+ },
+ "icon": {
+ "description": "The URL of an image for the feed suitable to be used in a timeline, much the way an avatar might be used. It should be square and relatively large — such as 512 x 512 pixels — so that it can be scaled-down and so that it can look good on retina displays. It should use transparency where appropriate, since it may be rendered on a non-white background.",
+ "type": "string",
+ "format": "uri"
+ },
+ "favicon": {
+ "description": "The URL of an image for the feed suitable to be used in a source list. It should be square and relatively small, but not smaller than 64 x 64 pixels (so that it can look good on retina displays). This image should use transparency where appropriate, since it may be rendered on a non-white background.",
+ "type": "string",
+ "format": "uri"
+ },
+ "author": {
+ "description": "The feed author.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/author"
+ }
+ ]
+ },
+ "authors": {
+ "description": "One or more feed authors.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/author"
+ }
+ },
+ "language": {
+ "description": "The primary language for the feed in the format specified in RFC 5646. The value is usually a 2-letter language tag from ISO 639-1, optionally followed by a region tag.",
+ "type": "string"
+ },
+ "expired": {
+ "description": "Whether or not the feed is finished — that is, whether or not it will ever update again. A feed for a temporary event, such as an instance of the Olympics, could expire. If the value is true, then it’s expired. Any other value, or the absence of expired, means the feed may continue to update.",
+ "type": "boolean"
+ },
+ "hubs": {
+ "description": "Describes endpoints that can be used to subscribe to real-time notifications from the publisher of this feed.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "description": "Describes the protocol used to talk with the hub, such as “rssCloud” or “WebSub.”",
+ "type": "string"
+ },
+ "url": {
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "patternProperties": {
+ "^_[a-zA-Z][^.]*$": {
+ "$ref": "#/definitions/extension"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "type",
+ "url"
+ ]
+ }
+ },
+ "items": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "Unique for that item for that feed over time. If an item is ever updated, the id should be unchanged. New items should never use a previously-used id. Ideally, the id is the full URL of the resource described by the item, since URLs make great unique identifiers.",
+ "type": "string"
+ },
+ "url": {
+ "description": "The URL of the resource described by the item. It’s the permalink. This may be the same as the id.",
+ "type": "string",
+ "format": "uri"
+ },
+ "external_url": {
+ "description": "The URL of a page elsewhere. This is especially useful for linkblogs. If url links to where you’re talking about a thing, then external_url links to the thing you’re talking about.",
+ "type": "string",
+ "format": "uri"
+ },
+ "title": {
+ "description": "Plain text. Microblog items in particular may omit titles.",
+ "type": "string"
+ },
+ "content_html": {
+ "description": "The HTML of the item.",
+ "type": "string"
+ },
+ "content_text": {
+ "description": "The plain text of the item.",
+ "type": "string"
+ },
+ "summary": {
+ "description": "A plain text sentence or two describing the item. This might be presented in a timeline, for instance, where a detail view would display all of content_html or content_text.",
+ "type": "string"
+ },
+ "image": {
+ "description": "The URL of the main image for the item. This image may also appear in the content_html — if so, it’s a hint to the feed reader that this is the main, featured image. Feed readers may use the image as a preview (probably resized as a thumbnail and placed in a timeline).",
+ "type": "string",
+ "format": "uri"
+ },
+ "banner_image": {
+ "description": "The URL of an image to use as a banner. Some blogging systems (such as Medium) display a different banner image chosen to go with each post, but that image wouldn’t otherwise appear in the content_html. A feed reader with a detail view may choose to show this banner image at the top of the detail view, possibly with the title overlaid.",
+ "type": "string",
+ "format": "uri"
+ },
+ "date_published": {
+ "description": "The date in RFC 3339 format.",
+ "type": "string",
+ "format": "date-time"
+ },
+ "date_modified": {
+ "description": "The modification date in RFC 3339 format.",
+ "type": "string",
+ "format": "date-time"
+ },
+ "author": {
+ "description": "The author of the item.",
+ "allOf": [
+ {
+ "$ref": "#/definitions/author"
+ }
+ ]
+ },
+ "authors": {
+ "description": "The authors of the item.",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/author"
+ }
+ },
+ "tags": {
+ "description": "Can have any plain text values you want. Tags tend to be just one word, but they may be anything. Note: they are not the equivalent of Twitter hashtags. Some blogging systems and other feed formats call these categories.",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "language": {
+ "description": "The language for this item, using the format specified in RFC 5646. The value can be different than the primary language for the feed when a specific item is written in a different language than other items in the feed.",
+ "type": "string"
+ },
+ "attachments": {
+ "description": "Lists related resources. Podcasts, for instance, would include an attachment that’s an audio or video file.",
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "description": "The location of the attachment.",
+ "type": "string",
+ "format": "uri"
+ },
+ "mime_type": {
+ "description": "The type of the attachment, such as “audio/mpeg.”",
+ "type": "string"
+ },
+ "title": {
+ "description": "A name for the attachment. Important: if there are multiple attachments, and two or more have the exact same title (when title is present), then they are considered as alternate representations of the same thing. In this way a podcaster, for instance, might provide an audio recording in different formats.",
+ "type": "string"
+ },
+ "size_in_bytes": {
+ "description": "How large the file is.",
+ "type": "number"
+ },
+ "duration_in_seconds": {
+ "description": "How long it takes to listen to or watch, when played at normal speed.",
+ "type": "number"
+ }
+ },
+ "patternProperties": {
+ "^_[a-zA-Z][^.]*$": {
+ "$ref": "#/definitions/extension"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "url",
+ "mime_type"
+ ]
+ }
+ }
+ },
+ "patternProperties": {
+ "^_[a-zA-Z][^.]*$": {
+ "$ref": "#/definitions/extension"
+ }
+ },
+ "additionalProperties": false,
+ "anyOf": [
+ {
+ "required": [
+ "content_html"
+ ]
+ },
+ {
+ "required": [
+ "content_text"
+ ]
+ }
+ ],
+ "required": [
+ "id"
+ ]
+ }
+ }
+ },
+ "patternProperties": {
+ "^_[a-zA-Z][^.]*$": {
+ "$ref": "#/definitions/extension"
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "version",
+ "title",
+ "items"
+ ],
+ "definitions": {
+ "author": {
+ "title": "Author",
+ "type": "object",
+ "properties": {
+ "name": {
+ "description": "The author’s name.",
+ "type": "string"
+ },
+ "url": {
+ "description": "The URL of a site owned by the author. It could be a blog, micro-blog, Twitter account, and so on. Ideally the linked-to page provides a way to contact the author, but that’s not required. The URL could be a mailto: link.",
+ "type": "string",
+ "format": "uri"
+ },
+ "avatar": {
+ "description": "The URL for an image for the author. It should be square and relatively large — such as 512 x 512 pixels — and should use transparency where appropriate, since it may be rendered on a non-white background.",
+ "type": "string",
+ "format": "uri"
+ }
+ },
+ "minProperties": 1,
+ "patternProperties": {
+ "^_[a-zA-Z][^.]*$": {
+ "$ref": "#/definitions/extension"
+ }
+ },
+ "additionalProperties": false
+ },
+ "extension": {
+ "title": "Extension",
+ "type": "object",
+ "patternProperties": {
+ "^[^.]*$": {}
+ },
+ "additionalProperties": false
+ }
+ }
+}
diff --git a/assets/schemas/rss-v2.0.rng b/assets/schemas/rss-v2.0.rng
new file mode 100644
index 0000000..31708ca
--- /dev/null
+++ b/assets/schemas/rss-v2.0.rng
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar
+ xmlns:atom="http://www.w3.org/2005/Atom"
+ xmlns="http://relaxng.org/ns/structure/1.0"
+ ns=""
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
+ >
+ <start>
+ <element name="rss">
+ <attribute name="version">
+ <data type="decimal"/>
+ </attribute>
+ <element name="channel">
+ <ref name="title"/>
+ <ref name="link"/>
+ <ref name="description"/>
+ <element name="language">
+ <data type="NCName"/>
+ </element>
+ <element name="category">
+ <data type="NCName"/>
+ </element>
+ <element name="generator">
+ <text/>
+ </element>
+ <element name="lastBuildDate">
+ <text/>
+ </element>
+ <element name="image">
+ <ref name="title"/>
+ <element name="url">
+ <text/>
+ </element>
+ <ref name="link"/>
+ </element>
+ <oneOrMore>
+ <element name="atom:link">
+ <attribute name="href"/>
+ <attribute name="rel">
+ <data type="NCName"/>
+ </attribute>
+ <optional>
+ <attribute name="type"/>
+ </optional>
+ </element>
+ </oneOrMore>
+ <oneOrMore>
+ <element name="item">
+ <ref name="title"/>
+ <ref name="link"/>
+ <element name="pubDate">
+ <text/>
+ </element>
+ <element name="guid">
+ <text/>
+ </element>
+ <ref name="description"/>
+ <element name="atom:author">
+ <element name="atom:name">
+ <text/>
+ </element>
+ <element name="atom:uri">
+ <text/>
+ </element>
+ </element>
+ </element>
+ </oneOrMore>
+ </element>
+ </element>
+ </start>
+ <define name="title">
+ <element name="title">
+ <text/>
+ </element>
+ </define>
+ <define name="link">
+ <element name="link">
+ <text/>
+ </element>
+ </define>
+ <define name="description">
+ <element name="description">
+ <text/>
+ </element>
+ </define>
+</grammar>
diff --git a/assets/schemas/rss-v2.0.xsd b/assets/schemas/rss-v2.0.xsd
new file mode 100644
index 0000000..37068ae
--- /dev/null
+++ b/assets/schemas/rss-v2.0.xsd
@@ -0,0 +1,383 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:element name="rss" type="rss"/>
+ <xsd:complexType name="rss">
+ <xsd:sequence>
+ <xsd:element name="channel" type="channel" maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="version"/>
+ </xsd:complexType>
+ <xsd:simpleType name="version">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="2.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:complexType name="channel">
+ <xsd:sequence>
+ <xsd:element name="title" type="xsd:string" maxOccurs="1" minOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ The name of the channel. It's how people refer
+ to your service. If you have an HTML website
+ that contains the same information as your RSS
+ file, the title of your channel should be the
+ same as the title of your website.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="link" type="xsd:string" maxOccurs="1" minOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ The URL to the HTML website corresponding to the
+ channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="description" type="xsd:string" maxOccurs="1" minOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation>
+ Phrase or sentence describing the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="language" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The language the channel is written in. This
+ allows aggregators to group all Italian language
+ sites, for example, on a single page. A list of
+ allowable values for this element, as provided
+ by Netscape, is here
+ [http://www.rssboard.org/rss-language-codes].
+ You may also use values defined by the W3C
+ [http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes].
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="copyright" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Copyright notice for content in the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="managingEditor" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Email address for person responsible for
+ editorial content.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="webMaster" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Email address for person responsible for
+ technical issues relating to channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="pubDate" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The publication date for the content in the
+ channel. For example, the New York Times
+ publishes on a daily basis, the publication date
+ flips once every 24 hours. That's when the
+ pubDate of the channel changes. All date-times
+ in RSS conform to the Date and Time
+ Specification of RFC 822, with the exception
+ that the year may be expressed with two
+ characters or four characters (four preferred).
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="category" type="category" maxOccurs="unbounded" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Specify one or more categories that the channel
+ belongs to. Follows the same rules as the
+ &lt;item&gt;-level category element.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="generator" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ A string indicating the program used to generate
+ the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="lastBuildDate" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The last time the content of the channel
+ changed.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="docs" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ A URL that points to the documentation for the
+ format used in the RSS file. It's probably a
+ pointer to this page. It's for people who might
+ stumble across an RSS file on a Web server 25
+ years from now and wonder what it is.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="cloud" type="cloud" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Allows processes to register with a cloud to be
+ notified of updates to the channel, implementing
+ a lightweight publish-subscribe protocol for RSS
+ feeds. More info here.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="ttl" type="xsd:int" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ ttl stands for time to live. It's a number of
+ minutes that indicates how long a channel can be
+ cached before refreshing from the source.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="image" type="image" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Specifies a GIF, JPEG or PNG image that can be
+ displayed with the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="rating" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The PICS [http://www.w3.org/PICS/] rating for
+ the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="textInput" type="textInput" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Specifies a text input box that can be displayed
+ with the channel.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="skipHours" type="skipHours" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ A hint for aggregators telling them which hours
+ they can skip. This element contains up to 24
+ &lt;hour&gt; sub-elements whose value is a
+ number between 0 and 23, representing a time in
+ GMT, when aggregators, if they support the
+ feature, may not read the channel on hours
+ listed in the &lt;skipHours&gt; element. The
+ hour beginning at midnight is hour zero.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="skipDays" type="skipDays" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ A hint for aggregators telling them which days
+ they can skip. This element contains up to seven
+ &lt;day&gt;
+ sub-elements whose value is Monday, Tuesday,
+ Wednesday, Thursday, Friday, Saturday or
+ Sunday. Aggregators may not read the channel
+ during days listed in the
+ &lt;skipDays&gt;element.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="item" type="item" maxOccurs="unbounded" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="cloud">
+ <xsd:attribute name="domain" type="xsd:string"/>
+ <xsd:attribute name="port">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int">
+ <xsd:maxInclusive value="65536"/>
+ <xsd:minInclusive value="0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="path" type="xsd:string"/>
+ <xsd:attribute name="registerProcedure" type="xsd:string"/>
+ <xsd:attribute name="protocol" type="xsd:string"/>
+ </xsd:complexType>
+ <xsd:complexType name="image">
+ <xsd:sequence>
+ <xsd:element name="title" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ <xsd:element name="url" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ <xsd:element name="link" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+ <xsd:element name="width" default="88" maxOccurs="1" minOccurs="0">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int">
+ <xsd:minExclusive value="0"/>
+ <xsd:maxInclusive value="144"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="height" default="31" maxOccurs="1" minOccurs="0">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int">
+ <xsd:minExclusive value="0"/>
+ <xsd:maxInclusive value="400"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="description" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="textInput">
+ <xsd:sequence>
+ <xsd:element name="title" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ <xsd:element name="description" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ <xsd:element name="name" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ <xsd:element name="link" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="skipHours">
+ <xsd:sequence>
+ <xsd:element name="hour" minOccurs="1" maxOccurs="24">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int">
+ <xsd:maxInclusive value="23"/>
+ <xsd:minInclusive value="0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="skipDays">
+ <xsd:sequence>
+ <xsd:element name="day" maxOccurs="7">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="Monday"/>
+ <xsd:enumeration value="Tuesday"/>
+ <xsd:enumeration value="Wednesday"/>
+ <xsd:enumeration value="Thursday"/>
+ <xsd:enumeration value="Friday"/>
+ <xsd:enumeration value="Saturday"/>
+ <xsd:enumeration value="Sunday"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="item">
+ <xsd:sequence>
+ <xsd:element name="title" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The title of the item.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="link" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>The URL of the item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="description" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>The item synopsis.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="author" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Email address of the author of the item.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="category" type="category" maxOccurs="unbounded" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Includes the item in one or more categories.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="comments" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ URL of a page for comments relating to the item.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="enclosure" type="enclosure" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Describes a media object that is attached to the
+ item.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="guid" type="guid" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ A string that uniquely identifies the item.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="pubDate" type="xsd:string" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates when the item was published.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="source" type="source" maxOccurs="1" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation>
+ The RSS channel that the item came from.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:complexType name="category">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="domain" type="xsd:string"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="enclosure">
+ <xsd:attribute name="url" type="xsd:string" use="required"/>
+ <xsd:attribute name="length" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:int">
+ <xsd:minExclusive value="0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="type" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ <xsd:complexType name="guid">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="isPermaLink" type="xsd:boolean"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ <xsd:complexType name="source">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="url" type="xsd:string" use="required"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+</xsd:schema>
diff --git a/assets/schemas/sitemap-v0.9.xsd b/assets/schemas/sitemap-v0.9.xsd
new file mode 100644
index 0000000..2dd7437
--- /dev/null
+++ b/assets/schemas/sitemap-v0.9.xsd
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
+ targetNamespace="http://www.sitemaps.org/schemas/sitemap/0.9"
+ elementFormDefault="qualified"
+ >
+ <xsd:annotation>
+ <xsd:documentation>
+ XML Schema for Sitemap files.
+ Last Modifed 2008-03-26
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:element name="urlset">
+ <xsd:annotation>
+ <xsd:documentation>
+ Container for a set of up to 50,000 document elements.
+ This is the root element of the XML file.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
+ <xsd:element name="url" type="tUrl" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="tUrl">
+ <xsd:annotation>
+ <xsd:documentation>
+ Container for the data needed to describe a document to crawl.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="loc" type="tLoc"/>
+ <xsd:element name="lastmod" type="tLastmod" minOccurs="0"/>
+ <xsd:element name="changefreq" type="tChangeFreq" minOccurs="0"/>
+ <xsd:element name="priority" type="tPriority" minOccurs="0"/>
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:simpleType name="tLoc">
+ <xsd:annotation>
+ <xsd:documentation>
+ REQUIRED: The location URI of a document.
+ The URI must conform to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt).
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:anyURI">
+ <xsd:minLength value="12"/>
+ <xsd:maxLength value="2048"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="tLastmod">
+ <xsd:annotation>
+ <xsd:documentation>
+ OPTIONAL: The date the document was last modified. The date must conform
+ to the W3C DATETIME format (http://www.w3.org/TR/NOTE-datetime).
+ Example: 2005-05-10
+ Lastmod may also contain a timestamp.
+ Example: 2005-05-10T17:33:30+08:00
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:union>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:date"/>
+ </xsd:simpleType>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:dateTime"/>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ <xsd:simpleType name="tChangeFreq">
+ <xsd:annotation>
+ <xsd:documentation>
+ OPTIONAL: Indicates how frequently the content at a particular URL is
+ likely to change. The value "always" should be used to describe
+ documents that change each time they are accessed. The value "never"
+ should be used to describe archived URLs. Please note that web
+ crawlers may not necessarily crawl pages marked "always" more often.
+ Consider this element as a friendly suggestion and not a command.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="always"/>
+ <xsd:enumeration value="hourly"/>
+ <xsd:enumeration value="daily"/>
+ <xsd:enumeration value="weekly"/>
+ <xsd:enumeration value="monthly"/>
+ <xsd:enumeration value="yearly"/>
+ <xsd:enumeration value="never"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="tPriority">
+ <xsd:annotation>
+ <xsd:documentation>
+ OPTIONAL: The priority of a particular URL relative to other pages
+ on the same site. The value for this element is a number between
+ 0.0 and 1.0 where 0.0 identifies the lowest priority page(s).
+ The default priority of a page is 0.5. Priority is used to select
+ between pages on your site. Setting a priority of 1.0 for all URLs
+ will not help you, as the relative priority of pages on your site
+ is what will be considered.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:decimal">
+ <xsd:minInclusive value="0.0"/>
+ <xsd:maxInclusive value="1.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/assets/schemas/sitemapindex-v0.9.xsd b/assets/schemas/sitemapindex-v0.9.xsd
new file mode 100644
index 0000000..c35d50a
--- /dev/null
+++ b/assets/schemas/sitemapindex-v0.9.xsd
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
+ targetNamespace="http://www.sitemaps.org/schemas/sitemap/0.9"
+ elementFormDefault="qualified"
+ >
+ <xsd:annotation>
+ <xsd:documentation>
+ XML Schema for Sitemap index files.
+ Last Modifed 2009-04-08
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:element name="sitemapindex">
+ <xsd:annotation>
+ <xsd:documentation>
+ Container for a set of up to 50,000 sitemap URLs.
+ This is the root element of the XML file.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
+ <xsd:element name="sitemap" type="tSitemap" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:complexType name="tSitemap">
+ <xsd:annotation>
+ <xsd:documentation>
+ Container for the data needed to describe a sitemap.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="loc" type="tLocSitemap"/>
+ <xsd:element name="lastmod" type="tLastmodSitemap" minOccurs="0"/>
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ <xsd:simpleType name="tLocSitemap">
+ <xsd:annotation>
+ <xsd:documentation>
+ REQUIRED: The location URI of a sitemap.
+ The URI must conform to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt).
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:anyURI">
+ <xsd:minLength value="12"/>
+ <xsd:maxLength value="2048"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="tLastmodSitemap">
+ <xsd:annotation>
+ <xsd:documentation>
+ OPTIONAL: The date the document was last modified. The date must conform
+ to the W3C DATETIME format (http://www.w3.org/TR/NOTE-datetime).
+ Example: 2005-05-10
+ Lastmod may also contain a timestamp.
+ Example: 2005-05-10T17:33:30+08:00
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:union>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:date"/>
+ </xsd:simpleType>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:dateTime"/>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+</xsd:schema>
diff --git a/assets/templates/author.yaml b/assets/templates/author.yaml
index 0a0f458..ae7bf40 100644
--- a/assets/templates/author.yaml
+++ b/assets/templates/author.yaml
@@ -1,16 +1,23 @@
---
name: {{ .Name }}
user: {{ .User }}
-blogtitle: {{ .Name }}'s Micro Blog
+title: {{ .Name }}'s Micro Blog
wordlimit: 50
place: Nowhere
domain:
host: example.com
url: https://example.com
+# Accepts file path or URL
+# header: /media/header.jpg
+# picture: https://example.com/media/picture.jpg
+picture:
+ header:
+ profile:
epoch: Just now
description: >
- I am a nobody. Copy this [example configuration](/data/generates/authors/{{ .User }}.yaml)
- to `data/{{ .User }}.yaml` and make me a somebody.
-webring:
+ I am a nobody. Copy this [example
+ configuration](/data/generates/authors/{{ .User }}.yaml) to
+ `data/{{ .User }}.yaml` and make me a [somebody](/data/default.yaml).
+feeds:
rss:
json:
diff --git a/assets/templates/markdown-feed.yaml b/assets/templates/markdown-feed.yaml
index 33118da..ff0aae5 100644
--- a/assets/templates/markdown-feed.yaml
+++ b/assets/templates/markdown-feed.yaml
@@ -21,12 +21,19 @@ feed:
{{ end -}}
---
-{{ $content := .content | replaceRE "{" "&#123;" | replaceRE "}" "&#125;" -}}
-{{ $content }} [Read More &rarr;]({{ .link }})
+{{ $content := .content }}
+
+{{- $content = replace $content "{" "&#123;" -}}
+{{- $content = replace $content "}" "&#125;" -}}
+{{- $content = replace $content "[" "&#91;" -}}
+{{- $content = replace $content "]" "&#93;" -}}
+
+{{ $content }}
+
+{{- $caption := "Image/Picture" -}}
-{{- $enclosureDescription := "Image/Picture" -}}
{{- with $content -}}
- {{ $enclosureDescription = $content | truncate 80 "" }}
+ {{ $caption = $content | truncate 80 "" }}
{{- end }}
{{ with .enclosure -}}
@@ -43,8 +50,8 @@ feed:
(in . ".svg")
(in . ".webp")
-}}
-![{{ $enclosureDescription }}]({{ . }} "
- {{ $enclosureDescription }}"
+![{{ $caption }}]({{ . }} "
+ {{ $caption }}"
)
{{- end -}}
{{- end }}