AutoBracketter
漢字、カタカナ、アルファベットなどの一塊を自動でブラケティングするPopupメニュー用UserScript
AutoBracketter試験用で試験を行う
要件
自動ブラケティングしたい範囲を選択して表示されたPopupメニューからあるボタンをクリックすると、漢字、カタカナ、アルファベットの2次以上の一塊を自動でブラケティング([と]で囲うこと)をしてくれる
バージョン
code:script.js
import '/api/code/my-knowledge/AutoBracketter/script_v2_0_0.js';
v1.0.0
連続する漢字、カタカナ、半角カタカナ、数字、アルファベットをブラケティングする
課題
URLや装飾、`で囲われた文字も見境なくブラケティングする
code:script_v1_0_0.js
scrapbox.PopupMenu.addButton({
title: '📘',
onClick: text => ab(text)
})
const regList = [
[0-9],
[a-zA-Z],
[\u4E00-\u9FFF\u3005-\u3007],// 漢字
[\u30A0-\u30FF],// カタカナ
[\uFF61-\uFF9F],// 半角カタカナ
];
// 連続した数字、連続したアルファベットそれぞれで検索及び置換を実施
// どちらかに限定して検索
// 「連続した〇〇」にマッチした文字列の配列で forEach
// 要素がsetに無ければ追加して置換
// あれば何もしない
function ab(t) {
const s = new Set();
let rslt = t;
// 連続した文字を種類ずつ(数字のみ、アルファベットのみ...で)検索
for (let r of regList) {
// マッチした文字列の配列でループ
t.match(new RegExp(${r}{2,}, "g"))?.forEach(e => {
if (!s.has(e)) {
s.add(e);
rslt = rslt.replace(new RegExp((?<!${r})${e}(?!${r})), [${e}]);
}
});
}
return rslt;
}
v2.0.0
とりあえず数字と連続して出現するドット「.」とコンマ「,」を同じブラケットで囲うように変更
例:10.5.2、10,000,000
code:script_v2_0_0.js
scrapbox.PopupMenu.addButton({
title: '📘',
onClick: text => ab(text)
})
const regList = [
[0-9\.,],
[a-zA-Z],
[\u4E00-\u9FFF\u3005-\u3007],// 漢字
[\u30A0-\u30FF],// カタカナ
[\uFF61-\uFF9F],// 半角カタカナ
];
// 連続した数字、連続したアルファベットそれぞれで検索及び置換を実施
// どちらかに限定して検索
// 「連続した〇〇」にマッチした文字列の配列で forEach
// 要素がsetに無ければ追加して置換
// あれば何もしない
function ab(t) {
const s = new Set();
let rslt = t;
// 連続した文字を種類ずつ(数字のみ、アルファベットのみ...で)検索
for (let r of regList) {
// マッチした文字列の配列でループ
t.match(new RegExp(${r}{2,}, "g"))?.forEach(e => {
if (!s.has(e)) {
s.add(e);
rslt = rslt.replace(new RegExp((?<!${r})${e}(?!${r})), [${e}]);
}
});
}
return rslt;
}
v3.0.0_prev
課題
全角数字を半角数字に変換
数字と「年」が続くときもカウント
アルファベットが半角空白を挟んで続くときは1つとしてカウント?
数字と「つ」が続くときもカウント
全角のシャープ(#)を半角シャープ(#)に変換
`で囲われた文字列をブラケティングしないようにする
code:script_v3_0_0.js
scrapbox.PopupMenu.addButton({
title: '📘',
onClick: text => ab2(text)
})
const regList = [
[0-9],
[a-zA-Z],
[\u4E00-\u9FFF\u3005-\u3007],// 漢字
[\u30A0-\u30FF],// カタカナ
[\uFF61-\uFF9F],// 半角カタカナ
];
// 連続した数字、連続したアルファベットそれぞれで検索及び置換を実施
// どちらかに限定して検索
// 「連続した〇〇」にマッチした文字列の配列で forEach
// 要素がsetに無ければ追加して置換
// あれば何もしない
function ab2(t) {
const s = new Set();
let rslt = t;
// 連続した文字を種類ずつ(数字のみ、アルファベットのみ...で)検索
for (let r of regList) {
// マッチした文字列の配列でループ
t.match(new RegExp(${r}{2,}, "g"))?.forEach(e => {
if (!s.has(e)) {
s.add(e);
rslt = rslt.replace(new RegExp((?<!${r})${e}(?!${r})), [${e}]);
}
});
}
return rslt;
}
v.4.0.0_prev
既にブラケティングしてある文字列をブラケティングしないようにする
ブラケティングした後で[[と]]を[と]に置換すれば良いのでは!?
[[の後に出てくる]]を[と]に置換
[[あ]]は変えるけど[あ[ああ]]や[[あ]ああ]は変えない
String.prototype.match() - JavaScript | MDN
g フラグがなかった場合、最初に完全に一致したものと、それに関するキャプチャグループを返します。この場合、match() は RegExp.prototype.exec() と同じ結果になります(追加のプロパティ付きの配列)。
このキャプチャグループは使える…かも?
試験用文章
code:test
自動ブラケティングしたい範囲を選択して表示されたPopupメニューからあるボタンをクリックすると、漢字、カタカナ、アルファベットの2次以上の一塊を自動でブラケティング([と]で囲うこと)をしてくれる
code:AutoBracketter.js
const testTxt1 = `独特の華麗な世界観を持つ上生菓子など、歴史とともに洗練されてきた京都の和菓子。献上菓子として宮中や公家の他、寺院からの注文にも応えてきました。
京菓子は、粉を混ぜたり伸ばしたり、切ったりしますが、この工程が、蕎麦切りと共通する点が多く、寺院からの依頼で和菓子職人が蕎麦打ちをするようになったといわれています。
京都で一番古い歴史のある本家尾張屋も、元々は菓子店として創業した歴史があり、御所や寺院から蕎麦の注文をたくさんもらううちに、蕎麦店を開業。御所に出入りする「御用蕎麦司」となった歴史があります。
ちなみにこの本家尾張屋には、江戸時代末期に十三代目当主が考案した「そば餅」をはじめ、十四代目当主考案の「蕎麦板」(蕎麦の麺打ちをするような技法で作られた蕎麦菓子)、十五代目考案のそば焙煎わらび餅、蕎麦ぼうる、十六代目当主が考案した蕎麦かりんとう…と、当主が自ら蕎麦菓子を作る伝統があります。`;
const debugFlag = 1;
const f = (t) => debugFlag ? console.log(t) : "";
/*
文字列から(漢字|カタカナ|アルファベット){2,}の文字列を取り、
setに無いならsetに追加してブラケット
あれば何もしない
*/
// [蕎麦切]り
function AutoBracketter(txt) {
// f(txt);
const s = new Set();
// 連続した(漢字|カタカナ|半角カタカナ|アルファベット|数字)にマッチ
const reg = /(?<!\[)(\u4E00-\u9FFF\u3005-\u3007{2,}|\u30A0-\u30FF{2,}|\uFF61-\uFF9F{2,}|a-zA-Z{2,}|0-9{2,})(?!\])/g;
returnTxt = txt;
f(returnTxt);
txt.match(reg).forEach(e => {
f(e);
if (!s.has(e)) {
s.add(e);
// returnTxt = returnTxt.replace(e, [${e}]);
returnTxt = returnTxt.replace(new RegExp((?<!\\[)${e}), [${e}]);
}
f(returnTxt);
});
f(returnTxt);
}
AutoBracketter(testTxt1);
const result1 = `独特の華麗な世界観を持つ上生菓子など、歴史とともに洗練されてきた京都の和菓子。献上菓子として宮中や公家の他、寺院からの注文にも応えてきました。
京菓子は、粉を混ぜたり伸ばしたり、切ったりしますが、この工程が、[蕎麦切]りと共通する点が多く、寺院からの依頼で和菓子職人が蕎麦打ちをするようになったといわれています。
京都で一番古い歴史のある本家尾張屋も、元々は菓子店として創業した歴史があり、御所や寺院から蕎麦の注文をたくさんもらううちに、蕎麦店を開業。御所に出入りする「御用蕎麦司」となった歴史があります。
ちなみにこの本家尾張屋には、江戸時代末期に[十三代目当主]が考案した「そば餅」をはじめ、十四代目当主考案の「蕎麦板」(蕎麦の麺打ちをするような技法で作られた蕎麦菓子)、十五代目考案のそば焙煎わらび餅、蕎麦ぼうる、十六代目当主が考案した蕎麦かりんとう…と、当主が自ら蕎麦菓子を作る伝統があります。
`;
const result2 = `独特の華麗な世界観を持つ上生菓子など、歴史とともに洗練されてきた京都の和菓子。献上菓子として宮中や公家の他、寺院からの注文にも応えてきました。
京菓子は、粉を混ぜたり伸ばしたり、切ったりしますが、この工程が、蕎麦切りと共通する点が多く、寺院からの依頼で和菓子職人が蕎麦打ちをするようになったといわれています。
京都で一番古い歴史のある本家尾張屋も、元々は菓子店として創業した歴史があり、御所や寺院から蕎麦の注文をたくさんもらううちに、蕎麦店を開業。御所に出入りする「御用蕎麦司」となった歴史があります。
ちなみにこの本家尾張屋には、江戸時代末期に[十三代目当主]が考案した「そば餅」をはじめ、十四代目当主考案の「蕎麦板」(蕎麦の麺打ちをするような技法で作られた蕎麦菓子)、十五代目考案のそば焙煎わらび餅、蕎麦ぼうる、十六代目当主が考案した蕎麦かりんとう…と、当主が自ら蕎麦菓子を作る伝統があります。
`;
code:AutoBracketter用test.js
const debugFlag = 1;
const f = (t) => debugFlag ? console.log(t) : "";
const testTxt2 = [蕎麦切]り
const reg = /(?<!\[)(\u4E00-\u9FFF\u3005-\u3007{2,}|\u30A0-\u30FF{2,}|\uFF61-\uFF9F{2,}|a-zA-Z{2,}|0-9{2,})(?!\])/g;
const reg2 = /(\u4E00-\u9FFF\u3005-\u3007{2,}|\u30A0-\u30FF{2,}|\uFF61-\uFF9F{2,}|a-zA-Z{2,}|0-9{2,})(?!\])/g;
const reg3 = /(?!.*\[)麦切/;
function matchtest(t) {
return t.match(reg3);
}
// とに囲われていない漢字カタカナ半角カタカナアルファベットのみを抽出したい…
f(matchtest(testTxt2));
code:AutoBracketter用最小テスト.js
const debugFlag = 1;
const f = (t) => debugFlag ? console.log(t) : "";
const input = 123456789の中に89は含まれます
const requireOutput = [123456789]の中に[89]は含まれます
const reg1 = /(?<!\[)(0-9{2,})(?!\])/g;
const reg3 = /(?!.*\[)麦切/;
function matchtest(txt) {
f(txt);
return t.match(reg1);
}
// とに囲われていない漢字カタカナ半角カタカナアルファベットのみを抽出したい…
console.log(matchtest(input) == requireOutput);