markdown AIで小説を連載する

# 前置き
もう本当、ビビりましたよ。

https://qiita.com/official-events/142fdd0d69ff6bb2d547

上のキャンペーンのタイトルを最初に見たとき、筆者は素直に「ええやん」と思いました。なぜなら、タイトルに
- **`markdown`**
- **`AI`**

という2つの言葉が含まれるからです。
筆者はいうなれば**パブロフの犬**のようなもので、これらの要素を含む存在に無条件で靡いてしまう。`markdown`という言葉が目に入るととりあえず安心感を覚えますし、`AI`については……場合によりますが。`markdown`の隣にいる場合は、コイツに任せてもいいかな、という気になれるのです。
そういうわけで……`markdown AI`というプロダクト名は大変気に入りました。何せ**安心感**というか、喉越しのさわやかさがあります。炭酸水というよりはいろはすに近い、そんな感じ。エコロジーに配慮したラベルを剥がしてリサイクルしつつ、プロダクトの詳細を見ていきましょう。

> # 概要
> 弊社開発のmarkdown AIを使用した感想や、独自の使い方についての説明を投稿してください。
> markdown AIとはQiitaでも採用されているMarkdownの記述をするだけで簡単にWebサイトを作成することができるwebアプリケーションです。
> 今後AIを用いてMarkdown方式での出力ができるようになるので、さまざまな表現が可能です。

AI機能は**未実装**らしいです。
そんなの……**ただのMarkdown**じゃねえかよッ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/b3e9f054-5330-d4d8-80dc-d371b282af82.png)
*2024年06月14日撮影*

ホラ！みんなただのMarkdownであることに気づいて **「使ってみる」記事しか書いてねえ**　そりゃそうでしょ！そもそもQiita自体がMarkdown投稿サイトなんだから　Markdown投稿サイトでMarkdown投稿サイトのレビューする構造になっちゃってる　使ってみる以外できないっすよそんなん
いやでも……**ちょっと待ってください**？

```html
<textarea style="width: 100%; background-color:#cceeee; color:#ff8833;font-size:50px;font-weight:bold;height:50vh;overflow-y:scroll;resize:none;">あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</textarea>
```

こう打ち込んだら……。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/20cadf42-3116-9e41-8a89-0c084032807f.png)

……あ、**HTMLタグは使える**んですね。
え、それじゃあ……。

```html
<textarea style="width: 100%; background-color:#cceeee; color:#ff8833;font-size:50px;font-weight:bold;height:50vh;overflow-y:scroll;resize:none;">あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。</textarea>

<button onClick="addCount()">+</button>

<script>
let count = 0
function addCount(){
  count += 1
  const target = document.querySelector("textarea")
  let output = String(count)
  if (count%15 == 0) {
    output = "FizzBuzz"
  } else if (count%5 == 0) {
    output = "Buzz"
  } else if (count%3 == 0) {
    output = "Fizz"
  }
  target.value += " " + output
}
</script>
```

![Popopon.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/73c74164-8d75-495e-2c46-b3e292091df5.gif)

あ、**`script`タグも使える**[^1]。なるほど
じゃあ……何でもできるか！
というわけで、何かすることにしました。

# 検討
先ほども述べた通り、筆者は**QiitaというMarkdown共有サービスでmarkdown AIというMarkdown共有サービスについて書く**という行為そのものに疑問を抱いています。
もちろんHTMLタグを使えるという点での優位性はありますが、だからといって全部HTMLだとこう……**もう自分でサイト作れよ**みたいになるところがありませんか？
1. あくまでmarkdownという**大枠**から逸脱しすぎない範囲で、
2. **補助**としてHTMLを使いつつ、
3. **Qiitaだとできないこと**をする

