diff --git a/css/style.css b/css/style.css index b16d24f..81ee75d 100644 --- a/css/style.css +++ b/css/style.css @@ -1,5 +1,134 @@ + :root { + /* size variables */ + /* more pronounced, perfect fifth on narrow screens */ + /* @link https://utopia.fyi/type/calculator?c=360,16,1.5,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */ + + --step--2: clamp(0.4444rem, 0.299rem + 0.6465vw, 0.8rem); + --step--1: clamp(0.6667rem, 0.5303rem + 0.6061vw, 1rem); + --step-0: clamp(1rem, 0.8977rem + 0.4545vw, 1.25rem); + --step-1: clamp(1.5rem, 1.4744rem + 0.1136vw, 1.5625rem); + --step-2: clamp(1.9531rem, 2.3714rem + -0.5398vw, 2.25rem); + --step-3: clamp(2.4414rem, 3.7569rem + -1.6974vw, 3.375rem); + --step-4: clamp(3.0518rem, 5.8851rem + -3.6559vw, 5.0625rem); + --step-5: clamp(3.8147rem, 9.1397rem + -6.871vw, 7.5938rem); + + /* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */ + + --space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem); + --space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem); + --space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem); + --space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem); + --space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem); + --space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem); + --space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem); + --space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem); + --space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem); + + /* One-up pairs */ + --space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem); + --space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem); + --space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem); + --space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem); + --space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem); + --space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem); + --space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem); + --space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem); + + /* Custom pairs */ + --space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem); + + + /*COLORS*/ + --blue: #d7f0e1; + --darkblue: #2c6a88; + --oc-gray-3: #dee2e6; + --oc-gray-5: #adb5bd; + --oc-gray-6: #868e96; + --oc-gray-7: #495057; + --oc-gray-8: #343a40; + --oc-cyan-6: #15aabf; + --oc-cyan-9: #0b7285; + --oc-blue-1: #d0ebff; + --oc-blue-3: #74c0fc; + --oc-blue-4: #4dabf7; + --oc-blue-7: #1c7ed6; + --oc-blue-9: #1864ab; + --oc-grape-9: #862e9c; + --oc-violet-4: #9775fa; + --oc-violet-9: #5f3dc4; + + } body { font-family: "sans-serif"; margin: 0 auto; max-width: 66ch; } +@layer translations { + body > trl-selector:first-child {display: none;} /* was adding a grid row! */ + trl-selector { + display: flex; + flex-direction: row; + gap: var(--space-3xs); + flex-wrap: wrap; + justify-content: end; + justify-self: end; + align-items: start; + padding-inline: var(--space-3xs); + margin-inline-end: var(--space-3xs); + grid-column: grid-start/content-start; + align-self: start; + margin-top: var(--space-l); + background-color: var(--oc-blue-1); + max-width: max-content; + border-radius: 3px; + + label { + cursor: pointer; + } + input { + display: none; + } + /* assumes labels follow their inputs immediately */ + input:checked + label { + font-weight: bold; + } + + } + /* Do we use trl-selector ~ or [trl] descendants? */ + /* need one of these rules for each language.*/ + trl-selector:has(> input[value="nl"]:checked) { + & ~ trl-alt:lang('nl') { + display: block; + } + & ~ trl-alt:not(:lang('nl')) { + display: none; + } + } + trl-selector:has( > input[value="en"]:checked) { + & ~ trl-alt:lang('en') { + display: block; + } + & ~ trl-alt:not(:lang('en')) { + display: none; + } + } + + body:has(> trl-selector input[value="nl"]:checked) { + & [trl-ui]:lang('nl') { + display: block; + } + & [trl-ui]:not(:lang('nl')) { + display: none; + } + + } + body:has(> trl-selector input[value="en"]:checked) { + & [trl-ui]:lang('en') { + display: block; + } + & [trl-ui]:not(:lang('en')) { + display: none; + } + + } +} diff --git a/pagesInFoldersWithTranslations.js b/pagesInFoldersWithTranslations.js index ac07a8b..d29a939 100644 --- a/pagesInFoldersWithTranslations.js +++ b/pagesInFoldersWithTranslations.js @@ -1,24 +1,38 @@ -import {fromHtml} from 'hast-util-from-html'; -import {toHtml} from 'hast-util-to-html'; -import {visit} from 'unist-util-visit'; +import {JSDOM} from 'jsdom'; /* * The idea: need to create another subdir `title/nl/index.html` */ +/* + * addTranslationInterface adds the with radio buttons and labels to each . + * It sets the checked property on the indicated language. + */ + +/* + * first, index.html is the original page, with the page language (from markdown frontmatter) active. + * This allows switching between languages for each translated fragment in the page. + * then, for each language in the frontmatter `trls`, another folder-with-index.html is generated, + * with added, + * where the language corresponding to the given language is active. + * + * So note that page `trls: []` is independent of the languages of the ``s in each ``. + */ export default async (page) => { const html = await page.html; return { - "index.html": page.html, + "index.html": addTranslationInterface(html, page?.lang), ...handleTranslations(html, page.trls) } } +//this is going to create a folder for each 'translation' specified in frontmatter. function handleTranslations(html, trls) { if (trls) { + console.log(trls); const outputs = {}; trls.forEach(trl => { outputs[trl] = { - "index.html": reorderTranslations(html, trl) + "index.html": addTranslationInterface(html, trl) } }) return outputs; @@ -27,11 +41,43 @@ function handleTranslations(html, trls) { } } -//reorders all '.translation-group's so the element with given lang is first, and 'open' is set appropriately. -//also, handles latest/laatst. Is that a special case, or should that be translated in the page too? -function reorderTranslations(body, lang){ - //handles both text and dom object as input - const hast = fromHtml(body); - //visit: trlselector>radio, and set active on current lang and inactive on other langs. - return toHtml(hast); +//"reorders" all `trl-group`s so the element with given lang is displayed. +//EN is default language ... +//also adds a (hidden by css) trl-selector at the top of `body`. +//TODO: add a link to translated pages ... +//that's complicated, because what about all the links in the page? +function addTranslationInterface(body, activelang="en"){ + const dom = new JSDOM(body); + const doc = dom.window.document; + let seq = 1; //serial number for identifying translation group inputs and labels + const trlGroups = Array.from(doc.querySelectorAll('trl-group')); + trlGroups.forEach((trlGroup) => { + //for each trlGroup. + const trlAltElems = Array.from(trlGroup.querySelectorAll('trl-alt')); + const langsInGroup = trlAltElems.map(t => t.getAttribute('lang')); + const trlSel = doc.createElement('trl-selector'); + langsInGroup.forEach(lang => { + console.log(lang); + let grname = `trlg-${seq}`; + let inputId = `${grname}-${lang}`; + const input = doc.createElement('input'); + input.type = 'radio'; + input.setAttribute('id', inputId); + input.setAttribute('name', grname); + input.setAttribute('lang', lang); + input.setAttribute('value', lang); + if (lang === activelang) { + input.setAttribute('checked', ''); + } + const label = doc.createElement('label'); + label.setAttribute('for', inputId); + label.textContent = lang; + trlSel.append(input); + trlSel.append(label); + + }) + trlGroup.prepend(trlSel); + seq ++; //increment id serial number + }) + return dom.serialize(); } diff --git a/pipeline.ori b/pipeline.ori index be25533..04bb98c 100644 --- a/pipeline.ori +++ b/pipeline.ori @@ -64,14 +64,9 @@ Then, we can use that html and the trls property to add the translations. */ + //NOTE! two steps at once. Could separate the withTranslations part: add a html_LANG property to the document object, then later create the folder structure. pagesInFolders: Tree.map(renderedPages, pagesInFoldersWithTranslations.js) - /* - pagesInFolders: Tree.map(renderedPages, { - value: (value) => { - index.html: value - } - }) - */ + //bug in 0.6.14? linksByFile: Tree.map(renderedPages,getLinkedFilesFromHtml.js)