Custom plugin for description and "minutes reading"

This commit is contained in:
DarkCat09 2023-06-18 20:00:53 +04:00
parent 82d3214187
commit 94f3de5337
5 changed files with 236 additions and 8 deletions

View file

@ -1,10 +1,12 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import compress from "astro-compress"; import compress from "astro-compress";
import remarkPostMeta from './remark-post-meta.mjs';
import remarkUnwrapImages from 'remark-unwrap-images'; import remarkUnwrapImages from 'remark-unwrap-images';
import { rehypeHeadingIds } from '@astrojs/markdown-remark'; import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import rehypeSlug from 'rehype-slug'; import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings'; import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeFigure from 'rehype-figure';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
@ -14,7 +16,10 @@ export default defineConfig({
}, },
markdown: { markdown: {
syntaxHighlight: "shiki", syntaxHighlight: "shiki",
remarkPlugins: [remarkUnwrapImages], remarkPlugins: [
remarkPostMeta,
remarkUnwrapImages,
],
rehypePlugins: [ rehypePlugins: [
rehypeSlug, rehypeSlug,
rehypeHeadingIds, rehypeHeadingIds,
@ -22,6 +27,10 @@ export default defineConfig({
rehypeAutolinkHeadings, rehypeAutolinkHeadings,
{ behavior: "append" }, { behavior: "append" },
], ],
[
rehypeFigure,
{ className: "rehype-figure" },
],
], ],
}, },
}); });

196
package-lock.json generated
View file

@ -10,7 +10,10 @@
"astro": "^2.3.0", "astro": "^2.3.0",
"astro-compress": "^1.1.42", "astro-compress": "^1.1.42",
"less": "^4.1.3", "less": "^4.1.3",
"mdast-util-to-string": "^3.2.0",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-figure": "^1.0.1",
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",
"remark-unwrap-images": "^3.0.1" "remark-unwrap-images": "^3.0.1"
} }
@ -4638,6 +4641,11 @@
"node": ">=8.10.0" "node": ">=8.10.0"
} }
}, },
"node_modules/reading-time": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz",
"integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg=="
},
"node_modules/rehype": { "node_modules/rehype": {
"version": "12.0.1", "version": "12.0.1",
"resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz", "resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz",
@ -4671,6 +4679,106 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/rehype-figure": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rehype-figure/-/rehype-figure-1.0.1.tgz",
"integrity": "sha512-g7DJuK8R8xHIaPI3QJ6/OoWiKepn92RF2CV3z4dO7lRO6ZHo48Tu9X3KgnZUKK035srFHqWQx93AybBy12XqmQ==",
"dependencies": {
"hastscript": "^6.0.0",
"unist-util-visit": "^2.0.3"
}
},
"node_modules/rehype-figure/node_modules/comma-separated-tokens": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/rehype-figure/node_modules/hast-util-parse-selector": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
"integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-figure/node_modules/hastscript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
"integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
"dependencies": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^1.0.0",
"hast-util-parse-selector": "^2.0.0",
"property-information": "^5.0.0",
"space-separated-tokens": "^1.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-figure/node_modules/property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
"integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
"dependencies": {
"xtend": "^4.0.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/rehype-figure/node_modules/space-separated-tokens": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
"integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/rehype-figure/node_modules/unist-util-is": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
"integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-figure/node_modules/unist-util-visit": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
"integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0",
"unist-util-visit-parents": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-figure/node_modules/unist-util-visit-parents": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
"integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
"dependencies": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-parse": { "node_modules/rehype-parse": {
"version": "8.0.4", "version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
@ -6093,6 +6201,14 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}, },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
},
"node_modules/yallist": { "node_modules/yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
@ -9272,6 +9388,11 @@
"picomatch": "^2.2.1" "picomatch": "^2.2.1"
} }
}, },
"reading-time": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz",
"integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg=="
},
"rehype": { "rehype": {
"version": "12.0.1", "version": "12.0.1",
"resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz", "resolved": "https://registry.npmjs.org/rehype/-/rehype-12.0.1.tgz",
@ -9297,6 +9418,76 @@
"unist-util-visit": "^4.0.0" "unist-util-visit": "^4.0.0"
} }
}, },
"rehype-figure": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rehype-figure/-/rehype-figure-1.0.1.tgz",
"integrity": "sha512-g7DJuK8R8xHIaPI3QJ6/OoWiKepn92RF2CV3z4dO7lRO6ZHo48Tu9X3KgnZUKK035srFHqWQx93AybBy12XqmQ==",
"requires": {
"hastscript": "^6.0.0",
"unist-util-visit": "^2.0.3"
},
"dependencies": {
"comma-separated-tokens": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz",
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw=="
},
"hast-util-parse-selector": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",
"integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ=="
},
"hastscript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz",
"integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==",
"requires": {
"@types/hast": "^2.0.0",
"comma-separated-tokens": "^1.0.0",
"hast-util-parse-selector": "^2.0.0",
"property-information": "^5.0.0",
"space-separated-tokens": "^1.0.0"
}
},
"property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
"integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==",
"requires": {
"xtend": "^4.0.0"
}
},
"space-separated-tokens": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
"integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA=="
},
"unist-util-is": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
"integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg=="
},
"unist-util-visit": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
"integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0",
"unist-util-visit-parents": "^3.0.0"
}
},
"unist-util-visit-parents": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
"integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
"requires": {
"@types/unist": "^2.0.0",
"unist-util-is": "^4.0.0"
}
}
}
},
"rehype-parse": { "rehype-parse": {
"version": "8.0.4", "version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
@ -10254,6 +10445,11 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}, },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"yallist": { "yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View file

@ -13,7 +13,10 @@
"astro": "^2.3.0", "astro": "^2.3.0",
"astro-compress": "^1.1.42", "astro-compress": "^1.1.42",
"less": "^4.1.3", "less": "^4.1.3",
"mdast-util-to-string": "^3.2.0",
"reading-time": "^1.5.0",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-figure": "^1.0.1",
"rehype-slug": "^5.1.0", "rehype-slug": "^5.1.0",
"remark-unwrap-images": "^3.0.1" "remark-unwrap-images": "^3.0.1"
} }

