1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Nimで静的ファイルの配信

Last updated at Posted at 2022-09-20

htmlgenの公式しか頼れなかったので、ここにメモします。

htmlgenをimportすると、HTMLタグに対応したmacroが使えます。

h1

例えばh1タグ

nim
h1("hello world!")

↓のように解釈されます

html
<h1>hello world!</h1>

サーバーとして実行して試すなら下記のように記述します。
フレームワークに Jester を使っています。
$ nimble install jesterとしてjesterを使えるようにしてください。

nim
import std/htmlgen, jester

router route:
  get "/":
    let html = h1("hello world!")
    resp(Http200, html)

proc main() =
  let settings = newSettings(port = Port(3333), staticDir = "static/")
  var jes = initJester(route, settings = settings)
  jes.serve()

when isMainModule:
  main()

これでブラウザからlocalhost:3333へアクセスすると、"hello world!"と大きな文字で表示されます。

a

例えばaタグ

nim
a(href="https://qiita.com/", "Qiitaのトップページ")

↓のように解釈されます

html
<a href="https://qiita.com/">Qiitaのトップページ</a>

htmlgenのソースを見てみるとどんなタグが指定可能かわかります。
たいていのHTMLタグが列挙されていることがわかると思います。
aタグだったら、"href target download rel hreflang type " とあるので、これらのスペース区切りの文字列を指定可能なタグの属性として指定できます。

macro a*(e: varargs[untyped]): untyped =
  ## generates the HTML ``a`` element.
  result = xmlCheckedTag(e, "a", "href target download rel hreflang type " &
    commonAttr)

commonAttr

commonAttrは文字通り共通の属性で、すべてのマクロに使える属性です。
classやid, styleなどが含まれます。

commonAttr = " accesskey class contenteditable dir hidden id lang spellcheck style tabindex title translate onabort onblur oncancel oncanplay oncanplaythrough onchange onclick oncuechange ondblclick ondurationchange onemptied onended onerror onfocus oninput oninvalid onkeydown onkeypress onkeyup onload onloadeddata onloadedmetadata onloadstart onmousedown onmouseenter onmouseleave onmousemove onmouseout onmouseover onmouseup onmousewheel onpause onplay onplaying onprogress onratechange onreset onresize onscroll onseeked onseeking onselect onshow onstalled onsubmit onsuspend ontimeupdate ontoggle onvolumechange onwaiting  role "

実際にブラウザーへアクセスして確かめるなら、先ほどのサンプルのrouterブロックを下記のように書き換えます。

nim
router route:
  get "/":
    let
      h1 = h1("hello world!")
      a = a(href = "https://qiita.com/", "Qiitaのトップページ")
      html = h1 & a
    resp(Http200, html)

input

例えばinputタグ

nim
input(type = "text",
      name = "search-word",
      id = "search-word",
      placeholder = "検索キーワードを入力",
      size = "20")

↓のように解釈されます

html
<input type="text" name="search-word" id="search-word" placeholder="検索キーワードを入力" size="20">

複数の属性を指定してみます。

nim
router route:
  get "/":
    let
      h1 = h1("hello world!")
      a = a(href = "https://qiita.com/", "Qiitaのトップページ")
      input = input(type = "text",
                    name = "search-word",
                    id = "search-word",
                    placeholder = "検索キーワードを入力",
                    size = "20")
      html = h1 & a & input
    resp(Http200, html)

table

例えばtableタグ

tableを書くときはtrタグとtdタグを組み合わせます。

nim
table(
  tr(td("要素"), td(input(id = "短い", value = "短い文書"))),
  tr(td("文書"), td(
    textarea(
      id = "長い",
      readonly = "",
      style = "width:242px; height:100px;",
      "長い文書",
      )
    )
  )
)

↓のように解釈されます。
適当にインデントしています。

html
<table>
  <tbody>
    <tr>
      <td>要素</td>
      <td><input id="短い" value="短い文書"></td>
    </tr>
    <tr>
      <td>文書</td>
      <td><textarea id="長い" readonly="" style="width:242px; height:100px;">長い文書</textarea></td>
    </tr>
  </tbody>
</table>

例ではテーブルの要素の中にinputタグやtextareaタグを入れて複雑なテーブルになっています。

textareaタグではreadonly属性を使っていますが、
readonlyのような値を持たない属性をNimのマクロで指定するときは空の文字列を指定するようです。

nim
textarea(readonly = "", "長い文書")

↓のように解釈されます

html
<textarea readonly> 長い文書 </textarea>

head, link

CSSやfaviconのパスを記述するために使うheadタグとlinkタグ

nim
favicon = link(type = "image/png",
            rel = "icon",
            href = "/favicon.png")
bootstrap = link(href = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css",
              rel = "stylesheet",
              crossorigin = "anonymous")
head = head(favicon & bootstrap)

↓のように解釈されます。
適当にインデントしています。

html
<head>
  <link type="image/png" rel="icon" href="/favicon.png">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
</head>

headタグにlinkなんかを書く例。
これでfaviconを表示し、Bootstrap5が使えます。

script

例えばscriptタグ

nim
js = script(type = "module", src = "/dist/main.js")

↓のように解釈されます。

html
<script type="module" src="/dist/main.js"></script>

さいごに

全部結合すればHTMLファイルの完成です。

nim
router route:
  get "/":
    let
      favicon = link(type = "image/png",
                  rel = "icon",
                  href = "/favicon.png")
      bootstrap = link(href = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css",
                    rel = "stylesheet",
                    crossorigin = "anonymous")
      head = head(favicon & bootstrap)

      h1 = h1("hello world!")
      a = a(href = "https://qiita.com/", "Qiitaのトップページ")
      input = input(type = "text",
                    name = "search-word",
                    id = "search-word",
                    placeholder = "検索キーワードを入力",
                    size = "20")
      table = table(
        tr(td("要素"), td(input(id = "短い", value = "短い文書"))),
        tr(td("文書"), td(
          textarea(
            id = "長い",
            readonly = "",
            style = "width:242px; height:100px;",
            "長い文書",
            )
          )
        )
      )
      js = script(type = "module", src = "/dist/main.js")
      body = h1 & a & input & table & js

      html = head & body
    resp(Http200, html)

index.html的なものを最初に書いておいて変数を埋め込む、という形ではなく、
マクロによってNimの関数を書くようにHTMLを記述していくスタイルでした。

マクロのソースを眺めているだけでも、HTMLタグやタグに指定できる属性を知ることができるので勉強になりますね。

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?