必要があります。
1や2はともかく、問題は3です。markdown AIのQiitaに対するアドバンテージであるHTMLタグの存在をベースに3を解決しようとすると、今度は1や2に抵触し始める……。今回筆者は技術的な側面ではなく、Qiitaの**目的**に目をつけました。
このサイトの[コミュニティガイドライン](https://help.qiita.com/ja/articles/qiita-community-guideline)にはこんな記述があります。
> Qiitaはエンジニアにとって再利用性・汎用性の高い他のユーザーにとっても役にたつ、学びのある情報が多く集まっている場であり続けたいと考えています。 Qiitaは記事を読むこと、記事を書くことを通して、読む側・書く側それぞれがお互いに関わり合いを持ち、情報をみんなで育てていくことで、今後同じようなことを学んだり、悩んだりするエンジニアが使う時間を減らし、エンジニアの成長や生産性をスピードアップさせることを目指します。

つまり……エンジニアにとって再利用性・汎用性の**低い**、他のユーザーにとっても**役にたたない**、学びの**ない**情報については、markdown AIで表現できて、Qiitaで表現できないコンテンツの一つといえます。これは**明確なアドバンテージ**といえるのではないでしょうか。
具体的には……。
小説、なんてどうでしょうか？

# 実装
## ひな形
とりあえずChatGPTに「適当な小説投稿サイト」のコードを書かせました。
<details><summary>折りたたみ。出力された内容をそのまま掲載</summary>

```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小説閲覧サイト</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@400;700&family=Roboto:wght@400;700&display=swap">
    <style>
        body {
            font-family: 'Noto Serif JP', serif;
            margin: 0;
            padding: 0;
            background: #f7f7f7;
            color: #333;
        }
        header {
            background: #333;
            color: #fff;
            padding: 10px 20px;
            text-align: center;
            font-family: 'Roboto', sans-serif;
        }
        nav {
            display: flex;
            justify-content: center;
            background: #444;
        }
        nav a {
            color: #fff;
            text-decoration: none;
            padding: 10px 20px;
            display: block;
        }
        nav a:hover {
            background: #555;
        }
        .container {
            max-width: 800px;
            margin: 20px auto;
            padding: 20px;
            background: #fff;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        .title {
            font-size: 2em;
            margin-bottom: 10px;
            font-weight: 700;
        }
        .author {
            font-size: 1.2em;
            color: #666;
            margin-bottom: 20px;
        }
        .content {
            line-height: 1.6;
            font-size: 1.1em;
        }
        .footer {
            text-align: center;
            padding: 10px 0;
            background: #333;
            color: #fff;
            position: fixed;
            width: 100%;
            bottom: 0;
        }
    </style>
</head>
<body>
    <header>
        <h1>小説閲覧サイト</h1>
    </header>
    <nav>
        <a href="#">ホーム</a>
        <a href="#">小説一覧</a>
        <a href="#">著者一覧</a>
        <a href="#">お問い合わせ</a>
    </nav>
    <div class="container">
        <div class="title">小説のタイトル</div>
        <div class="author">著者名</div>
        <div class="content">
            <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
            <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
            <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
        </div>
    </div>
    <div class="footer">
        &copy; 2024 小説閲覧サイト
    </div>
    <script>
        // JavaScriptコードをここに記述します
    </script>
</body>
</html>
```
</details>

「単一のhtmlファイルを出力しろ」という指示だったので`<!DOCTYPE html>`などの記述がそのまま入っており、直接markdown AIにコピペするといろいろ良くないです。とりあえずみたいな感じで成形したものがこちらです

<details><summary>折りたたみ</summary>

```html
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+JP:wght@400;700&family=Roboto:wght@400;700&display=swap">
<style>
    body {
        font-family: 'Noto Serif JP', serif;
        margin: 0;
        padding: 0;
        background: #f7f7f7;
        color: #333;
    }
    header {
        background: #333;
        color: #fff;
        padding: 10px 20px;
        text-align: center;
        font-family: 'Roboto', sans-serif;
    }
    nav {
        display: flex;
        justify-content: center;
        background: #444;
    }
    nav a {
        color: #fff;
        text-decoration: none;
        padding: 10px 20px;
        display: block;
    }
    nav a:hover {
        background: #555;
    }
    .container {
        max-width: 800px;
        margin: 20px auto;
        padding: 20px;
        background: #fff;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    }
    .title {
        font-size: 2em;
        margin-bottom: 10px;
        font-weight: 700;
    }
    .author {
        font-size: 1.2em;
        color: #666;
        margin-bottom: 20px;
    }
    .content {
        line-height: 1.6;
        font-size: 1.1em;
    }
    .footer {
        text-align: center;
        padding: 10px 0;
        background: #333;
        color: #fff;
        position: fixed;
        width: 100%;
        bottom: 0;
    }
</style>
<header>
    <h1>小説閲覧サイト</h1>
</header>
<nav>
    <a href="#">ホーム</a>
    <a href="#">小説一覧</a>
    <a href="#">著者一覧</a>
    <a href="#">お問い合わせ</a>
</nav>
<div class="container">
    <div class="title">小説のタイトル</div>
    <div class="author">著者名</div>
    <div class="content">
        <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
        <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
        <p>ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。ここに小説の内容が表示されます。</p>
    </div>
</div>
<div class="footer">
    &copy; 2024 小説閲覧サイト
</div>
```
</details>

これをコピペしてプレビューを押すと……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/a23597a5-884b-335f-4bcc-246bf72995b2.png)

