簡単なwebアプリ作成、もはやClaudeに全部やってもらえる説 #初心者向け - Qiita

こんにちは!みっきーです!
この記事を見つけてくださりありがとうございます。

今回はまたClaudeを使ってwebアプリを作っていこうと思います。いや、Claudeにwebアプリを作ってもらいます。

前回、Pythonで作った「モンハンのクエスト同行メンバーをランダムで決めるプログラム」をClaudeを使ってwebアプリ化させることに成功しました。

この時は元となるPythonのプログラムがありましたが、今回は要件定義だけやってあとはClaudeに丸投げしてみます。これで本当にwebアプリが作れるのか検証していきます。

前まで大学の授業等のレポート課題をやる際によく使っていた「文字数をカウントしてくれるサイト」がありました…でもいつの間にか閉鎖されてました(涙)
広告もなくシンプルな設計ですごく使いやすかったのに残念。これのほかにも文字数をカウントしてくれるサイトはありますが、広告(特にアニメーション付きの広告)が厄介で作業の邪魔になっていました。
前回のwebアプリ作成でClaudeのすごさを知ったので、「もうClaudeに作ってもらえばいいじゃん」と思い立ちました。それではやっていきましょう。

image.png
試してみたい方はこちら

まずは要件定義を行います。
使用したプロンプトはこちら

文字数カウントwebアプリを作りたいです。 
以下に要件を指定するので作成手順を教えてください。 
・大きなテキストボックス 
・テキストボックス内にはフィードフォワードで「カウントしたい文字列を入力」と表示 
・文字数はリアルタイムでカウント 
・カウントする内容は「文字数」 「改行を除いた文字数」 「改行、空白を除いた文字数」 「行数」 「バイト数」  
・カウントする文字列は日本語と英語を想定 
・英語の場合のみ単語数をカウント 
・テキストボックス内の文字列を一括で削除する「リセットボタン」の実装
編集
・Google Apps Scriptを使用

前回同様、GASでのデプロイ手順、htmlファイル、gsファイルを出力してくれました。
出力されたhtmlファイル、gsファイルを以下に提示します。

