詠唱
配列(文字列)からランダムに要素を取り出すコードを書くじゃろ
// ランダムに要素を取り出す関数
const randomPick = (items) => {
const index = Math.floor(items.length * Math.random());
return items[index];
};
randomPick("123456"); // 1〜6のどれか
文字列の範囲を展開するコードを書くじゃろ
// 文字列の範囲を展開する関数
const expandCharRange = (str) =>
str.replace(/.-./g, (range = 'a-z') => {
// ハイフンを挟んだ文字列を全て置換
const first = range.codePointAt(0); // 1文字目の文字コード
const last = range.codePointAt(2); // 2文字目の文字コード
const length = last - first + 1; // 文字数
const codePoints = [...Array(length)].map((_, i) => first + i); // 全ての文字コード
return String.fromCodePoint(...codePoints); // 文字列に変換
});
expandCharRange("a-z0-9"); // "abcdefghijklmnopqrstuvwxyz0123456789"
ルーン文字をランダムで生成して...
// ルーン文字を生成する関数
const runes = expandCharRange('ᚠ-ᛪᛮ-ᛰᛱ-ᛳᛴ-ᛸ');
const randomRune = () => randomPick(runes);
[...Array(3)].map(randomRune) // ["ᛴ", "ᚶ", "ᚳ"]
レイアウトが崩れたりしないようにテキストノードだけ置換するコードを書くんじゃ
// 指定要素以下の全ノードを取得する関数
const allNodes = (root = document.body) => [root, ...[...root.childNodes].flatMap(allNodes)];
// 無害そうなテキストノードだけ取得
const allVisibleTextNodes = allNodes()
.filter((node) => node.nodeType === Node.TEXT_NODE) // テキストノードだけ抽出
.filter((node) => !/script|style/i.test(node.parentElement.tagName)) // 親がヤバいヤツは除外
.filter((node) => node.nodeValue.trim()); // 空っぽなヤツは除外
// 空白以外は全てルーン文字に置換
allVisibleTextNodes.forEach((node) => {
node.nodeValue = node.nodeValue.replace(/\S/g, randomRune);
});
Chrome拡張を作成 (必要なファイルは2つだけ)
2つのファイルを作って適当なフォルダにぶち込む
manifest.json
{
"manifest_version": 3,
"version": "0.1.0",
"name": "異世界拡張",
"description": "Chrome拡張作ったら異世界転生した件",
"background": {
"service_worker": "isekai.js"
},
"action": {
"default_title": "転生する"
},
"permissions": ["activeTab", "scripting"]
}
isekai.js
'use strict';
// 上記のまとめ関数 (若干変えた)
function tensei() {
// ランダムに要素を取り出す関数
const randomPick = (items) => {
const index = Math.floor(items.length * Math.random());
return items[index];
};
// 文字列の範囲を展開する関数
const expandCharRange = (str) =>
str.replace(/.-./g, (range = 'a-z') => {
// ハイフンを挟んだ文字列を全て置換
const first = range.codePointAt(0); // 1文字目の文字コード
const last = range.codePointAt(2); // 2文字目の文字コード
const length = last - first + 1; // 文字数
const codePoints = [...Array(length)].map((_, i) => first + i); // 全ての文字コード
return String.fromCodePoint(...codePoints); // 文字列に変換
});
// ルーン文字を生成する関数
const runes = expandCharRange('ᚠ-ᛪᛮ-ᛰᛱ-ᛳᛴ-ᛸ');
const randomRune = () => randomPick(runes);
// 空白・記号・絵文字・数字・ギリシャ文字以外をルーン文字に置換する関数
const conv = (str) => str.replace(/[^\p{White_Space}\p{Symbol}\p{Punctuation}\p{Emoji}\p{Number}\p{sc=Greek}]/gu, randomRune);
// 指定要素以下の全ノードを取得する関数
const allNodes = (root = document.body) => [root, ...[...root.childNodes].flatMap(allNodes)];
// 無害そうなテキストノードだけ取得
const allVisibleTextNodes = allNodes()
.filter((node) => node.nodeType === Node.TEXT_NODE) // テキストノードだけ抽出
.filter((node) => !/script|style/i.test(node.parentElement.tagName)) // 親がヤバいヤツは除外
.filter((node) => node.nodeValue.trim()); // 空っぽなヤツは除外
// ルーン・オリジナルを切り替え
allVisibleTextNodes.forEach((node) => {
if (node.original) {
[node.original, node.nodeValue] = ['', node.original];
} else {
[node.original, node.nodeValue] = [node.nodeValue, conv(node.nodeValue)];
}
});
}
// 拡張のアイコンを押すたびに実行
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: tensei
});
});
Chromeの拡張機能のページを開いてデベロッパーモードを有効化
「パッケージ化されていない拡張機能を読み込む」からフォルダを選択して完了じゃ!
結果
右上のパズルのピースみたいなアイコンから「異世界拡張」をクリックすればいつでも異世界
楽しい!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