こうなります。なかなかいいんじゃないでしょうか。

## 閑話休題：styleタグについて
ちなみに先ほどのコードをコピペしたところ、筆者の環境ではmarkdown AIのエディタのレイアウトが変わりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/fd6acf0b-b32c-ffad-c73e-8eecaaaee6f0.png)
👆これが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/5b6101cc-6c6c-6ad7-5ca3-8569f7e2cd93.png)
👆こうなった
恐らく書き換えた`style`タグの内容が（非表示にされているがDOM内にはある）プレビュー用要素の内部で実体化した結果、ページ全体のスタイルルールまでもが書き変わってしまった結果なのでしょう。
この仕様を悪用すると、例えば
```html
<style>
textarea {
  color: red !important;
}
</style>
```
と書き込むだけでこうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/10b9ec56-c839-546f-616f-e04d18b83e16.png)
**自分に書き込まれているテキストによって外観を左右されるテキストエディタ**というのはなんだか円城塔あたりのSF小説に出てきそうな感じがして、正直かなりエキサイティングです。
普通に直した方がいいと思いました

## 続き
とりあえず小説投稿サイトっぽい見た目ができましたが、このままだと**Markdown感**がありません。
例えば現状、小説の**タイトル**は`title`というクラスを指定された`div`タグによって表示されています。しかしMarkdownを使っていることを考えると、本来ここは`# タイトル`と書いてh1タグで表示するのがあるべき姿ではないでしょうか？
また、`**強調**`あたりの記法についても小説の執筆に使えると嬉しいでしょう。
markdown AIにおけるプレビューは`text-preview`クラスをつけられたdivタグの内部にDOMとして展開されます。また例えば`# heading`と書けば`<h1>heading</h1>`を吐きますし、`**bold**`なら`<strong>bold<strong>`が出ます。けっこう**素直な実装**をしているようですね。
これを踏まえ、styleタグにこんな表記を追加します。
```css
.text-preview h1 { /*.titleを置換*/
        font-size: 2em;
        margin-bottom: 10px;
        font-weight: 700;
}
.text-preview h2 { /*.authorを置換*/
        font-size: 1.2em;
        color: #666;
        margin-bottom: 20px;
}
.text-preview strong {
        font-weight:normal;
        text-emphasis: filled sesame;
}
```

あと今気づいたんですが、どうやらmarkdown AIにおけるMarkdown記法は**それより前にhtmlタグが使用されていない**場合しか解釈されないようです。なのでナビゲーションバーとヘッダーは泣く泣く消去し、`style`タグと`link`タグは末尾に移動させました。
この状態で例えば、

```markdown
# 小説のタイトル
## 著者名
「こんにちは」
　**彼女**は言った。
```

と先頭に入力した場合、こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/20347d5b-ab3a-5de9-8cd6-ff4851cd6771.png)
ひとまずいい感じではないでしょうか。`**強調**`記法については**傍点**に割り振ることで、小説ナイズされてます感を出しています。
とりあえずガワはできたので、あとは小説を書き込むだけです。

## 小説
**偶然にも**筆者の趣味が小説を書くことだったので、以前書いたものを適当に流し込んでみました。こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812929/6abb7a5d-06f2-50bb-b49a-deff0d6266b9.png)
すげえ、ちゃんと読める……。
普通にHTMLタグが描画されているだけのはずなのですが、なんだか、謎の感動があります。
……この感動はもう、完全に **Qiitaでは出せないもの**ですよ。逆に、出したらヤバい。何ならこの完成したサイトへのリンクをQiitaに貼ることすらはばかられますもん。そのラインにある。
ありがとう……。
markdown AIよ。

# まとめ
- markdown AIの素朴かつ少し危うい立ち姿は言い換えれば可能性に満ち溢れた児童を目にしているかのようで、そのポテンシャルはとても高いと言える
- なので、**早くAI機能を実装してほしい**


[^1]: ちなみに`script`タグの中身はコード保存後のプレビュー画面では走らなかったのですが、Publishしたうえで発行されたURLに飛んだら実行されました。罠