HTML



  
     target="_top">
     charset="UTF-8">
    </span>文字数カウンター<span class="nt"/>
    <span class="nt"/>
      <span class="nt">body</span> <span class="p">{</span>
        <span class="nl">font-family</span><span class="p">:</span> <span class="s2">'Helvetica Neue'</span><span class="p">,</span> <span class="n">Arial</span><span class="p">,</span> <span class="s2">'Hiragino Kaku Gothic ProN'</span><span class="p">,</span> <span class="s2">'Hiragino Sans'</span><span class="p">,</span> <span class="n">Meiryo</span><span class="p">,</span> <span class="nb">sans-serif</span><span class="p">;</span>
        <span class="nl">max-width</span><span class="p">:</span> <span class="m">800px</span><span class="p">;</span>
        <span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;</span>
        <span class="nl">padding</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
        <span class="nl">background-color</span><span class="p">:</span> <span class="m">#f5f5f5</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nt">h1</span> <span class="p">{</span>
        <span class="nl">color</span><span class="p">:</span> <span class="m">#333</span><span class="p">;</span>
        <span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
        <span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nc">.container</span> <span class="p">{</span>
        <span class="nl">background-color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
        <span class="nl">border-radius</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
        <span class="nl">padding</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
        <span class="nl">box-shadow</span><span class="p">:</span> <span class="m">0</span> <span class="m">2px</span> <span class="m">10px</span> <span class="n">rgba</span><span class="p">(</span><span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0.1</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="nc">.text-area-container</span> <span class="p">{</span>
        <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
        <span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nt">textarea</span> <span class="p">{</span>
        <span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
        <span class="nl">height</span><span class="p">:</span> <span class="m">300px</span><span class="p">;</span>
        <span class="nl">padding</span><span class="p">:</span> <span class="m">15px</span><span class="p">;</span>
        <span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="m">#ddd</span><span class="p">;</span>
        <span class="nl">border-radius</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span>
        <span class="nl">resize</span><span class="p">:</span> <span class="n">vertical</span><span class="p">;</span>
        <span class="nl">font-size</span><span class="p">:</span> <span class="m">16px</span><span class="p">;</span>
        <span class="nl">box-sizing</span><span class="p">:</span> <span class="n">border-box</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nt">textarea</span><span class="nd">:focus</span> <span class="p">{</span>
        <span class="nl">outline</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
        <span class="nl">border-color</span><span class="p">:</span> <span class="m">#4A90E2</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nc">.placeholder</span> <span class="p">{</span>
        <span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
        <span class="nl">top</span><span class="p">:</span> <span class="m">15px</span><span class="p">;</span>
        <span class="nl">left</span><span class="p">:</span> <span class="m">15px</span><span class="p">;</span>
        <span class="nl">color</span><span class="p">:</span> <span class="m">#aaa</span><span class="p">;</span>
        <span class="nl">pointer-events</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
        <span class="nl">transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">0.2s</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nc">.counter-container</span> <span class="p">{</span>
        <span class="nl">display</span><span class="p">:</span> <span class="n">grid</span><span class="p">;</span>
        <span class="py">grid-template-columns</span><span class="p">:</span> <span class="nb">repeat</span><span class="p">(</span><span class="m">3</span><span class="p">,</span> <span class="m">1</span><span class="n">fr</span><span class="p">);</span>
        <span class="py">gap</span><span class="p">:</span> <span class="m">15px</span><span class="p">;</span>
        <span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nc">.counter</span> <span class="p">{</span>
        <span class="nl">background-color</span><span class="p">:</span> <span class="m">#f9f9f9</span><span class="p">;</span>
        <span class="nl">padding</span><span class="p">:</span> <span class="m">15px</span><span class="p">;</span>
        <span class="nl">border-radius</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span>
        <span class="nl">box-shadow</span><span class="p">:</span> <span class="m">0</span> <span class="m">1px</span> <span class="m">3px</span> <span class="n">rgba</span><span class="p">(</span><span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0.1</span><span class="p">);</span>
      <span class="p">}</span>
      <span class="nc">.counter</span> <span class="nt">h3</span> <span class="p">{</span>
        <span class="nl">margin-top</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
        <span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
        <span class="nl">color</span><span class="p">:</span> <span class="m">#333</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nc">.counter</span> <span class="nt">p</span> <span class="p">{</span>
        <span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
        <span class="nl">font-size</span><span class="p">:</span> <span class="m">24px</span><span class="p">;</span>
        <span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
        <span class="nl">color</span><span class="p">:</span> <span class="m">#4A90E2</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nt">button</span> <span class="p">{</span>
        <span class="nl">background-color</span><span class="p">:</span> <span class="m">#4A90E2</span><span class="p">;</span>
        <span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
        <span class="nl">border</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
        <span class="nl">padding</span><span class="p">:</span> <span class="m">10px</span> <span class="m">20px</span><span class="p">;</span>
        <span class="nl">border-radius</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span>
        <span class="nl">font-size</span><span class="p">:</span> <span class="m">16px</span><span class="p">;</span>
        <span class="nl">cursor</span><span class="p">:</span> <span class="nb">pointer</span><span class="p">;</span>
        <span class="nl">transition</span><span class="p">:</span> <span class="n">background-color</span> <span class="m">0.3s</span><span class="p">;</span>
      <span class="p">}</span>
      <span class="nt">button</span><span class="nd">:hover</span> <span class="p">{</span>
        <span class="nl">background-color</span><span class="p">:</span> <span class="m">#3A80D2</span><span class="p">;</span>
      <span class="p">}</span>
    <span class="nt"/>
  <span class="nt"/>
  <span class="nt"/>
    <span class="nt"><div> <span class="na">class=</span><span class="s">"container"</span><span class="nt">></span>
      <span class="nt"/>文字数カウンター<span class="nt"/>
      
      <span class="nt"><div> <span class="na">class=</span><span class="s">"text-area-container"</span><span class="nt">></span>
        <span class="nt"><textarea> <span class="na">id=</span><span class="s">"textInput"</span> <span class="na">oninput=</span><span class="s">"countText()"</span><span class="nt">></span></textarea></span>
        <span class="nt"><p> <span class="na">id=</span><span class="s">"placeholder"</span> <span class="na">class=</span><span class="s">"placeholder"</span><span class="nt">></span>カウントしたい文字列を入力<span class="nt"/></p></span>
      <span class="nt"/></div></span>
      
      <span class="nt"><div> <span class="na">class=</span><span class="s">"counter-container"</span><span class="nt">></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>文字数<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"charCount"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>改行を除いた文字数<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"charNoLineBreaks"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>改行・空白を除いた文字数<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"charNoSpaces"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>行数<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"lineCount"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>バイト数<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"byteCount"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
        <span class="nt"><div> <span class="na">class=</span><span class="s">"counter"</span><span class="nt">></span>
          <span class="nt"><h3/></span>単語数 (英語のみ)<span class="nt"/>
          <span class="nt"><p> <span class="na">id=</span><span class="s">"wordCount"</span><span class="nt">></span>0<span class="nt"/></p></span>
        <span class="nt"/></div></span>
      <span class="nt"/></div></span>
      
      <span class="nt"><button> <span class="na">id=</span><span class="s">"resetButton"</span> <span class="na">onclick=</span><span class="s">"resetText()"</span><span class="nt">></span>リセット<span class="nt"/></button></span>
    <span class="nt"/></div></span>

    <span class="nt"><script/></span>
      <span class="c1">// プレースホルダーの表示/非表示を管理</span>
      <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">textInput</span><span class="dl">'</span><span class="p">).</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">focus</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">placeholder</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">opacity</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">0</span><span class="dl">'</span><span class="p">;</span>
      <span class="p">});</span>
      
      <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">textInput</span><span class="dl">'</span><span class="p">).</span><span class="nf">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">blur</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
        <span class="k">if </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span> <span class="o">===</span> <span class="dl">''</span><span class="p">)</span> <span class="p">{</span>
          <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">placeholder</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">opacity</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">});</span>
      
      <span class="c1">// テキストカウント機能</span>
      <span class="kd">function</span> <span class="nf">countText</span><span class="p">()</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">text</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">textInput</span><span class="dl">'</span><span class="p">).</span><span class="nx">value</span><span class="p">;</span>
        
        <span class="c1">// 文字数 (全体)</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">charCount</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
        
        <span class="c1">// 改行を除いた文字数</span>
        <span class="kd">const</span> <span class="nx">noLineBreaks</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">n</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">);</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">charNoLineBreaks</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">noLineBreaks</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
        
        <span class="c1">// 改行と空白を除いた文字数</span>
        <span class="kd">const</span> <span class="nx">noSpaces</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nf">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">[ns]</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">);</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">charNoSpaces</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">noSpaces</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
        
        <span class="c1">// 行数</span>
        <span class="kd">const</span> <span class="nx">lines</span> <span class="o">=</span> <span class="nx">text</span> <span class="o">===</span> <span class="dl">''</span> <span class="p">?</span> <span class="mi">0</span> <span class="p">:</span> <span class="nx">text</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="dl">'</span><span class="se">n</span><span class="dl">'</span><span class="p">).</span><span class="nx">length</span><span class="p">;</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">lineCount</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">lines</span><span class="p">;</span>
        
        <span class="c1">// バイト数 (UTF-8エンコーディングを想定)</span>
        <span class="kd">let</span> <span class="nx">byteCount</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
        <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"> <span class="nx">text</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">const</span> <span class="nx">c</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nf">charCodeAt</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
          <span class="k">if</span> <span class="p">(</span><span class="nx">c</span> <span class="o">>=</span> <span class="mh">0x0000</span> <span class="o">&&</span> <span class="nx">c</span> <span class="o"> <span class="mh">0x007F</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">byteCount</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
          <span class="p">}</span> <span class="k">else</span> <span class="k">if </span><span class="p">(</span><span class="nx">c</span> <span class="o">></span> <span class="mh">0x07FF</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">byteCount</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span>
          <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nx">byteCount</span> <span class="o">+=</span> <span class="mi">2</span><span class="p">;</span>
          <span class="p">}</span>
        <span class="p">}</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">byteCount</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">byteCount</span><span class="p">;</span>
        
        <span class="c1">// 単語数 (英語のみ)</span>
        <span class="c1">// 日本語が含まれない場合のみカウント</span>
        <span class="kd">const</span> <span class="nx">hasJapanese</span> <span class="o">=</span> <span class="sr">/</span><span class="se">[u</span><span class="sr">3000-</span><span class="se">u</span><span class="sr">303f</span><span class="se">u</span><span class="sr">3040-</span><span class="se">u</span><span class="sr">309f</span><span class="se">u</span><span class="sr">30a0-</span><span class="se">u</span><span class="sr">30ff</span><span class="se">u</span><span class="sr">ff00-</span><span class="se">u</span><span class="sr">ff9f</span><span class="se">u</span><span class="sr">4e00-</span><span class="se">u</span><span class="sr">9faf</span><span class="se">u</span><span class="sr">3400-</span><span class="se">u</span><span class="sr">4dbf</span><span class="se">]</span><span class="sr">/</span><span class="p">.</span><span class="nf">test</span><span class="p">(</span><span class="nx">text</span><span class="p">);</span>
        <span class="k">if </span><span class="p">(</span><span class="o">!</span><span class="nx">hasJapanese</span> <span class="o">&&</span> <span class="nx">text</span><span class="p">.</span><span class="nf">trim</span><span class="p">()</span> <span class="o">!==</span> <span class="dl">''</span><span class="p">)</span> <span class="p">{</span>
          <span class="kd">const</span> <span class="nx">words</span> <span class="o">=</span> <span class="nx">text</span><span class="p">.</span><span class="nf">trim</span><span class="p">().</span><span class="nf">split</span><span class="p">(</span><span class="sr">/</span><span class="se">s</span><span class="sr">+/</span><span class="p">).</span><span class="nx">length</span><span class="p">;</span>
          <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">wordCount</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">words</span><span class="p">;</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
          <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">wordCount</span><span class="dl">'</span><span class="p">).</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">hasJapanese</span> <span class="p">?</span> <span class="dl">'</span><span class="s1">日本語テキスト</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">0</span><span class="dl">'</span><span class="p">;</span>
        <span class="p">}</span>
      <span class="p">}</span>
      
      <span class="c1">// リセット機能</span>
      <span class="kd">function</span> <span class="nf">resetText</span><span class="p">()</span> <span class="p">{</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">textInput</span><span class="dl">'</span><span class="p">).</span><span class="nx">value</span> <span class="o">=</span> <span class="dl">''</span><span class="p">;</span>
        <span class="nb">document</span><span class="p">.</span><span class="nf">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">placeholder</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">opacity</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">;</span>
        <span class="nf">countText</span><span class="p">();</span>
      <span class="p">}</span>
    <span class="nt"/>
  <span class="nt"/>
