HTML+css+TypeScript で構造化した箇条書きに適切な見出しをつけるツールを作ってみた

Posted on 2024年05月04日 (土) in 自作ツール

アイキャッチ

目次

はじめに

最近 Raact を勉強するために、HTML・css・Typescript の勉強を始めたのですが、それらの使い方を把握するために試しにツールを作りました。

このツールにした理由は、私はメモのとき構造化した箇条書きですることが多く、これだとあとから見返しにくいため、構造を維持したまま見返すためのツールがちょうど欲しかったためです。

そのため汎用性を一切捨てて自分のためのツールとして作っています。

一応コードを公開しますが、厳密にテストをしていないため不具合がある可能性がありますので、使用の際にはご注意ください。

見た目

ツールの見た目

コード

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>箇条書き変換ツール</title>
    <link href="style.css" rel="stylesheet" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
  </head>

  <body>
    <h1>箇条書き変換ツール</h1>
    <textarea
      id="input"
      placeholder="ここにテキストを入力してください"
    ></textarea>
    <button id="convert">変換</button>
    <textarea
      id="output"
      placeholder="ここに変換結果が表示されます"
      readonly
    ></textarea>
    <footer></footer>
    <script src="script.js"></script>
  </body>
</html>

css

textarea {
  width: 100%; /* 横幅 */
  height: 200px; /* 高さ */
  display: block;
}

button {
  text-align: center;
  display: block;
  margin: 0 auto;
}

TypeScript

let inputTxt = document.getElementById("input") as HTMLInputElement;
let btn = document.getElementById("convert") as HTMLButtonElement;
let outputTxt = document.getElementById("output") as HTMLInputElement;

function replaceLeadingSpacesWithHash(input: string, txt: string): string {
  const leadingSpaces = input.match(/^\s*/);
  if (leadingSpaces) {
    const numSpaces = leadingSpaces[0].length;
    if (numSpaces > 0) {
      let replacement = "";
      for (let i = 0; i < Math.ceil(numSpaces / 2); i++) {
        replacement += txt;
      }
      return input.replace(/^\s*/, replacement);
    }
  }
  return input; // 空白がない場合やエラーの場合はそのまま返す
}

function countLeadingSpaces(input: string): number {
  const leadingSpaces = input.match(/^\s*/);
  if (leadingSpaces) {
    return leadingSpaces[0].length;
  } else {
    return 0; // No leading spaces
  }
}

function get_input() {
  let content: string = inputTxt.value;
  let arrayFromString = content.split("\n");
  let array: string[] = [];
  for (let i = 0; i < arrayFromString.length - 1; i++) {
    if (
      countLeadingSpaces(arrayFromString[i + 1]) >
      countLeadingSpaces(arrayFromString[i])
    ) {
      array[i] = replaceLeadingSpacesWithHash(
        arrayFromString[i].replace("- ", "# "),
        "#"
      );
    } else if (
      countLeadingSpaces(arrayFromString[i - 1]) >
      countLeadingSpaces(arrayFromString[i])
    ) {
      array[i] = replaceLeadingSpacesWithHash(
        arrayFromString[i].replace("- ", "# "),
        "#"
      );
    } else if (
      array[i - 1].slice(0, 1) == "#" &&
      countLeadingSpaces(arrayFromString[i]) ==
        countLeadingSpaces(arrayFromString[i - 1])
    ) {
      array[i] = replaceLeadingSpacesWithHash(
        arrayFromString[i].replace("- ", "# "),
        "#"
      );
    } else {
      array[i] = replaceLeadingSpacesWithHash(arrayFromString[i], "");
    }
  }
  content = array.join("\n");
  outputTxt.value = content;
}

btn.addEventListener("click", get_input, false);
JavaScript
  
var inputTxt = document.getElementById("input");
var btn = document.getElementById("convert");
var outputTxt = document.getElementById("output");
function replaceLeadingSpacesWithHash(input, txt) {
    var leadingSpaces = input.match(/^\s*/);
    if (leadingSpaces) {
        var numSpaces = leadingSpaces[0].length;
        if (numSpaces > 0) {
            var replacement = "";
            for (var i = 0; i < Math.ceil(numSpaces / 2); i++) {
                replacement += txt;
            }
            return input.replace(/^\s*/, replacement);
        }
    }
    return input; // 空白がない場合やエラーの場合はそのまま返す
}
function countLeadingSpaces(input) {
    var leadingSpaces = input.match(/^\s*/);
    if (leadingSpaces) {
        return leadingSpaces[0].length;
    }
    else {
        return 0; // No leading spaces
    }
}
function get_input() {
    var content = inputTxt.value;
    var arrayFromString = content.split("\n");
    var array = [];
    for (var i = 0; i < arrayFromString.length - 1; i++) {
        if (countLeadingSpaces(arrayFromString[i + 1]) >
            countLeadingSpaces(arrayFromString[i])) {
            array[i] = replaceLeadingSpacesWithHash(arrayFromString[i].replace("- ", "# "), "#");
        }
        else if (countLeadingSpaces(arrayFromString[i - 1]) >
            countLeadingSpaces(arrayFromString[i])) {
            array[i] = replaceLeadingSpacesWithHash(arrayFromString[i].replace("- ", "# "), "#");
        }
        else if (array[i - 1].slice(0, 1) == "#" &&
            countLeadingSpaces(arrayFromString[i]) ==
                countLeadingSpaces(arrayFromString[i - 1])) {
            array[i] = replaceLeadingSpacesWithHash(arrayFromString[i].replace("- ", "# "), "#");
        }
        else {
            array[i] = replaceLeadingSpacesWithHash(arrayFromString[i], "");
        }
    }
    content = array.join("\n");
    outputTxt.value = content;
}
btn.addEventListener("click", get_input, false);

感想

TypeScript を初めて触ったためまだ不慣れで、結構 chatGPT に頼ってしまいましたが、なんとか最低限の書き方を理解できた気がしました。

今回はのツールは実際に自分で使いながらブラッシュアップし、Typescript のコードを改良したり、Python として YAk のツールに追加して活用していこうと思います。