diff --git a/astro.config.mjs b/astro.config.mjs index eafb922..c69ac85 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,6 +3,7 @@ import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; import rehypeExternalLinks from 'rehype-external-links'; +import rehypeTableScroll from './src/lib/rehype-table-scroll.mjs'; import mdx from '@astrojs/mdx'; const SITE = 'https://stackyard.sandobserver.com'; @@ -12,6 +13,7 @@ export default defineConfig({ markdown: { rehypePlugins: [ [rehypeExternalLinks, { target: '_blank', rel: ['noopener', 'noreferrer'] }], + rehypeTableScroll, ], }, integrations: [ @@ -46,6 +48,17 @@ export default defineConfig({ { tag: 'meta', attrs: { property: 'og:site_name', content: 'Stackyard' } }, { tag: 'meta', attrs: { name: 'twitter:card', content: 'summary_large_image' } }, { tag: 'meta', attrs: { name: 'twitter:image', content: `${SITE}/img/og.jpg` } }, + { + tag: 'script', + content: + "addEventListener('DOMContentLoaded',function(){" + + "var boxes=document.querySelectorAll('.sy-tscroll');" + + "function sync(){boxes.forEach(function(b){" + + "if(b.scrollWidth>b.clientWidth+1){b.tabIndex=0;b.setAttribute('role','group');" + + "b.setAttribute('aria-label','Scrollable table');}" + + "else{b.removeAttribute('tabindex');b.removeAttribute('role');b.removeAttribute('aria-label');}});}" + + "sync();addEventListener('resize',sync);});", + }, ], expressiveCode: { diff --git a/src/lib/rehype-table-scroll.mjs b/src/lib/rehype-table-scroll.mjs new file mode 100644 index 0000000..bc547ca --- /dev/null +++ b/src/lib/rehype-table-scroll.mjs @@ -0,0 +1,28 @@ +// @ts-check + +/* Wraps every markdown table in a horizontally scrollable container, so a wide + table scrolls instead of clipping its last column on a narrow screen. */ + +const CLASS = 'sy-tscroll'; + +/** @param {any} node */ +function wrapTables(node) { + if (!node || !Array.isArray(node.children)) return; + const children = node.children; + for (const child of children) wrapTables(child); + node.children = children.map(child => + child.type === 'element' && child.tagName === 'table' + ? { + type: 'element', + tagName: 'div', + properties: { className: [CLASS] }, + children: [child], + } + : child, + ); +} + +export default function rehypeTableScroll() { + /** @param {any} tree */ + return tree => wrapTables(tree); +} diff --git a/src/pages/index.astro b/src/pages/index.astro index 7b00134..4d95fe2 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -233,11 +233,11 @@ const schema = { @@ -333,6 +333,32 @@ const schema = {