Skip to content

Commit

Permalink
feat: Implemented document processing as VFM in case of major metadet…
Browse files Browse the repository at this point in the history
…a design changes
  • Loading branch information
akabekobeko committed May 29, 2021
1 parent 95239b2 commit fb57dae
Show file tree
Hide file tree
Showing 5 changed files with 1,145 additions and 1,809 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
},
"dependencies": {
"debug": "^4.3.1",
"doctype": "^2.0.4",
"github-slugger": "^1.3.0",
"hast-util-find-and-replace": "^3.2.0",
"hast-util-is-element": "^1.1.0",
Expand All @@ -66,7 +67,6 @@
"mdast-util-to-string": "^2.0.0",
"meow": "^9.0.0",
"refractor": "^3.3.0",
"rehype-document": "^5.1.0",
"rehype-format": "^3.1.0",
"rehype-katex": "^4.0.0",
"rehype-raw": "^5.0.0",
Expand Down Expand Up @@ -108,14 +108,14 @@
"common-tags": "^1.8.0",
"eslint": "^7.18.0",
"husky": "^4.3.8",
"jest": "^26.6.3",
"jest": "^27.0.1",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"prettier-plugin-organize-imports": "^1.1.1",
"pretty-quick": "^3.1.0",
"release-it": "^14.2.2",
"shx": "^0.3.3",
"ts-jest": "^26.5.4",
"ts-jest": "^27.0.1",
"typescript": "^4.2.3"
}
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import doc from 'rehype-document';
import rehypeFormat from 'rehype-format';
import rehypeStringify from 'rehype-stringify';
import unified, { Processor } from 'unified';
import { hast as hastClearHtmlLang } from './plugins/clear-html-lang';
import { mdast as doc } from './plugins/document';
import { hast as hastMath } from './plugins/math';
import { hast as hastMetadata, MetadataVFile } from './plugins/metadata';
import { replace as handleReplace, ReplaceRule } from './plugins/replace';
Expand Down Expand Up @@ -79,7 +79,7 @@ export function VFM({
}

if (!partial) {
processor.use(doc, { language, css: style, title });
processor.use(doc, { language, css: style, title, responsive: true });
if (!language) {
processor.use(hastClearHtmlLang);
}
Expand Down
157 changes: 157 additions & 0 deletions src/plugins/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/**
* derived from `rehype-document`.
* original: Copyright (c) 2016 Titus Wormer <tituswormer@gmail.com>
* modified: 2021 and later is Akabeko
* @license MIT
* @see https://github.com/rehypejs/rehype-document
*/

import doctype from 'doctype';
import { Properties } from 'hast';
import h from 'hastscript';
import { Node } from 'unist';
import { VFile } from 'vfile';

/** Options. */
export type DocOptions = {
/** Text of <html lang="...">. */
language?: string;
/**
* Version of HTML.
* @see https://github.com/wooorm/doctype
*/
doctype?: string;
/** Whether to insert a `meta[viewport]`. */
responsive?: boolean;
/** Text of `<title>...</title>`. */
title?: string;
/** Array of `<meta>`. */
meta?: Properties | Properties[];
/** Array of `<link>`. */
link?: Properties | Properties[];
/** Array of `<style>...</style>` */
style?: string | string[];
/** Array of `<link ref="stylesheet" href="...">`. */
css?: string | string[];
/** Array of `<script>...</script>`. */
script?: string | string[];
/** Array of `<script src="...">`. */
js?: string | string[];
};

/**
* Makes the specified values into an array.
* @param value Value.
* @returns Array.
*/
const castArray = <T>(value: undefined | T | T[]): T[] => {
if (!value) {
return [];
}

return Array.isArray(value) ? value : [value];
};

/**
* Process Markdown AST.
* @param options Options.
* @returns Transformer.
*/
export const mdast = (options: DocOptions) => (tree: Node, vfile: VFile) => {
const head = [{ type: 'text', value: '\n' }, h('meta', { charset: 'utf-8' })];

// `<title>...</title>`
{
const title = options.title || vfile.stem;
if (title) {
head.push({ type: 'text', value: '\n' }, h('title', [title]));
}
}

// `<meta>`
{
const properties = castArray<Properties>(options.meta);
if (options.responsive) {
properties.unshift({
name: 'viewport',
content: 'width=device-width, initial-scale=1',
});
}

for (const meta of properties) {
head.push({ type: 'text', value: '\n' }, h('meta', meta));
}
}

// `<link>`
{
const properties = castArray<Properties>(options.link);
for (const link of properties) {
head.push({ type: 'text', value: '\n' }, h('link', link));
}
}

// `<style>...</style>`
{
const styles = castArray<string>(options.style);
for (const style of styles) {
head.push({ type: 'text', value: '\n' }, h('style', style));
}

head.push({ type: 'text', value: '\n' });
}

// `<link rel="stylesheet" href="...">`
{
const filePaths = castArray<string>(options.css);
for (const href of filePaths) {
head.push(
{ type: 'text', value: '\n' },
h('link', { rel: 'stylesheet', href }),
);
}
}

// <body>...</body>
const contents =
tree.type === 'root' && Array.isArray(tree.children)
? tree.children.concat()
: [tree];
if (0 < contents.length) {
contents.unshift({ type: 'text', value: '\n' });
}

// `<script>...</script>` to end of `<body>`
{
const scripts = castArray<string>(options.script);
for (const script of scripts) {
contents.push({ type: 'text', value: '\n' }, h('script', script));
}
}

// `<script src="...">` to end of `<body>`
{
const sources = castArray<string>(options.js);
for (const src of sources) {
contents.push({ type: 'text', value: '\n' }, h('script', { src }));
}

contents.push({ type: 'text', value: '\n' });
}

return {
type: 'root',
children: [
{ type: 'doctype', name: doctype(options.doctype || 5) },
{ type: 'text', value: '\n' },
h('html', { lang: options.language || undefined }, [
{ type: 'text', value: '\n' },
h('head', head),
{ type: 'text', value: '\n' },
h('body', contents),
{ type: 'text', value: '\n' },
]),
{ type: 'text', value: '\n' },
],
};
};
1 change: 1 addition & 0 deletions types/remark.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ declare module 'remark-math';
declare module 'unist-util-remove';
declare module 'remark-attr';
declare module 'unist-util-find-after';
declare module 'doctype';

interface Tokenizer {
(
Expand Down
Loading

0 comments on commit fb57dae

Please sign in to comment.