diff --git a/src/components/SearchBoxFlexSearch.vue b/src/components/SearchBoxFlexSearch.vue
index 013bee1..dceaa08 100644
--- a/src/components/SearchBoxFlexSearch.vue
+++ b/src/components/SearchBoxFlexSearch.vue
@@ -51,6 +51,7 @@
import { Document } from 'flexsearch'
import data from '@dynamic/vuepress-plugin-flexsearch/data'
import excerpt from './excerpt'
+import matcher from './matcher';
import ngram from '../tokenizer/ngram'
/* global FLEX_SEARCH_HOTKEYS */
@@ -159,6 +160,7 @@ export default {
setUpFlexSearchDocument () {
for (const locale in data) {
const doc = new Document({
+ matcher: matcher,
tokenize: 'forward',
id: 'key',
index: [
diff --git a/src/components/excerpt.js b/src/components/excerpt.js
index b6c6945..a1c9e2b 100644
--- a/src/components/excerpt.js
+++ b/src/components/excerpt.js
@@ -1,11 +1,13 @@
const ExcerptHtml = require('./excerpt-html');
const TextProcessing = require('./text-processing');
+const matcher = require('./matcher');
+
/**
* @typedef {Object} ExcerptOption
* @property {number} [aroundLength]
- * @property {string} [head]
- * @property {string} [tail]
+ * @property {string} [headText]
+ * @property {string} [tailText]
*/
/**
@@ -22,7 +24,7 @@ const create = (content, query, option) => {
} = option || {};
const contentLowerCase = content.toLowerCase();
- const queryLowerCase = query.toLowerCase();
+ const queryLowerCase = addMatcher(query).toLowerCase();
const textProcessing = new TextProcessing();
@@ -46,6 +48,22 @@ const create = (content, query, option) => {
return content.slice(0, aroundLength) + (content.length > aroundLength ? tailText : '');
};
+/**
+ * @param {string} query
+ * @return {string}
+ */
+const addMatcher = (query) => {
+ let converted1 = query;
+ let converted2 = query;
+
+ Object.keys(matcher).forEach((key) => {
+ converted1 = converted1.replaceAll(key, matcher[key]);
+ converted2 = converted2.replaceAll(matcher[key], key);
+ })
+
+ return [query, converted1, converted2].join(' ');
+};
+
/**
* @param {string} excerpt
* @param {string[]} queries
diff --git a/src/components/matcher.js b/src/components/matcher.js
new file mode 100644
index 0000000..d2ac349
--- /dev/null
+++ b/src/components/matcher.js
@@ -0,0 +1,95 @@
+module.exports = {
+ '1': '1',
+ '2': '2',
+ '3': '3',
+ '4': '4',
+ '5': '5',
+ '6': '6',
+ '7': '7',
+ '8': '8',
+ '9': '9',
+ '0': '0',
+
+ 'あ': 'ア',
+ 'い': 'イ',
+ 'う': 'ウ',
+ 'え': 'エ',
+ 'お': 'オ',
+ 'か': 'カ',
+ 'き': 'キ',
+ 'く': 'ク',
+ 'け': 'ケ',
+ 'こ': 'コ',
+ 'さ': 'サ',
+ 'し': 'シ',
+ 'す': 'ス',
+ 'せ': 'セ',
+ 'そ': 'ソ',
+ 'た': 'タ',
+ 'ち': 'チ',
+ 'つ': 'ツ',
+ 'て': 'テ',
+ 'と': 'ト',
+ 'な': 'ナ',
+ 'に': 'ニ',
+ 'ぬ': 'ヌ',
+ 'ね': 'ネ',
+ 'の': 'ノ',
+ 'は': 'ハ',
+ 'ひ': 'ヒ',
+ 'ふ': 'フ',
+ 'へ': 'ヘ',
+ 'ほ': 'ホ',
+ 'ま': 'マ',
+ 'み': 'ミ',
+ 'む': 'ム',
+ 'め': 'メ',
+ 'も': 'モ',
+ 'や': 'ヤ',
+ 'ゆ': 'ユ',
+ 'よ': 'ヨ',
+ 'ら': 'ラ',
+ 'り': 'リ',
+ 'る': 'ル',
+ 'れ': 'レ',
+ 'ろ': 'ロ',
+ 'わ': 'ワ',
+ 'を': 'ヲ',
+ 'ん': 'ン',
+
+ 'が': 'ガ',
+ 'ぎ': 'ギ',
+ 'ぐ': 'グ',
+ 'げ': 'ゲ',
+ 'ご': 'ゴ',
+ 'ざ': 'ザ',
+ 'じ': 'ジ',
+ 'ず': 'ズ',
+ 'ぜ': 'ゼ',
+ 'ぞ': 'ゾ',
+ 'だ': 'ダ',
+ 'ぢ': 'ヂ',
+ 'づ': 'ヅ',
+ 'で': 'デ',
+ 'ど': 'ド',
+ 'ば': 'バ',
+ 'び': 'ビ',
+ 'ぶ': 'ブ',
+ 'べ': 'ベ',
+ 'ぼ': 'ボ',
+
+ 'ぱ': 'パ',
+ 'ぴ': 'ピ',
+ 'ぷ': 'プ',
+ 'ぺ': 'ペ',
+ 'ぽ': 'ポ',
+
+ 'ぁ': 'ァ',
+ 'ぃ': 'ィ',
+ 'ぅ': 'ゥ',
+ 'ぇ': 'ェ',
+ 'ぉ': 'ォ',
+ 'ゃ': 'ャ',
+ 'ゅ': 'ュ',
+ 'ょ': 'ョ',
+};
diff --git a/test/components/excerpt.js b/test/components/excerpt.js
index 9505dce..7a967ae 100644
--- a/test/components/excerpt.js
+++ b/test/components/excerpt.js
@@ -84,6 +84,25 @@ describe('components', () => {
'weigh ...',
],
+ // matcher
+ [
+ '2023',
+ {},
+ '2023年',
+ '2023年',
+ ],
+ [
+ '2023',
+ {},
+ '2023年',
+ '2023年',
+ ],
+ [
+ 'いぬ ねこ',
+ {},
+ 'イヌとネコ',
+ 'イヌとネコ',
+ ],
];
dataSet.forEach(([query, option, content, highlighted]) => {