LoginSignup
291
171

More than 1 year has passed since last update.

Chrome拡張作ったら異世界転生した件

Last updated at Posted at 2021-06-20

詠唱

配列(文字列)からランダムに要素を取り出すコードを書くじゃろ

// ランダムに要素を取り出す関数
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の拡張機能のページを開いてデベロッパーモードを有効化
「パッケージ化されていない拡張機能を読み込む」からフォルダを選択して完了じゃ!

スクリーンショット 2021-06-21 10.21.02.png

結果

スクリーンショット 2021-06-21 10.22.33.png

右上のパズルのピースみたいなアイコンから「異世界拡張」をクリックすればいつでも異世界
楽しい!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌

参考

291
171
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
291
171