mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-07-01 12:22:15 +02:00
🔤 ⚡ Docs UI/UX
This commit is contained in:
@ -1,28 +1,174 @@
|
||||
import { registerClientFile, styles } from "../ssr.js";
|
||||
const host= "."+code.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
--shiki-color-text: #e9eded;
|
||||
--shiki-color-background: #212121;
|
||||
/* Code block styling */
|
||||
${host} {
|
||||
/* Theme for dark mode - matches Flems/CodeMirror dark theme */
|
||||
--shiki-color-text: #f8f8f2;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #82b1ff;
|
||||
--shiki-token-string: #c3e88d;
|
||||
--shiki-token-comment: #546e7a;
|
||||
--shiki-token-keyword: #c792ea;
|
||||
--shiki-token-parameter: #AA0000;
|
||||
--shiki-token-parameter: #fd971f;
|
||||
--shiki-token-function: #80cbae;
|
||||
--shiki-token-string-expression: #c3e88d;
|
||||
--shiki-token-punctuation: var(--code);
|
||||
--shiki-token-link: #EE0000;
|
||||
--shiki-token-punctuation: #89ddff;
|
||||
--shiki-token-link: #82aaff;
|
||||
--shiki-token-variable: #f8f8f2;
|
||||
--shiki-token-number: #f78c6c;
|
||||
--shiki-token-boolean: #82b1ff;
|
||||
--shiki-token-tag: #f07178;
|
||||
--shiki-token-attribute: #ffcb6b;
|
||||
--shiki-token-property: #82b1ff;
|
||||
--shiki-token-operator: #89ddff;
|
||||
--shiki-token-regex: #c3e88d;
|
||||
--shiki-token-class: #ffcb6b;
|
||||
|
||||
/* Basic styling */
|
||||
white-space: pre;
|
||||
tab-size: 2; /* TODO: allow custom tab size?! */
|
||||
overflow: scroll;
|
||||
tab-size: 2;
|
||||
overflow: auto;
|
||||
border-radius: var(--border-radius);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
position: relative;
|
||||
}
|
||||
${host}[data-js=todo]{
|
||||
|
||||
/* Light mode overrides to match GitHub-like theme */
|
||||
@media (prefers-color-scheme: light) {
|
||||
${host} {
|
||||
--shiki-color-text: #24292e;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #005cc5;
|
||||
--shiki-token-string: #22863a;
|
||||
--shiki-token-comment: #6a737d;
|
||||
--shiki-token-keyword: #d73a49;
|
||||
--shiki-token-parameter: #e36209;
|
||||
--shiki-token-function: #6f42c1;
|
||||
--shiki-token-string-expression: #22863a;
|
||||
--shiki-token-punctuation: #24292e;
|
||||
--shiki-token-link: #0366d6;
|
||||
--shiki-token-variable: #24292e;
|
||||
--shiki-token-number: #005cc5;
|
||||
--shiki-token-boolean: #005cc5;
|
||||
--shiki-token-tag: #22863a;
|
||||
--shiki-token-attribute: #005cc5;
|
||||
--shiki-token-property: #005cc5;
|
||||
--shiki-token-operator: #d73a49;
|
||||
--shiki-token-regex: #032f62;
|
||||
--shiki-token-class: #6f42c1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Support for theme toggles */
|
||||
html[data-theme="light"] ${host} {
|
||||
--shiki-color-text: #24292e;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #005cc5;
|
||||
--shiki-token-string: #22863a;
|
||||
--shiki-token-comment: #6a737d;
|
||||
--shiki-token-keyword: #d73a49;
|
||||
--shiki-token-parameter: #e36209;
|
||||
--shiki-token-function: #6f42c1;
|
||||
--shiki-token-string-expression: #22863a;
|
||||
--shiki-token-punctuation: #24292e;
|
||||
--shiki-token-link: #0366d6;
|
||||
--shiki-token-variable: #24292e;
|
||||
--shiki-token-number: #005cc5;
|
||||
--shiki-token-boolean: #005cc5;
|
||||
--shiki-token-tag: #22863a;
|
||||
--shiki-token-attribute: #005cc5;
|
||||
--shiki-token-property: #005cc5;
|
||||
--shiki-token-operator: #d73a49;
|
||||
--shiki-token-regex: #032f62;
|
||||
--shiki-token-class: #6f42c1;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] ${host} {
|
||||
--shiki-color-text: #f8f8f2;
|
||||
--shiki-color-background: var(--code-bg);
|
||||
--shiki-token-constant: #82b1ff;
|
||||
--shiki-token-string: #c3e88d;
|
||||
--shiki-token-comment: #546e7a;
|
||||
--shiki-token-keyword: #c792ea;
|
||||
--shiki-token-parameter: #fd971f;
|
||||
--shiki-token-function: #80cbae;
|
||||
--shiki-token-string-expression: #c3e88d;
|
||||
--shiki-token-punctuation: #89ddff;
|
||||
--shiki-token-link: #82aaff;
|
||||
--shiki-token-variable: #f8f8f2;
|
||||
--shiki-token-number: #f78c6c;
|
||||
--shiki-token-boolean: #82b1ff;
|
||||
--shiki-token-tag: #f07178;
|
||||
--shiki-token-attribute: #ffcb6b;
|
||||
--shiki-token-property: #82b1ff;
|
||||
--shiki-token-operator: #89ddff;
|
||||
--shiki-token-regex: #c3e88d;
|
||||
--shiki-token-class: #ffcb6b;
|
||||
}
|
||||
|
||||
/* Code block with syntax highlighting waiting for JS */
|
||||
${host}[data-js=todo] {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--standard-border-radius);
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 18.4px; /* to fix shift when → dataJS=done */
|
||||
padding: 1rem 1.4rem;
|
||||
border-radius: var(--border-radius);
|
||||
margin-bottom: 1.5rem;
|
||||
margin-top: 1rem;
|
||||
padding: 1rem;
|
||||
background-color: var(--code-bg);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Add a subtle loading indicator */
|
||||
${host}[data-js=todo]::before {
|
||||
content: "Loading syntax highlighting...";
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-light);
|
||||
background-color: var(--bg);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: var(--border-radius);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* All code blocks should have consistent font and sizing */
|
||||
${host} code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* Ensure line numbers (if added) are styled appropriately */
|
||||
${host} .line-number {
|
||||
user-select: none;
|
||||
opacity: 0.5;
|
||||
margin-right: 1rem;
|
||||
min-width: 1.5rem;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* If there's a copy button, style it */
|
||||
${host} .copy-button {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
background-color: var(--bg);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
${host}:hover .copy-button {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
import { el } from "deka-dom-el";
|
||||
@ -52,12 +198,46 @@ let is_registered= {};
|
||||
function registerClientPart(page_id){
|
||||
if(is_registered[page_id]) return;
|
||||
|
||||
// Add Shiki with a more reliable loading method
|
||||
document.head.append(
|
||||
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki@0.9", defer: true }),
|
||||
// Use a newer version of Shiki with better performance
|
||||
el("script", { src: "https://cdn.jsdelivr.net/npm/shiki@0.14.3/dist/index.unpkg.iife.js", defer: true }),
|
||||
// Make sure we can match Flems styling in dark/light mode
|
||||
el("style", `
|
||||
/* Ensure CodeMirror and Shiki use the same font */
|
||||
.CodeMirror *, .shiki * {
|
||||
font-family: var(--font-mono) !important;
|
||||
}
|
||||
|
||||
/* Style Shiki's output to match our theme */
|
||||
.shiki {
|
||||
background-color: var(--shiki-color-background) !important;
|
||||
color: var(--shiki-color-text) !important;
|
||||
padding: 1rem;
|
||||
border-radius: var(--border-radius);
|
||||
tab-size: 2;
|
||||
}
|
||||
|
||||
/* Ensure Shiki code tokens use our CSS variables */
|
||||
.shiki .keyword { color: var(--shiki-token-keyword) !important; }
|
||||
.shiki .constant { color: var(--shiki-token-constant) !important; }
|
||||
.shiki .string { color: var(--shiki-token-string) !important; }
|
||||
.shiki .comment { color: var(--shiki-token-comment) !important; }
|
||||
.shiki .function { color: var(--shiki-token-function) !important; }
|
||||
.shiki .operator, .shiki .punctuation { color: var(--shiki-token-punctuation) !important; }
|
||||
.shiki .parameter { color: var(--shiki-token-parameter) !important; }
|
||||
.shiki .variable { color: var(--shiki-token-variable) !important; }
|
||||
.shiki .property { color: var(--shiki-token-property) !important; }
|
||||
`),
|
||||
);
|
||||
|
||||
// Register our highlighting script to run after Shiki loads
|
||||
const scriptElement = el("script", { type: "module" });
|
||||
|
||||
registerClientFile(
|
||||
new URL("./code.js.js", import.meta.url),
|
||||
el("script", { type: "module" })
|
||||
scriptElement
|
||||
);
|
||||
|
||||
is_registered[page_id]= true;
|
||||
}
|
||||
|
@ -1,12 +1,61 @@
|
||||
const highlighter= await globalThis.shiki.getHighlighter({
|
||||
theme: "css-variables",
|
||||
langs: ["js", "ts", "css", "html", "shell"],
|
||||
});
|
||||
const codeBlocks= document.querySelectorAll('code[class*="language-"]');
|
||||
try {
|
||||
// Initialize Shiki with our custom theme
|
||||
const highlighter = await globalThis.shiki.getHighlighter({
|
||||
theme: "css-variables",
|
||||
langs: ["javascript", "typescript", "css", "html", "shell"],
|
||||
});
|
||||
|
||||
codeBlocks.forEach((block)=> {
|
||||
const lang= block.className.replace("language-", "");
|
||||
block.parentElement.dataset.js= "done";
|
||||
const html= highlighter.codeToHtml(block.textContent, { lang });
|
||||
block.innerHTML= html;
|
||||
});
|
||||
// Find all code blocks that need highlighting
|
||||
const codeBlocks = document.querySelectorAll('div[data-js="todo"] code[class*="language-"]');
|
||||
|
||||
// Process each code block
|
||||
codeBlocks.forEach((block) => {
|
||||
try {
|
||||
// Get the language from the class
|
||||
const langClass = block.className.match(/language-(\w+)/);
|
||||
|
||||
// Map the language to Shiki format
|
||||
let lang = langClass ? langClass[1] : 'javascript';
|
||||
if (lang === 'js') lang = 'javascript';
|
||||
if (lang === 'ts') lang = 'typescript';
|
||||
|
||||
// Mark the container as processed
|
||||
block.parentElement.dataset.js = "done";
|
||||
|
||||
// Highlight the code
|
||||
const code = block.textContent;
|
||||
const html = highlighter.codeToHtml(code, { lang });
|
||||
|
||||
// Insert the highlighted HTML
|
||||
block.innerHTML = html;
|
||||
|
||||
// Add copy button functionality
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.className = 'copy-button';
|
||||
copyBtn.textContent = 'Copy';
|
||||
copyBtn.setAttribute('aria-label', 'Copy code to clipboard');
|
||||
copyBtn.addEventListener('click', () => {
|
||||
navigator.clipboard.writeText(code).then(() => {
|
||||
copyBtn.textContent = 'Copied!';
|
||||
setTimeout(() => {
|
||||
copyBtn.textContent = 'Copy';
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
// Add the copy button to the code block container
|
||||
block.parentElement.appendChild(copyBtn);
|
||||
} catch (err) {
|
||||
console.error('Error highlighting code block:', err);
|
||||
// Make sure we don't leave the block in a pending state
|
||||
block.parentElement.dataset.js = "error";
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to initialize Shiki:', err);
|
||||
|
||||
// Fallback: at least mark blocks as processed so they don't show loading indicator
|
||||
document.querySelectorAll('div[data-js="todo"]').forEach(block => {
|
||||
block.dataset.js = "error";
|
||||
});
|
||||
}
|
||||
|
@ -1,16 +1,103 @@
|
||||
import { styles } from "../ssr.js";
|
||||
const host= "."+example.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
${host} {
|
||||
grid-column: full-main;
|
||||
width: 100%;
|
||||
max-width: calc(9/5 * var(--body-max-width));
|
||||
height: calc(3/5 * var(--body-max-width));
|
||||
margin-inline: auto;
|
||||
margin: 2rem auto;
|
||||
border-radius: var(--border-radius);
|
||||
box-shadow: var(--shadow);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
${host} .runtime {
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
/* CodeMirror styling to match our theme */
|
||||
.CodeMirror {
|
||||
height: 100% !important;
|
||||
font-family: var(--font-mono) !important;
|
||||
font-size: 0.95rem !important;
|
||||
line-height: 1.5 !important;
|
||||
}
|
||||
|
||||
/* Dark mode styles for CodeMirror */
|
||||
.CodeMirror, .CodeMirror-gutters {
|
||||
background: #212121 !important;
|
||||
border: 1px solid white;
|
||||
background: var(--code-bg) !important;
|
||||
border: 1px solid var(--border) !important;
|
||||
color: var(--text) !important;
|
||||
}
|
||||
|
||||
/* Light mode adjustments for CodeMirror - using CSS variables */
|
||||
@media (prefers-color-scheme: light) {
|
||||
/* Core syntax elements */
|
||||
.cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; }
|
||||
.cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; }
|
||||
.cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; }
|
||||
.cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; }
|
||||
.cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
.cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; }
|
||||
.cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; }
|
||||
.cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; }
|
||||
.cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; }
|
||||
.cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; }
|
||||
.cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; }
|
||||
.cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; }
|
||||
.cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
.cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
.cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; }
|
||||
.cm-s-material .cm-error { color: #f44336 !important; }
|
||||
}
|
||||
|
||||
/* Handle theme toggle */
|
||||
html[data-theme="light"] .CodeMirror {
|
||||
background: #f5f7fa !important;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .CodeMirror-gutters {
|
||||
background: #f5f7fa !important;
|
||||
border-right: 1px solid #e5e7eb !important;
|
||||
}
|
||||
|
||||
/* Also apply the same styles to CodeMirror with data-theme */
|
||||
html[data-theme="light"] .cm-s-material .cm-keyword { color: var(--shiki-token-keyword, #d73a49) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-atom { color: var(--shiki-token-constant, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-number { color: var(--shiki-token-number, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-def { color: var(--shiki-token-function, #6f42c1) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable-2 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-variable-3 { color: var(--shiki-token-variable, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-property { color: var(--shiki-token-property, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-operator { color: var(--shiki-token-operator, #d73a49) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-comment { color: var(--shiki-token-comment, #6a737d) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-string { color: var(--shiki-token-string, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-string-2 { color: var(--shiki-token-string, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-tag { color: var(--shiki-token-tag, #22863a) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-attribute { color: var(--shiki-token-attribute, #005cc5) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-bracket { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-punctuation { color: var(--shiki-token-punctuation, #24292e) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-link { color: var(--shiki-token-link, #0366d6) !important; }
|
||||
html[data-theme="light"] .cm-s-material .cm-error { color: #f44336 !important; }
|
||||
|
||||
/* Mobile adjustments */
|
||||
@media (max-width: 767px) {
|
||||
${host} {
|
||||
height: 50vh;
|
||||
max-width: 100%;
|
||||
}
|
||||
${host} main {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
${host} main > * {
|
||||
width: 100%;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -1,18 +1,67 @@
|
||||
import { pages, styles } from "../ssr.js";
|
||||
const host= "."+prevNext.name;
|
||||
styles.css`
|
||||
${host}{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2fr 1fr;
|
||||
margin-top: 1rem;
|
||||
/* Previous/Next navigation */
|
||||
${host} {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 3rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
gap: 1rem;
|
||||
}
|
||||
${host} [rel=prev]{
|
||||
grid-column: 1;
|
||||
|
||||
${host} a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1.25rem;
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--primary-dark); /* Darker background for better contrast */
|
||||
color: white;
|
||||
font-weight: 600; /* Bolder text for better readability */
|
||||
text-decoration: none;
|
||||
transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
|
||||
max-width: 45%;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); /* Subtle shadow for better visibility */
|
||||
}
|
||||
${host} [rel=next]{
|
||||
grid-column: 3;
|
||||
text-align: right;
|
||||
|
||||
${host} a:hover {
|
||||
background-color: var(--primary);
|
||||
transform: translateY(-2px);
|
||||
text-decoration: none;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* Enhanced shadow on hover */
|
||||
}
|
||||
|
||||
${host} [rel=prev] {
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
${host} [rel=next] {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
${host} [rel=prev]::before {
|
||||
content: "←";
|
||||
margin-right: 0.75rem;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
${host} [rel=next]::after {
|
||||
content: "→";
|
||||
margin-left: 0.75rem;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* If there's no previous/next, ensure the spacing still works */
|
||||
${host} a:only-child {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
${host} a {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
`;
|
||||
import { el } from "../../index.js";
|
||||
@ -22,21 +71,28 @@ import { el } from "../../index.js";
|
||||
* @param {string} [attrs.id]
|
||||
* */
|
||||
export function h3({ textContent, id }){
|
||||
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
|
||||
return el("h3", { id }).append(
|
||||
el("a", { textContent: "#", href: "#"+id, tabIndex: -1 }),
|
||||
" ", textContent
|
||||
);
|
||||
if(!id) id= "h-"+textContent.toLowerCase().replaceAll(/\s/g, "-").replaceAll(/[^a-z-]/g, "");
|
||||
return el("h3", { id, className: "section-heading" }).append(
|
||||
el("a", {
|
||||
className: "heading-anchor",
|
||||
href: "#"+id,
|
||||
textContent: "#",
|
||||
title: `Link to this section: ${textContent}`,
|
||||
"aria-label": `Link to section ${textContent}`
|
||||
}),
|
||||
" ",
|
||||
textContent,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {import("../types.d.ts").Info} page
|
||||
* */
|
||||
export function prevNext(page){
|
||||
const page_index= pages.indexOf(page);
|
||||
return el("div", { className: prevNext.name }).append(
|
||||
el(pageLink, { rel: "prev", page: pages[page_index-1] }),
|
||||
el(pageLink, { rel: "next", page: pages[page_index+1] })
|
||||
);
|
||||
const page_index= pages.indexOf(page);
|
||||
return el("div", { className: prevNext.name }).append(
|
||||
el(pageLink, { rel: "prev", page: pages[page_index-1] }),
|
||||
el(pageLink, { rel: "next", page: pages[page_index+1] })
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @param {Object} attrs
|
||||
@ -44,11 +100,22 @@ export function prevNext(page){
|
||||
* @param {import("../types.d.ts").Info} [attrs.page]
|
||||
* */
|
||||
function pageLink({ rel, page }){
|
||||
if(!page) return el();
|
||||
let { href, title, description }= page;
|
||||
return el("a", { rel, href, title: description }).append(
|
||||
rel==="next" ?"(next) " : "",
|
||||
title,
|
||||
rel==="prev" ? " (previous)" : "",
|
||||
);
|
||||
if(!page) return el();
|
||||
let { href, title, description }= page;
|
||||
|
||||
// Find the page index to show numbering
|
||||
const pageIndex = pages.findIndex(p => p === page);
|
||||
const pageNumber = pageIndex + 1;
|
||||
|
||||
const linkTitle = rel === "prev"
|
||||
? `Previous: ${pageNumber}. ${title}`
|
||||
: `Next: ${pageNumber}. ${title}`;
|
||||
|
||||
return el("a", {
|
||||
rel,
|
||||
href,
|
||||
title: description || linkTitle
|
||||
}).append(
|
||||
title
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user