Commit d6dd2a7
Changed files (4)
src/plugins/components/tabs.mjs
@@ -0,0 +1,70 @@
+/// <reference types="mdast" />
+import { h } from 'hastscript';
+
+/**
+ * Create a Tabs component.
+ *
+ * @param {Object} props - The properties of the component.
+ * @param {import('mdast').RootContent[]} children - The children elements of the component.
+ * @returns {import('mdast').Parent} The created Tabs component.
+ */
+export function componentTabs(props, children) {
+ if (!Array.isArray(children) || children.length === 0) {
+ return h(
+ 'div',
+ { class: 'hidden' },
+ 'Invalid directive. ("tabs" directive must container type and have at least one tab.)'
+ );
+ }
+ if (children[0].tagName !== 'tab') {
+ return h(
+ 'div',
+ { class: 'hidden' },
+ 'Invalid directive. ("tabs" directive must container type with "tab" leaf directive as first child.)'
+ );
+ }
+
+ const { result: tabs } = children.reduce(
+ (acc, child, index) => {
+ if (child.tagName === 'tab') {
+ if (acc.temp.title !== '') {
+ acc.result.push(acc.temp);
+ acc.temp = { title: '', content: [] };
+ }
+ acc.temp.title =
+ child.children.length > 0 ? child.children[0].value : `Tab ${acc.result.length + 1}`;
+ if ('active' in child.properties) {
+ acc.temp.active = true;
+ }
+ return acc;
+ }
+ acc.temp.content.push(child);
+ if (index === children.length - 1) acc.result.push(acc.temp);
+
+ return acc;
+ },
+ {
+ temp: {
+ title: '',
+ active: false,
+ content: [],
+ },
+ result: [],
+ }
+ );
+
+ const tabsId = `tabs-${Math.random().toString(36).substring(2, 15)}`;
+ const tabsContent = tabs.flatMap((tab) => {
+ const tabTitle = h('input', {
+ class: 'tab',
+ type: 'radio',
+ name: tabsId,
+ 'aria-label': tab.title,
+ checked: tab.active ? 'checked' : undefined,
+ });
+ const tabContent = h('div', { class: 'tab-content p-4' }, ...tab.content);
+ return [tabTitle, tabContent];
+ });
+
+ return h('div', { class: 'tabs tabs-box bg-base-200/15 my-4' }, tabsContent);
+}
src/plugins/remark-prase-directive.mjs
@@ -0,0 +1,37 @@
+/**
+ * @import {} from 'mdast-util-directive'
+ * @import {Root} from 'mdast'
+ */
+import { h } from 'hastscript';
+import { visit } from 'unist-util-visit';
+
+export function parseDirectiveNodes() {
+ /**
+ * @param {Root} tree
+ * Tree.
+ * @returns {undefined}
+ * Nothing.
+ */
+ return (tree) => {
+ visit(tree, (node) => {
+ if (
+ node.type === 'containerDirective' ||
+ node.type === 'leafDirective' ||
+ node.type === 'textDirective'
+ ) {
+ const data = node.data || (node.data = {});
+ node.attributes = node.attributes || {};
+ if (
+ node.children.length > 0 &&
+ node.children[0].data &&
+ node.children[0].data.directiveLabel
+ ) {
+ node.attributes['has-directive-label'] = true;
+ }
+ const hast = h(node.name, node.attributes);
+ data.hName = hast.tagName;
+ data.hProperties = hast.properties;
+ }
+ });
+ };
+}
astro.config.mjs
@@ -1,7 +1,9 @@
// @ts-check
import { CDN } from './src/constants/cdn.mjs';
+import { componentTabs } from './src/plugins/components/tabs.mjs';
import { rehypeWrapTables } from './src/plugins/rehype-wrap-tables.mjs';
import { remarkExcerpt } from './src/plugins/remark-excerpt';
+import { parseDirectiveNodes } from './src/plugins/remark-prase-directive.mjs';
import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import sitemap from '@astrojs/sitemap';
@@ -10,7 +12,9 @@ import icon from 'astro-icon';
import pagefind from 'astro-pagefind';
import { defineConfig } from 'astro/config';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
+import rehypeComponents from 'rehype-components';
import rehypeMathJaxCHtml from 'rehype-mathjax/chtml';
+import remarkDirective from 'remark-directive';
import remarkGithubBlockQuote from 'remark-github-beta-blockquote-admonitions';
import remarkMath from 'remark-math';
@@ -49,9 +53,17 @@ export default defineConfig({
},
},
],
+ remarkDirective,
+ parseDirectiveNodes,
],
rehypePlugins: [
rehypeHeadingIds,
+ [
+ rehypeComponents,
+ {
+ components: { tabs: componentTabs },
+ },
+ ],
[
rehypeAutolinkHeadings,
{
package.json
@@ -26,12 +26,15 @@
"autoprefixer": "^10.4.20",
"daisyui": "5.0.0-beta.7",
"dayjs": "^1.11.13",
+ "hastscript": "^9.0.0",
"markdown-it": "^14.1.0",
"mdast-util-to-string": "^4.0.0",
"postcss-load-config": "^6.0.1",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^7.1.0",
+ "rehype-components": "^0.3.0",
"rehype-mathjax": "^6.0.0",
+ "remark-directive": "^3.0.1",
"remark-github-beta-blockquote-admonitions": "^3.1.1",
"remark-math": "^6.0.0",
"sanitize-html": "^2.14.0",
@@ -46,6 +49,7 @@
"@eslint/js": "^9.20.0",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/markdown-it": "^14.1.2",
+ "@types/mdast": "^4.0.4",
"@types/sanitize-html": "^2.13.0",
"@typescript-eslint/parser": "^8.23.0",
"astro-eslint-parser": "^1.2.1",