Просмотр исходного кода

impl pukiwikiLikeLinker plugin for remark

Yuki Takei 3 лет назад
Родитель
Сommit
766e596599

+ 66 - 16
packages/app/src/services/renderer/remark-plugins/pukiwiki-like-linker.ts

@@ -3,28 +3,78 @@ import { syntax } from 'micromark-extension-wiki-link';
 import { Plugin } from 'unified';
 
 
-function add(data: Record<string, unknown>, key: string, value) {
-  if (data[key] != null) {
-    const array = data[key];
-    if (Array.isArray(array)) {
-      array.push(value);
-    }
+type FromMarkdownExtension = {
+  enter: {
+    wikiLink: (token: string) => void,
+  },
+  exit: {
+    wikiLinkTarget: (token: string) => void,
+    wikiLinkAlias: (token: string) => void,
+    wikiLink: (token: string) => void,
   }
-  else {
-    data[key] = [value];
+}
+
+type FromMarkdownData = {
+  value: string | null,
+  data: {
+    alias: string | null,
+    hProperties: Record<string, unknown>,
   }
 }
 
+function swapTargetAndAlias(fromMarkdownExtension: FromMarkdownExtension): FromMarkdownExtension {
+  return {
+    enter: fromMarkdownExtension.enter,
+    exit: {
+      wikiLinkTarget: fromMarkdownExtension.exit.wikiLinkTarget,
+      wikiLinkAlias: fromMarkdownExtension.exit.wikiLinkAlias,
+      wikiLink(token: string) {
+        const wikiLink: FromMarkdownData = this.stack[this.stack.length - 1];
 
-type PukiwikiLikeLinkerParams = {};
+        // swap target and alias
+        //    The default Wiki Link behavior: [[${target}${aliasDivider}${alias}]]
+        //    After swapping:                 [[${alias}${aliasDivider}${target}]]
+        const target = wikiLink.value;
+        const alias = wikiLink.data.alias;
+        if (target != null && alias != null) {
+          wikiLink.value = alias;
+          wikiLink.data.alias = target;
+        }
+
+        // invoke original wikiLink method
+        const orgWikiLink = fromMarkdownExtension.exit.wikiLink.bind(this);
+        orgWikiLink(token);
+      },
+    },
+  };
+}
 
-export const pukiwikiLinkLinker: Plugin<[PukiwikiLikeLinkerParams]> = function(options = {}) {
+/**
+ * Implemented with reference to https://github.com/landakram/remark-wiki-link/blob/master/src/index.js
+ */
+export const pukiwikiLikeLinker: Plugin = function() {
   const data = this.data();
 
-  add(data, 'micromarkExtensions', syntax({}));
-  add(data, 'fromMarkdownExtensions', fromMarkdown({}));
-  add(data, 'toMarkdownExtensions', toMarkdown({}));
-};
+  function add(field: string, value) {
+    if (data[field] != null) {
+      const array = data[field];
+      if (Array.isArray(array)) {
+        array.push(value);
+      }
+    }
+    else {
+      data[field] = [value];
+    }
+  }
 
-// wikiLinkPlugin.wikiLinkPlugin = wikiLinkPlugin;
-// export default wikiLinkPlugin;
+  add('micromarkExtensions', syntax({
+    aliasDivider: '>',
+  }));
+  add('fromMarkdownExtensions', swapTargetAndAlias(fromMarkdown({
+    wikiLinkClassName: 'pukiwiki-like-linker',
+    newClassName: ' ',
+    pageResolver: value => [value],
+    hrefTemplate: permalink => permalink,
+  })));
+  add('toMarkdownExtensions', toMarkdown({}));
+};

+ 2 - 2
packages/app/src/services/renderer/renderer.ts

@@ -17,7 +17,7 @@ import loggerFactory from '~/utils/logger';
 
 import { addClass } from './rehype-plugins/add-class';
 import { relativeLinks } from './rehype-plugins/relative-links';
-import { pukiwikiLinkLinker } from './remark-plugins/pukiwiki-like-linker';
+import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker';
 
 // import CsvToTable from './PreProcessor/CsvToTable';
 // import EasyGrid from './PreProcessor/EasyGrid';
@@ -218,7 +218,7 @@ export type RendererOptions = Partial<ReactMarkdownOptions>;
 
 const generateCommonOptions = (pagePath: string|undefined, config: RendererConfig): RendererOptions => {
   return {
-    remarkPlugins: [gfm, pukiwikiLinkLinker],
+    remarkPlugins: [gfm, pukiwikiLikeLinker],
     rehypePlugins: [
       slug,
       [relativeLinks, { pagePath }],