🌊

GitBucket Markdown Enhanced Plugin に Mark のレンダリング機能を追加しました

に公開

概要

GitBucketのプラグインGitBucket Markdown Enhanced Pluginを開発しています。

今回は、Visual Studio Code のプラグイン Markdown Preview Enhanced の機能である Mark という拡張記法に対応しました。

==Marked==

のように書くと

<mark>Marked</mark>

変換される機能です。

前回の記事

https://qiita.com/yasumichi/items/b3c2b2d0aaa03e2786af

Qiita だけど…

インライン記法のパース先のノードを用意

src\main\scala\io\github\yasumichi\gme\Mark.scala

package io.github.yasumichi.gme

import com.vladsch.flexmark.util.ast.Node
import com.vladsch.flexmark.util.sequence.BasedSequence

class Mark(val text: BasedSequence, val source: BasedSequence) extends Node {
  override def getSegments: Array[BasedSequence] = Array(source)
}

インラインパーサーの作成

src\main\scala\io\github\yasumichi\gme\MarkInlineParserExtension.scala

package io.github.yasumichi.gme

import com.vladsch.flexmark.parser.{InlineParser, InlineParserExtension, InlineParserExtensionFactory, LightInlineParser}
import java.util
import java.util.regex.Pattern

class MarkInlineParserExtension() extends InlineParserExtension {
  override def finalizeDocument(inlineParser: InlineParser): Unit = {}
  override def finalizeBlock(inlineParser: InlineParser): Unit = {}
  override def parse(inlineParser: LightInlineParser): Boolean = {
    val patternText = """==(.+?)=="""
    val matches = inlineParser.matchWithGroups(Pattern.compile(patternText))
    if (matches != null) {
      inlineParser.flushTextNode()
      val markText = matches(1)
      inlineParser.getBlock.appendChild(new Mark(markText, matches(0)))
      return true
    }
    false
  }
}
object MarkInlineParserExtension {
  class Factory() extends InlineParserExtensionFactory {
    override def getCharacters: CharSequence = "="
    override def apply(inlineParser: LightInlineParser): InlineParserExtension = new MarkInlineParserExtension()
    override def getAfterDependents: util.Set[Class[_]] = null
    override def getBeforeDependents: util.Set[Class[_]] = null
    override def affectsGlobalScope(): Boolean = false
  }
}

MarkInlineParserExtension.Factory の

    override def getCharacters: CharSequence = "="

というメソッドで Mark の先頭文字 = を指定。

また、MarkInlineParserExtension.parse() メソッドの

    val patternText = """==(.+?)=="""

前後に == で囲まれた文字列にマッチするように指定しています。

ノードレンダラーの作成

既存の MarkdownEnhancedNodeRenderer に機能を追加することにしました。

MarkdownEnhancedNodeRenderer.getNodeRenderingHandlers() メソッドが返す HashSet に以下を追加しました。

    set.add(
      new NodeRenderingHandler[Mark](
        classOf[Mark],
        this.renderMark
      )
    )

実際の renderMark() メソッドは、次のように実装しました。

  private def renderMark(
      node: Mark,
      context: NodeRendererContext,
      html: HtmlWriter
  ): Unit = {
    html.tag("mark")
    html.text(node.text.toString())
    html.tag("/mark")
  }

拡張への追加

既存の MarkdownEnhancedExtention クラスの extend() メソッドで先ほど作成したインラインパーサーを登録します。

    override def extend(parserBuilder: Parser.Builder): Unit = {
      parserBuilder.customInlineParserExtensionFactory(new MarkInlineParserExtension.Factory())
    }

スタイルの追加

src\main\resources\gme\assets\gme.css に以下を追加しました。

mark {
    background-color: #fffd54;
    padding: 0;
}

スクリーンショット

以下のように マーク の部分が強調表示されるようになりました。

参考リンク

GitHubで編集を提案

Discussion