<span class="nt"/>
</span></span></span></span></span></code></pre>
</div>
</div>
<h3 data-sourcepos="236:1-236:6">
<span id="gs" class="fragment"/><a href="#gs"><i class="fa fa-link"/></a>gs</h3>
<div class="code-frame" data-lang="gs" data-sourcepos="237:1-248:3">
<div class="highlight">
<pre><code>// Google Apps Script のコードファイル (Code.gs)

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index')
    .setTitle('文字数カウンター')
    .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

// 必要に応じてサーバーサイドの関数を追加できます
// 例: ログ機能や保存機能など
</code></pre>
</div>
</div>
<p data-sourcepos="251:1-251:136">アプリのUI等は<a href="#%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%82%A2%E3%83%97%E3%83%AA">作成したアプリ</a>でお見せした通りなので、実際に動かしてみます。
<h3 data-sourcepos="252:1-252:28">
<span id="まずは日本語入力" class="fragment"/><a href="#%E3%81%BE%E3%81%9A%E3%81%AF%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%85%A5%E5%8A%9B"><i class="fa fa-link"/></a>まずは日本語入力</h3>
<p data-sourcepos="253:1-256:159"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2F9140f0b8-7229-47bd-b8ed-dd5bb1592024.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=bf4b50f7a0656bc2cfbde5662ba56429" target="_blank" rel="nofollow noopener"><img decoding="async" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2F9140f0b8-7229-47bd-b8ed-dd5bb1592024.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=bf4b50f7a0656bc2cfbde5662ba56429" alt="image.png" srcset="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2F9140f0b8-7229-47bd-b8ed-dd5bb1592024.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=f24c5a85c04ce6d236078b4c87fe20d9 1x" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493131/9140f0b8-7229-47bd-b8ed-dd5bb1592024.png" loading="lazy"/></a><strong>ちゃんとできてる!!!!</strong>指示通りリアルタイムでカウントしてくれます。そして、指示していないのに日本語入力している場合は単語数の部分に「日本語テキスト」と書かれています。賢すぎ
<h3 data-sourcepos="258:1-258:16">
<span id="英語入力" class="fragment"/><a href="#%E8%8B%B1%E8%AA%9E%E5%85%A5%E5%8A%9B"><i class="fa fa-link"/></a>英語入力</h3>
<p data-sourcepos="259:1-260:63"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fc0141bc2-6852-4164-a99a-232c711a5f02.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=773c5238d28553a977be081063e48cd7" target="_blank" rel="nofollow noopener"><img decoding="async" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fc0141bc2-6852-4164-a99a-232c711a5f02.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=773c5238d28553a977be081063e48cd7" alt="image.png" srcset="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fc0141bc2-6852-4164-a99a-232c711a5f02.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=cce9ff8e7832f9f8d66c73bdf2b1678a 1x" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493131/c0141bc2-6852-4164-a99a-232c711a5f02.png" loading="lazy"/></a>英語でもしっかりとカウントしてくれてます。
<div class="code-frame" data-lang="html" data-sourcepos="262:1-272:3">
<div class="highlight">
<pre><code>// 単語数 (英語のみ)
// 日本語が含まれない場合のみカウント
const hasJapanese = /[u3000-u303fu3040-u309fu30a0-u30ffuff00-uff9fu4e00-u9fafu3400-u4dbf]/.test(text);
if (!hasJapanese <span class="err">&&</span> text.trim() !== '') {
  const words = text.trim().split(/s+/).length;
  document.getElementById('wordCount').textContent = words;
} else {
  document.getElementById('wordCount').textContent = hasJapanese ? '日本語テキスト' : '0';
}
</code></pre>
</div>
</div>
<p data-sourcepos="273:1-273:202">HTMLのこの部分を見る限り、単語数はスペースで区切ってカウントしているようです。また、日本語の有無に関しては正規表現を用いて絞っています。
<p data-sourcepos="275:1-276:263"><a href="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fb81827a7-bcad-41b3-affc-b91cc50aed82.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=84eed3976181931099af82ffffa755b3" target="_blank" rel="nofollow noopener"><img decoding="async" src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fb81827a7-bcad-41b3-affc-b91cc50aed82.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=84eed3976181931099af82ffffa755b3" alt="image.png" srcset="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F3493131%2Fb81827a7-bcad-41b3-affc-b91cc50aed82.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=3ed97fa536313018119eba1c75eed2ff 1x" data-canonical-src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493131/b81827a7-bcad-41b3-affc-b91cc50aed82.png" loading="lazy"/></a>文字列に日本語が混ざると単語のカウントは止まります。そもそも単語数を数える条件が日本語が含まれていないときなので当然ですね。(全角文字を入力しても単語数のカウントは止まります。)
<p data-sourcepos="278:1-278:350">まさか本当に要件定義だけで完結するとは思ってませんでした。生成AIの進歩を身をもって感じることができました。「作業中にあったら便利だな」と思うようなwebアプリをノーコードで作ることができるのは、作業効率化に大きく寄与してくれると思います。
<h3 data-sourcepos="279:1-279:16">
<span id="検証結果" class="fragment"/><a href="#%E6%A4%9C%E8%A8%BC%E7%B5%90%E6%9E%9C"><i class="fa fa-link"/></a>検証結果</h3>
<p data-sourcepos="280:1-280:96">「簡単なwebアプリ作成、もはやClaudeに全部やってもらえる説」立証!!
</div>
<script>!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '305156090176370');
fbq('trackSingle', '305156090176370', 'PageView');</script><br />
<br /><a href="https://h.accesstrade.net/sp/cc?rk=0100oyf000odbd" rel="nofollow" referrerpolicy="no-referrer-when-downgrade"><img decoding="async" src="https://h.accesstrade.net/sp/rr?rk=0100oyf000odbd" alt="フラッグシティパートナーズ海外不動産投資セミナー" border="0" /></a>
<a href="https://h.accesstrade.net/sp/cc?rk=01004iw600odbd" rel="nofollow" referrerpolicy="no-referrer-when-downgrade"><img decoding="async" src="https://h.accesstrade.net/sp/rr?rk=01004iw600odbd" alt="【DMM FX】入金" border="0" /></a><br />
<br /><a href="https://qiita.com/mickey_mh/items/46e6e047a1e7e66c89dc?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items">Source link </a></p>
<div class='amazon-auto-links'><div class="amazon-products-container-list amazon-unit-29349 unit-type-category" style="">
        <div class="amazon-product-container">
        <div class="amazon-auto-links-product">
    <div class="amazon-auto-links-product-image">
        <div class='amazon-product-thumbnail-container' data-href='https://www.amazon.co.jp/iPad%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB2018-2025%E5%AF%BE%E5%BF%9C-13%E5%88%86%E6%80%A5%E9%80%9F%E5%85%85%E9%9B%BB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AB%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB-%E6%89%8B%E3%81%AE%E3%81%B2%E3%82%89%E8%AA%A4%E6%93%8D%E4%BD%9C%E9%98%B2%E6%AD%A2-5%E5%88%86%E8%87%AA%E5%8B%95%E3%82%B9%E3%83%AA%E3%83%BC%E3%83%97-%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3%E7%AC%AC11/dp/B0DSW7KNST/ref=zg_bsnr_g_computers_d_sccl_17/356-3178928-8054451?psc=1&tag=inmobi06-22' data-large-src='https://images-fe.ssl-images-amazon.com/images/I/51XtSw+eSqL._AC_UL500_SR500,500_.jpg'><div class="amazon-product-thumbnail" style="max-width:160px;max-height:160px;width:160px">
    <a href="https://www.amazon.co.jp/iPad%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB2018-2025%E5%AF%BE%E5%BF%9C-13%E5%88%86%E6%80%A5%E9%80%9F%E5%85%85%E9%9B%BB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AB%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB-%E6%89%8B%E3%81%AE%E3%81%B2%E3%82%89%E8%AA%A4%E6%93%8D%E4%BD%9C%E9%98%B2%E6%AD%A2-5%E5%88%86%E8%87%AA%E5%8B%95%E3%82%B9%E3%83%AA%E3%83%BC%E3%83%97-%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3%E7%AC%AC11/dp/B0DSW7KNST/ref=zg_bsnr_g_computers_d_sccl_17/356-3178928-8054451?psc=1&tag=inmobi06-22" title="iPadペンシル2018-2025対応, 13分急速充電アップルペンシル, 手のひら誤操作防止, 傾き感知, 磁気吸着, 5分自動スリープ 長時間使用, iPad タッチペン第11 (A16)/10/9/8/7/6世代、Air 11"/13" M2/M3 2025 /Pro 11"/13" M4 2024 、Mini 第7/6 Gen、Air 3/4/5 Gen に対応: " rel="nofollow noopener" target="_blank">
        <img decoding="async" src="https://images-fe.ssl-images-amazon.com/images/I/51XtSw+eSqL._AC_UL160_SR160,160_.jpg" alt="" style="max-height:160px" />
    </a>
