Commit b5bc27a
Changed files (5)
src
content
posts
plugins
components
styles
src/content/posts/Markdown-Extensions.md
@@ -111,3 +111,28 @@ If no title, will automatically use `Tab [index]` as title.
```
::::
+
+### Inline
+
+:::tabs
+::tab[Component Syntax]
+
+```md
+:inline[content]
+```
+
+::tab[Parameter Description]
+
+- `content`: The content of the inline component, will add `inline` class to the rendered content.
+
+::tab[Component Examples]{active}
+
+This is an inline img example: :inline[].
+
+::tab[Code of Examples]
+
+```md
+This is an inline img example: :inline[].
+```
+
+:::
src/plugins/components/inline.mjs
@@ -0,0 +1,41 @@
+/// <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 componentInline(props, children) {
+ if (!Array.isArray(children)) {
+ return h(
+ 'span',
+ { class: 'hidden' },
+ 'Invalid directive. ("inline" directive must be a text directive with child.)'
+ );
+ }
+ if (children.length !== 1) {
+ return h(
+ 'span',
+ { class: 'hidden' },
+ 'Invalid directive. ("inline" directive must be a text directive with child.)'
+ );
+ }
+ const child = children[0];
+
+ if (child.tagName === 'img') {
+ delete child.properties['data-zoom'];
+ }
+
+ const classes = [
+ ...new Set([
+ ...('class' in child.properties ? child.properties.class : '').split(' '),
+ 'inline',
+ ]),
+ ].join(' ');
+ child.properties.class = classes;
+
+ return h(child.tagName, child.properties, child.children);
+}
src/plugins/remark-image-process.mjs
@@ -10,6 +10,10 @@ export function remarkImageProcess() {
node.data = node.data || {};
node.data.hProperties = node.data.hProperties || {};
node.data.hProperties['data-zoom'] = '';
+ // lazyload
+ node.data.hProperties.loading = 'lazy';
+ // async decode
+ node.data.hProperties.decoding = 'async';
});
};
}
src/styles/markdown.css
@@ -68,12 +68,20 @@ article {
/* 媒体元素 */
img {
- position: relative;
- margin: 1rem auto;
- max-width: 75%;
- max-height: 40rem;
+ &:not(.inline) {
+ position: relative;
+ margin: 1rem auto;
+ max-width: 75%;
+ max-height: 40rem;
+
+ @apply rounded-md;
+ }
- @apply rounded-md;
+ &:is(.inline) {
+ max-height: 1.5em;
+ vertical-align: middle;
+ margin: 0 0.25em;
+ }
}
hr {
astro.config.mjs
@@ -1,5 +1,6 @@
// @ts-check
import { CDN } from './src/constants/cdn.mjs';
+import { componentInline } from './src/plugins/components/inline.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';
@@ -63,7 +64,7 @@ export default defineConfig({
[
rehypeComponents,
{
- components: { tabs: componentTabs },
+ components: { tabs: componentTabs, inline: componentInline },
},
],
[