From 2b50e1778b164e641c03c2e77176b6f47ca1e278 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 18 Mar 2023 15:47:05 +0900 Subject: refactor: add RawHTML type to represent text node not being escaped --- nuldoc-src/docbook/to_html.ts | 12 +++++-- nuldoc-src/dom.ts | 9 ++++- nuldoc-src/html.ts | 8 +++-- nuldoc-src/templates/utils.ts | 1 + nuldoc-src/types/highlight-js.d.ts | 4 +++ nuldoc-src/xml.ts | 2 ++ .../ruby-detect-running-implementation/index.html | 4 +-- .../ruby-then-keyword-and-case-in/index.html | 12 +++---- .../rust-where-are-primitive-types-from/index.html | 8 ++--- .../index.html | 2 +- .../vim-swap-order-of-selected-lines/index.html | 24 ++++++------- .../2022-04-09/phperkaigi-2022-tokens/index.html | 34 +++++++++--------- .../index.html | 2 +- .../index.html | 14 ++++---- .../phperkaigi-2023-unused-token-quiz-1/index.html | 6 ++-- .../setup-server-for-this-site/index.html | 40 +++++++++++----------- 16 files changed, 104 insertions(+), 78 deletions(-) diff --git a/nuldoc-src/docbook/to_html.ts b/nuldoc-src/docbook/to_html.ts index c824780..9f176d4 100644 --- a/nuldoc-src/docbook/to_html.ts +++ b/nuldoc-src/docbook/to_html.ts @@ -9,6 +9,7 @@ import { forEachChild, forEachChildRecursively, Node, + RawHTML, removeChildElements, Text, } from "../dom.ts"; @@ -239,6 +240,7 @@ function transformNoteElement(doc: Document) { children: [{ kind: "text", content: "Note", + raw: true, }], }; const contentElement: Element = { @@ -298,12 +300,18 @@ function highlightPrograms(doc: Document) { if (!language) { return; } - const sourceCode = (codeElement.children[0] as Text).content; + const sourceCodeNode = codeElement.children[0] as Text | RawHTML; + const sourceCode = sourceCodeNode.content; + + if (!hljs.getLanguage(language)) { + return; + } const highlighted = hljs.highlight(sourceCode, { language: language }).value; - (codeElement.children[0] as Text).content = highlighted; + sourceCodeNode.content = highlighted; + sourceCodeNode.raw = true; codeElement.attributes.set("class", "highlight"); }); } diff --git a/nuldoc-src/dom.ts b/nuldoc-src/dom.ts index 51ef25a..626d400 100644 --- a/nuldoc-src/dom.ts +++ b/nuldoc-src/dom.ts @@ -1,6 +1,13 @@ export type Text = { kind: "text"; content: string; + raw: false; +}; + +export type RawHTML = { + kind: "text"; + content: string; + raw: true; }; export type Element = { @@ -10,7 +17,7 @@ export type Element = { children: Node[]; }; -export type Node = Element | Text; +export type Node = Element | Text | RawHTML; export function addClass(e: Element, klass: string) { const classes = e.attributes.get("class"); diff --git a/nuldoc-src/html.ts b/nuldoc-src/html.ts index 70b5748..b94877a 100644 --- a/nuldoc-src/html.ts +++ b/nuldoc-src/html.ts @@ -115,15 +115,19 @@ function toHtmlText(dom: Document): string { function nodeToHtmlText(n: Node, ctx: Context): string { if (n.kind === "text") { - return textNodeToHtmlText(n, ctx); + if (n.raw) { + return n.content; + } else { + return textNodeToHtmlText(n, ctx); + } } else { return elementNodeToHtmlText(n, ctx); } } function textNodeToHtmlText(t: Text, ctx: Context): string { - if (ctx.isInPre) return t.content; const s = encodeSpecialCharacters(t.content); + if (ctx.isInPre) return s; // TODO: 日本語で改行するときはスペースを入れない return s diff --git a/nuldoc-src/templates/utils.ts b/nuldoc-src/templates/utils.ts index a86803d..65dd506 100644 --- a/nuldoc-src/templates/utils.ts +++ b/nuldoc-src/templates/utils.ts @@ -7,6 +7,7 @@ export function text(content: string): Text { return { kind: "text", content: content, + raw: false, }; } diff --git a/nuldoc-src/types/highlight-js.d.ts b/nuldoc-src/types/highlight-js.d.ts index 312cd06..d7bd0b5 100644 --- a/nuldoc-src/types/highlight-js.d.ts +++ b/nuldoc-src/types/highlight-js.d.ts @@ -1,4 +1,8 @@ declare module "highlight.js" { + function getLanguage( + name: string, + ): string | undefined; + function highlight( code: string, options: { language: string }, diff --git a/nuldoc-src/xml.ts b/nuldoc-src/xml.ts index bb7d499..9c0ea45 100644 --- a/nuldoc-src/xml.ts +++ b/nuldoc-src/xml.ts @@ -80,6 +80,7 @@ function parseTextNode(p: Parser): Text { return { kind: "text", content: replaceEntityReferences(content), + raw: false, }; } @@ -90,6 +91,7 @@ function parseCdata(p: Parser): Text { return { kind: "text", content: formatCdata(content), + raw: false, }; } diff --git a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html index 03bae40..4d17e71 100644 --- a/public/posts/2021-10-02/ruby-detect-running-implementation/index.html +++ b/public/posts/2021-10-02/ruby-detect-running-implementation/index.html @@ -75,10 +75,10 @@ 上記ページの例から引用する:

-
$ ruby-1.9.1 -ve 'p RUBY_ENGINE'
+          
$ ruby-1.9.1 -ve 'p RUBY_ENGINE'
 ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]
 "ruby"
-$ jruby -ve 'p RUBY_ENGINE'
+$ jruby -ve 'p RUBY_ENGINE'
 jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
 "jruby"
diff --git a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html index 25fb3bb..c027417 100644 --- a/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html +++ b/public/posts/2021-10-02/ruby-then-keyword-and-case-in/index.html @@ -119,11 +119,11 @@ a 次のような構文エラーが出力される。

-
20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
-if true puts 'Hello, World!' end
+            
20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
+if true puts 'Hello, World!' end
         ^~~~
-20:1: syntax error, unexpected `end', expecting end-of-input
-...f true puts 'Hello, World!' end
+20:1: syntax error, unexpected `end', expecting end-of-input +...f true puts 'Hello, World!' end

二つ目のメッセージは無視して一つ目を読むと、then;か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。 @@ -182,7 +182,7 @@ b https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986

-
p_case_body : keyword_in
+            
p_case_body : keyword_in
   {
   SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
   p->command_start = FALSE;
@@ -213,7 +213,7 @@ b
               簡略版:
             

-
p_case_body : keyword_in p_top_expr then compstmt p_cases
+            
p_case_body : keyword_in p_top_expr then compstmt p_cases
 ;

diff --git a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html index bc40aaa..0554341 100644 --- a/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html +++ b/public/posts/2021-10-02/rust-where-are-primitive-types-from/index.html @@ -119,20 +119,20 @@ rustcはセルフホストされている (=rustc自身が Rust で書かれている) ので、boolcharなどで適当に検索をかけてもノイズが多すぎて話にならない。 しかし、お誂え向きなことにi128/u128というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使ってgit grepしてみる。

-
$ git grep "\bi128\b" | wc      # i128
+            
$ git grep "\bi128\b" | wc      # i128
 165    1069   15790
 
-$ git grep "\bu128\b" | wc      # u128
+$ git grep "\bu128\b" | wc      # u128
 293    2127   26667
 
-$ git grep "\bbool\b" | wc      # cf. bool の結果
+$ git grep "\bbool\b" | wc      # cf. bool の結果
 3563   23577  294659

165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。

-
$ git grep "\bi128\b"
+            
$ git grep "\bi128\b"
 ...
 rustc_resolve/src/lib.rs:        table.insert(sym::i128, Int(IntTy::I128));
 ...
diff --git a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html index 0e1e296..d2da2e5 100644 --- a/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html +++ b/public/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/index.html @@ -157,7 +157,7 @@ FileEncoding = 'EncodingChanged', ところで、上では取り上げなかったFileEncodingだが、これは:help FileEncodingにしっかりと書いてある。

-
                                                           *FileEncoding*
+              
                                                           *FileEncoding*
 FileEncoding                    Obsolete.  It still works and is equivalent
 to |EncodingChanged|.
diff --git a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html index 8dbea05..22042a8 100644 --- a/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html +++ b/public/posts/2021-10-02/vim-swap-order-of-selected-lines/index.html @@ -125,9 +125,9 @@ なお、:g/^/m0は全ての行を入れ替えるが、:N,Mg/^/mN-1とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。

-
command! -bar -range=%
+              
command! -bar -range=%
 \ Reverse
-\ <line1>,<line2>g/^/m<line1>-1
+\ <line1>,<line2>g/^/m<line1>-1

これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。 @@ -160,13 +160,13 @@ 前述した:Reverseコマンドの定義を少し変えて、次のようにする:

-
function! s:reverse_lines(from, to) abort
-  execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
-  endfunction
+            
function! s:reverse_lines(from, to) abort
+  execute printf("%d,%dg/^/m%d", a:from, a:to, a:from - 1)
+  endfunction
 
-  command! -bar -range=%
+  command! -bar -range=%
   \ Reverse
-  \ call <SID>reverse_lines(<line1>, <line2>)
+ \ call <SID>reverse_lines(<line1>, <line2>)

実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。 @@ -217,9 +217,9 @@

-
command! -bar -range=%
+            
command! -bar -range=%
   \ Reverse
-  \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1

まさにこのための Exコマンド、:keeppatternsが存在する。:keeppatterns {command}のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。 @@ -234,11 +234,11 @@

コピペ用再掲

-
" License: Public Domain
+            
" License: Public Domain
 
-  command! -bar -range=%
+  command! -bar -range=%
   \ Reverse
-  \ keeppatterns <line1>,<line2>g/^/m<line1>-1
+ \ keeppatterns <line1>,<line2>g/^/m<line1>-1
diff --git a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html index d077255..9dd9495 100644 --- a/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html +++ b/public/posts/2022-04-09/phperkaigi-2022-tokens/index.html @@ -173,28 +173,28 @@ なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。

-
+ + + + + + + + + +
+                
+ + + + + + + + + +
 [
-> + + +
-> + + + + +
-> + + + + + + + + + + + +
-> + + + + + + + + + +
-< < < < -
+> + + +
+> + + + + +
+> + + + + + + + + + + + +
+> + + + + + + + + + +
+< < < < -
 ]
-> + + + + + .
+> + + + + + .
 - - .
-> - - - .
-> - - - .
+> - - - .
+> - - - .
 - - .
 - .
-< .
-> > - - .
+< .
+> > - - .
 + + + + + + + .
-< - - - - .
-< .
-> + + .
-> - .
-< .
+< - - - - . +< . +> + + . +> - . +< .

実行結果はこちら:https://ideone.com/22VWmb @@ -532,7 +532,7 @@ コメントにもあるとおり、次のようにして実行すれば答えがでてくる。

-
$ php toquine.php | php | php | php | ...
+
$ php toquine.php | php | php | php | ...

実際にはもう少しパイプで繋げなければならない。 diff --git a/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html b/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html index d8e5dee..f0edd35 100644 --- a/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html +++ b/public/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/index.html @@ -53,7 +53,7 @@ こんなものを作った。

-
$ term-banner 'Hello, World!' 'こんにちは、' '世界!'
+
$ term-banner 'Hello, World!' 'こんにちは、' '世界!'

image::https://raw.githubusercontent.com/nsfisis/term-banner/main/screenshot.png[term-banner のスクリーンショット] diff --git a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html index 93a0a0c..8d821d7 100644 --- a/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html +++ b/public/posts/2022-09-29/write-fizzbuzz-in-php-2-letters-per-line/index.html @@ -689,15 +689,15 @@ ${ 先程と同じく、chrprintfを生成する部分は長くなるので省いた。

-
${
-'_
-'}
+
${
+'_
+'}

は変数で、中にはスペースとエスケープが入っている (chr(32) . chr(92))。シェルに渡されている文字列は次のようになる。

-
e\
+            
e\
 c\
 h\
 o\
@@ -718,9 +718,9 @@ o\
               ちなみに、PHP 8.2 からは、この記法で Warning が出るようになるようだ。
             

-
${
-'_
-'}
+
${
+'_
+'}

最新版で警告が出るというのも美しくないので、私としては本編の解法を推す。 diff --git a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html index 10ef763..864958a 100644 --- a/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html +++ b/public/posts/2022-10-23/phperkaigi-2023-unused-token-quiz-1/index.html @@ -107,14 +107,14 @@ $π = trim($π); ソースを見るとわかるとおり、$argv[1]を参照している。それをなる変数に代入しているので、円周率を渡してみる。

-
$ php Q.php 3.14
+            
$ php Q.php 3.14
   Failed.

失敗してしまった。精度を上げてみる。

-
$ php Q.php 3.1415
+            
$ php Q.php 3.1415
 Failed.

@@ -125,7 +125,7 @@ Failed.

最初にトークンが得られるのは、小数点以下 16 桁目まで入力したときで、こうなる。

-
$ php Q.php 3.1415926535897932
+            
$ php Q.php 3.1415926535897932
 Token: #YO

diff --git a/public/posts/2022-10-28/setup-server-for-this-site/index.html b/public/posts/2022-10-28/setup-server-for-this-site/index.html index a290046..5329b98 100644 --- a/public/posts/2022-10-28/setup-server-for-this-site/index.html +++ b/public/posts/2022-10-28/setup-server-for-this-site/index.html @@ -83,7 +83,7 @@ ローカルマシンで鍵を生成する。

-
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key
+              
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/teika.key
   $ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github2teika.key

@@ -97,7 +97,7 @@ .ssh/configに設定しておく。

-
Host teika
+              
Host teika
   HostName **********
   User **********
   Port **********
@@ -120,7 +120,7 @@
                 管理者ユーザで作業すると危ないので、メインで使うユーザを作成する。sudoグループに追加してsudoできるようにし、suで切り替え。
               

-
$ sudo adduser **********
+              
$ sudo adduser **********
     $ sudo adduser ********** sudo
     $ su **********
     $ cd
@@ -128,12 +128,12 @@

ホスト名を変える

-
$ sudo hostname teika
+
$ sudo hostname teika

公開鍵を置く

-
$ mkdir ~/.ssh
+              
$ mkdir ~/.ssh
   $ chmod 700 ~/.ssh
   $ vi ~/.ssh/authorized_keys
@@ -148,7 +148,7 @@ SSH の設定を変更し、少しでも安全にしておく。

-
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
+              
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
   $ sudo vi /etc/ssh/sshd_config
    @@ -169,7 +169,7 @@ そして設定を反映。

    -
    $ sudo systemctl restart sshd
    +              
    $ sudo systemctl restart sshd
     $ sudo systemctl status sshd
@@ -179,7 +179,7 @@ $ sudo systemctl status sshd
今の SSH セッションは閉じずに、ターミナルを別途開いて疎通確認する。セッションを閉じてしまうと、SSH の設定に不備があった場合に締め出しをくらう。

-
$ ssh teika
+
$ ssh teika
@@ -188,7 +188,7 @@ $ sudo systemctl status sshd
デフォルトの 22 番を閉じ、設定したポートだけ空ける。

-
$ sudo ufw deny ssh
+              
$ sudo ufw deny ssh
   $ sudo ufw allow *******
   $ sudo ufw enable
   $ sudo ufw reload
@@ -205,20 +205,20 @@ $ sudo systemctl status sshd
GitHub に置いてある private リポジトリをサーバから clone したいので、SSH 鍵を生成して置いておく。

-
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key
+              
$ ssh-keygen -t ed25519 -b 521 -f ~/.ssh/github.key
 $ cat ~/.ssh/github.key.pub

GitHub の設定画面から、この公開鍵を追加する。

-
$ vi ~/.ssh/config
+
$ vi ~/.ssh/config

設定はこう。

-
Host github.com
+              
Host github.com
 HostName github.com
 User git
 IdentityFile ~/.ssh/github.key
@@ -227,12 +227,12 @@ IdentityFile ~/.ssh/github.key
最後に接続できるか確認しておく。

-
ssh -T github.com
+
ssh -T github.com

パッケージの更新

-
$ sudo apt update
+              
$ sudo apt update
   $ sudo apt upgrade
   $ sudo apt update
   $ sudo apt upgrade
@@ -251,12 +251,12 @@ IdentityFile ~/.ssh/github.key

使うソフトウェアのインストール

-
$ sudo apt install docker docker-compose git make
+
$ sudo apt install docker docker-compose git make

メインユーザが Docker を使えるように

-
sudo adduser ********** docker
+
sudo adduser ********** docker
@@ -265,7 +265,7 @@ IdentityFile ~/.ssh/github.key
80 番と 443 番を空ける。

-
$ sudo ufw allow 80/tcp
+              
$ sudo ufw allow 80/tcp
     $ sudo ufw allow 443/tcp
     $ sudo ufw reload
     $ sudo ufw status
@@ -273,7 +273,7 @@ IdentityFile ~/.ssh/github.key

リポジトリのクローン

-
$ cd
+              
$ cd
   $ git clone git@github.com:nsfisis/nsfisis.dev.git
   $ cd nsfisis.dev
   $ git submodule update --init
@@ -281,13 +281,13 @@ IdentityFile ~/.ssh/github.key

certbot で証明書取得

-
$ docker-compose up -d acme-challenge
+              
$ docker-compose up -d acme-challenge
   $ make setup

サーバを稼動させる

-
$ make serve
+
$ make serve
-- cgit v1.2.3-70-g09d2