grokに生成させた。
Last active
February 27, 2025 09:59
-
-
Save podhmo/73b53034f154f1af4c023af9386e7418 to your computer and use it in GitHub Desktop.
スマホのアウトラインエディタで雑な文章が書きたい
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 行を表す型定義 | |
| interface Line { | |
| content: string; | |
| indent: number; // インデントレベル(スペースの数) | |
| isBullet: boolean; // 箇条書きかどうか | |
| isText: boolean; // テキストとして扱うかどうか(@付きなど) | |
| starLevel: number; // * の数(箇条書きのレベル) | |
| } | |
| // Markdown を変換するメイン関数 | |
| export function convertMarkdown(input: string): string { | |
| // 入力を改行で分割し、各行を解析 | |
| const lines = parseLines(input); | |
| let output = ""; | |
| let currentTopLevel = ""; | |
| for (let i = 0; i < lines.length; i++) { | |
| const line = lines[i]; | |
| // インデントなしで箇条書きでない場合、トップレベルのセクションとして扱う | |
| if (line.indent === 0 && !line.isBullet) { | |
| currentTopLevel = line.content; | |
| output += `## ${currentTopLevel}\n\n`; | |
| continue; | |
| } | |
| // 空行の場合、単純に改行を追加 | |
| if (line.content.trim() === "" && line.isBullet) { | |
| output += "\n"; | |
| continue; | |
| } | |
| // @付きまたはテキストとして扱う場合 | |
| if (line.isText) { | |
| output += `${line.content}\n\n`; | |
| continue; | |
| } | |
| // 箇条書きの処理 | |
| if (line.isBullet) { | |
| const group = collectGroup(lines, i); // 同じトップレベルの箇条書きを収集 | |
| const maxDepth = Math.max(...group.map((l) => l.indent)); // グループ内の最大深度 | |
| group.forEach((item, idx) => { | |
| if (item.starLevel > 0) { | |
| // * を使った箇条書きの場合 | |
| const bulletIndent = " ".repeat(item.starLevel - 1); | |
| output += `${bulletIndent}- ${item.content}\n`; | |
| } else if (item.indent === maxDepth || item.isText) { | |
| // 最大深度またはテキスト扱いの場合、テキストとして出力 | |
| output += `${item.content}\n`; | |
| if (idx < group.length - 1) output += "\n"; | |
| } else { | |
| // それ以外はセクションとして出力 | |
| const level = Math.min(3 + item.indent, 6); // h3 以降を使用 | |
| output += `${"#".repeat(level)} ${item.content}\n\n`; | |
| } | |
| }); | |
| i += group.length - 1; // グループ分スキップ | |
| } | |
| } | |
| return output.trim(); | |
| } | |
| // 入力を解析して Line オブジェクトの配列に変換 | |
| function parseLines(input: string): Line[] { | |
| return input.split("\n").map((line) => { | |
| const trimmed = line.trimStart(); | |
| const indent = (line.length - trimmed.length) / 2; // 2スペースを1インデントとみなす | |
| const isBullet = trimmed.startsWith("-"); | |
| let content = trimmed.replace(/^-/, "").trim(); | |
| let isText = false; | |
| let starLevel = 0; | |
| if (content.startsWith("@")) { | |
| isText = true; | |
| content = content.slice(1).trim(); | |
| } else if (content.startsWith("*")) { | |
| const match = content.match(/^\*+/); | |
| starLevel = match ? match[0].length : 0; | |
| content = content.slice(starLevel).trim(); | |
| } | |
| return { content, indent, isBullet, isText, starLevel }; | |
| }); | |
| } | |
| // 同じトップレベルの箇条書きをグループ化 | |
| function collectGroup(lines: Line[], startIdx: number): Line[] { | |
| const group: Line[] = []; | |
| const startIndent = lines[startIdx].indent; | |
| for (let i = startIdx; i < lines.length; i++) { | |
| const line = lines[i]; | |
| if (!line.isBullet || line.indent < startIndent) break; | |
| if ( | |
| line.indent === startIndent && group.length > 0 && !line.isText && | |
| line.starLevel === 0 | |
| ) break; | |
| group.push(line); | |
| } | |
| return group; | |
| } | |
| // テスト用の入力 | |
| const input1 = ` | |
| aaa | |
| - xxx | |
| - yyy | |
| - zzz | |
| `; | |
| const input2 = ` | |
| aaa | |
| - @ bbb | |
| - xxx | |
| - iii | |
| - jjj | |
| - kkk | |
| - yyy | |
| - zzz | |
| `; | |
| const input3 = ` | |
| aaa | |
| - @ bbb | |
| - xxx | |
| - iii | |
| - | |
| - jjj | |
| - | |
| - kkk | |
| - yyy | |
| - * 111 | |
| - ** 222 | |
| - ** 333 | |
| - * 111 | |
| - @ zzz | |
| `; | |
| // テスト実行 | |
| console.log("Test 1:"); | |
| console.log(convertMarkdown(input1.trim())); | |
| console.log("\nTest 2:"); | |
| console.log(convertMarkdown(input2.trim())); | |
| console.log("\nTest 3:"); | |
| console.log(convertMarkdown(input3.trim())); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // テストコード | |
| import { assertEquals } from "jsr:@std/assert"; | |
| import { convertMarkdown } from "./main.ts"; | |
| Deno.test("基本的な箇条書きの変換", () => { | |
| const input = ` | |
| aaa | |
| - xxx | |
| - yyy | |
| - zzz | |
| `; | |
| const expected = ` | |
| ## aaa | |
| xxx | |
| yyy | |
| zzz | |
| `.trim(); | |
| const result = convertMarkdown(input); | |
| assertEquals(result, expected); | |
| }); | |
| Deno.test("ネストした箇条書きの変換", () => { | |
| const input = ` | |
| aaa | |
| - @ bbb | |
| - xxx | |
| - iii | |
| - jjj | |
| - kkk | |
| - yyy | |
| - zzz | |
| `; | |
| const expected = ` | |
| ## aaa | |
| bbb | |
| ### xxx | |
| iii | |
| jjj | |
| kkk | |
| ## yyy | |
| ## zzz | |
| `.trim(); | |
| const result = convertMarkdown(input); | |
| assertEquals(result, expected); | |
| }); | |
| Deno.test("空白行と * を使った箇条書きの変換", () => { | |
| const input = ` | |
| aaa | |
| - @ bbb | |
| - xxx | |
| - iii | |
| - | |
| - jjj | |
| - | |
| - kkk | |
| - yyy | |
| - * 111 | |
| - ** 222 | |
| - ** 333 | |
| - * 111 | |
| - @ zzz | |
| `; | |
| const expected = ` | |
| ## aaa | |
| bbb | |
| ### xxx | |
| iii | |
| jjj | |
| kkk | |
| ## yyy | |
| - 111 | |
| - 222 | |
| - 333 | |
| - 111 | |
| zzz | |
| `.trim(); | |
| const result = convertMarkdown(input); | |
| assertEquals(result, expected); | |
| }); |
Author
Author
再度変更させた
Author
普通に壊れてるね。。
Author
書き換え前のアプローチの方が好きだな。
Author
真面目に扱うことにするか
Author
こういう入力で渡したい
タイトル
- @ ここに文章を書いてみる
- ここは章タイトル
- @ ここは章の文章
- ここは節タイトル
- ここは節の文章
- ここも同様
- 節2のタイトル
- これは節2の文章
- @ これは実質節2の文章
- @ ここも実質節2の文章
- ここは章2のタイトル
- ここは章2の文章
- * 箇条書き
- ** ネストしたもの
- ** ネストしたもの2
- * 箇条書き2
- ここも章2の文章
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
何かしら入力しやすい文字を先頭に入れて挿入するのが良さそう? > なんか文章のところ