未分類

マークダウン形式文字列のコードブロック外に存在する特定の記号をサニタイズする。

下記のようなコードブロックとコードブロック外の混在するマークダウン形式の文章があるとします。

33178870c736b737203c8b0678552038.png

以下の要件で文字列をサニタイズします。

・以下の記号をエスケープシーケンスに置き換えます。
(ただしコードブロック内の記号については置き換えない。)
(ただし、画像のURL内に含まれる&は置き換えない)

& は & に置き換え
< は  &lt;  に置き換え
>  は &gt;  に置き換え
" は &quot;  に置き換え
' は &#x27;  に置き換え

実装方針

1.文字列を「```」で分割する。
2.分割されたブロックがそれぞれコードブロック部分か、そうでないかを判別する。
3.コードブロック外の文字列の場合、上記の記号を置き換える。
4.画像URLないの&については置き換えない。
5.分割した文字列を再結合する。

サニタイズ後の文字列

ここはコード外です。# 大文字&lt; &gt; &amp; &#x27; &quot;&lt;&gt;&amp;&#x27;&quot;```javascriptconst test = () => {    console.log('テスト')const one = 1;const two = 2;if(one < tow && one >=0){ console.log("over") }}```コード外です2。*斜体*&lt;a onmouseover=alert(document.cookie)&gt;click me!&lt;/a&gt;```javascriptonmouseover=alert(document.cookie)>click me!</a>```![image](https://firebasestorage.googleapis.com/v0/b/searchistory.appspot.com/o/images%2F45d84e1d-5c54-48df-ae98-8ec8c7a6cdd1?alt=media&token=4c436dd6-92f7-41a2-8211-0cd41f769278) 

1についての関数(文字列を「```」で分割する。)

const originWord = "```javascript <inCodeWord> ``` <outCodeWord>  ```javascrpt <inCodeWord> ```"

const sanitize = (originWord) => {
  const splitReg = /(?=```)/
  const splitedArray = originWord.split(splitReg);

  console.log(splitedArray);
}

//結果
//["```javascript <inCodeWord> ","``` <outCodeWord>  ","```javascrpt <inCodeWord> ","```"]

// 正規表現の/(?=```)/でsplitすることにより肯定先読みで、
// ```の直前の位置で文字列を分割し配列化する。

2についての実装追加(分割されたブロックがそれぞれコードブロック部分か、そうでないかを判別する。)

配列の各文字列の先頭の```の直後に文字(言語名)が続く場合はコードブロック内、そうでなければコードブロック外と判定する。

const originWord = "```javascript <inCodeWord> ``` <outCodeWord>  ```javascrpt <inCodeWord> ```"

const sanitize = (originWord) => {
  const splitReg = /(?=```)/
  const splitedArray = originWord.split(splitReg);

  for (let i = 0; i < splitedArray.length; i++) {
    const splitReg = /^```\w+\s/
    if (!splitReg.test(splitedArray[i])) {
      console.log("out code");
    } else {
      console.log("in code");
    }
  }
}

sanitize(originWord)

//結果
//"in code", "out code", "in code"

3についての実装追加(コードブロック外の文字列の場合、上記の記号を置き換える。)

const originWord = "```javascript <inCodeWord>' ``` <outCodeWord>  ```javascrpt <inCodeWord> ```"

//記号置き換え関数を追加
const escapeHTML = (word) => {
  return word.replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, "&#x27;");
}

const sanitize = (originWord) => {
  const splitReg = /(?=```)/
  const splitedArray = originWord.split(splitReg);

  for (let i = 0; i < splitedArray.length; i++) {
    const splitReg = /^```\w+\s/
    if (!splitReg.test(splitedArray[i])) {
      const sanitizedBlockWord = escapeHTML(splitedArray[i])
      console.log(sanitizedBlockWord)
    } else {
      console.log(splitedArray[i]);
    }
  }
}

sanitize(originWord)

//結果
//"```javascript <inCodeWord>' "
//"``` &lt;outCodeWord&gt;  "
//"```javascrpt <inCodeWord> "

4についての実装追加(画像URL内の&については置き換えない。)

//略 

const originWord = "```javascript &  ``` media&token &```"

const escapeHTML = (word) => {
  return word.replace(/(?<!(media))&(?!(token))?/g, '&amp;')//修正
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, "&#x27;");
}

//略 

//結果
//"```javascript &  "
//"``` media&token &amp;"
//"```"

//escapeHTMLの&の置き換え関数を修正
//画像URLに含まれる&は必ず media&tokenという形式なので、正規表現で置き換え対象から除外する。

5の実装追加(分割した文字列を再結合する。)

const originWord = "```javascript <inCodeWord> ``` <outCodeWord>&  media&token ```javascrpt <inCodeWord> ```"

const escapeHTML = (word) => {
  return word.replace(/(?<!(media))&(?!(token))?/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, "&#x27;");
}

const sanitize = (originWord) => {
  const splitReg = /(?=```)/
  const splitedArray = originWord.split(splitReg);

  let sanitizedAllWord = ""

  for (let i = 0; i < splitedArray.length; i++) {
    const splitReg = /^```\w+\s/
    if (!splitReg.test(splitedArray[i])) {
      sanitizedAllWord = sanitizedAllWord + escapeHTML(splitedArray[i]);
    } else {
      sanitizedAllWord = sanitizedAllWord + splitedArray[i];
    }
  }
  return sanitizedAllWord;
}

console.log(sanitize(originWord));

//結果
//"```javascript <inCodeWord> ``` &lt;outCodeWord&gt;&lt;  media&token ```javascrpt <inCodeWord> ```"

以上です。

-未分類