16
remark-post-meta.mjs Normal file
View file

@ -0,0 +1,16 @@
import getReadingTime from 'reading-time';
import { toString as mdToString } from 'mdast-util-to-string';
const ELLIPSIS = '\u2026';
export default function() {
return function (tree, { data }) {
const textOnPage = mdToString(tree);
const readingTime = getReadingTime(textOnPage);
data.astro.frontmatter.readingTime = readingTime.text;
const description = textOnPage.slice(0, 100) + ELLIPSIS;
data.astro.frontmatter.description = description;
};
}

View file

@ -34,13 +34,11 @@ const { slug } = Astro.params;
const post: postType = Astro.props.post; const post: postType = Astro.props.post;
const postObj = await post.render(); const postObj = await post.render();
const fm = postObj.remarkPluginFrontmatter;
const title = postObj.headings[0]?.text || ''; const title = postObj.headings[0]?.text || '';
const description = post.body const description = fm.description;
.replace(/[^A-Za-z0-9А-ЯЁа-яё+-]/g, ' ') const readingTime = fm.readingTime;
.replace(/ {2,}/g, ' ')
.slice(0, 100)
.trim() + '\u2026'; // 2026 = ellipsis
let dateStr = slug.split("-", 1)[0]; let dateStr = slug.split("-", 1)[0];
let date: Date | undefined; let date: Date | undefined;
@ -64,7 +62,7 @@ const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content={image} /> <meta property="og:image" content={image} />
<meta property="article:published_time" content={date.toISOString()} /> <meta property="article:published_time" content={date?.toISOString()} />
<meta property="article:author" content="DarkCat09" /> <meta property="article:author" content="DarkCat09" />
<meta property="twitter:card" content="summary" /> <meta property="twitter:card" content="summary" />
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
@ -74,8 +72,14 @@ const image = (post.body.match(/(?:\s|^)!\[.*\]\((.*?)\)/) || [])[1];
<header> <header>
<h1>{title}</h1> <h1>{title}</h1>
<address> <address>
<time datetime={date.toISOString()}>{date.toLocaleDateString()}</time>, on
<time datetime={date?.toISOString()}>{date?.toLocaleDateString()}</time>
by
<a href="https://t.me/dcat09" rel="author">DarkCat09</a> <a href="https://t.me/dcat09" rel="author">DarkCat09</a>
//
<span id="reading-time">
{readingTime}
</span>
</address> </address>
</header> </header>
<article> <article>