</div></div>
    </div>
    <div class="amazon-auto-links-product-body">
        <h5 class="amazon-product-title">
<a href="https://www.amazon.co.jp/iPad%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB2018-2025%E5%AF%BE%E5%BF%9C-13%E5%88%86%E6%80%A5%E9%80%9F%E5%85%85%E9%9B%BB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AB%E3%83%9A%E3%83%B3%E3%82%B7%E3%83%AB-%E6%89%8B%E3%81%AE%E3%81%B2%E3%82%89%E8%AA%A4%E6%93%8D%E4%BD%9C%E9%98%B2%E6%AD%A2-5%E5%88%86%E8%87%AA%E5%8B%95%E3%82%B9%E3%83%AA%E3%83%BC%E3%83%97-%E3%82%BF%E3%83%83%E3%83%81%E3%83%9A%E3%83%B3%E7%AC%AC11/dp/B0DSW7KNST/ref=zg_bsnr_g_computers_d_sccl_17/356-3178928-8054451?psc=1&tag=inmobi06-22" rel="nofollow noopener" target="_blank">iPadペンシル2018-2025対応, 13分急速充電アップルペンシル, 手のひら誤操作防止, 傾き感知, 磁気吸着, 5分自動スリープ 長時間使用, iPad タッチペン第11 (A16)/10/9/8/7/6世代、Air 11"/13" M2/M3 2025 /Pro 11"/13" M4 2024 、Mini 第7/6 Gen、Air 3/4/5 Gen に対応</a>
</h5>
        <div class='amazon-customer-rating-stars'><div class='crIFrameNumCustReviews' data-rating='46' data-review-count='149' data-review-url='https://www.amazon.co.jp/product-reviews/B0DSW7KNST?tag=inmobi06-22'><span class='crAvgStars'><span class='review-stars'><a href='https://www.amazon.co.jp/product-reviews/B0DSW7KNST?tag=inmobi06-22' target='_blank' rel='nofollow noopener'><svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 160 32' enable-background='new 0 0 160 32'><title>5星中4.6(149)
¥1,599 (2025年4月25日 13:05 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)