◆ templatestring の tag を有効活用したい
  ◆ 適当に色々作ってみる
◆ heredoc は使える……かもしれない

tag `text ${10} text ${value}`

JavaScript のタグ機能はこういうやつです
バッククオートの文字列 テンプレートストリングの前に関数を置いておくと () なしで特別な実行のされ方をします
特殊な書き方なのが面白くて 何か有効利用できないものかとよくあれこれやってるのですが 実用性のあるものはできないのですよね
lit-html の記法はすごく良い利用方法だと思います
そういう実用性のあるものではないですが こんな事できるというのを書いてみました

1

コマンドっぽく
class Class {
constructor(){
this.value = ""
}

abc(){
this.value += "abc"
}

xyz(){
this.value += "xyz"
}

now(){
this.value += Date.now()
}

random(){
this.value += Math.random().toString(36).substr(2)
}

end(){
return this.value
}
}

const t = (...args) => {
const v = new Class()
const name = String.raw(...args)
v[name]()
const rec = (...args) => {
const name = String.raw(...args)
v[name]()
if(name === "end"){
return v.end()
}else{
return rec
}
}
return rec
}
t`abc``xyz``now``random``now``abc``abc``random``xyz``end`
abcxyz1529569122433de7md5601sa1529569122433abcabchtqmk4tcngjxyz

関数の () を `` に置き換えたようなものですが 一見なにこれと思えるのが面白いところです
文字列がそのままメソッド名になっていて メソッドチェーンしてるのと変わりません
end というテキストが特殊で これが来ると終了になります

2

引数とパイプライン風な機能も付けてみました

const fns = {
add(a, b){
return a + b
},

replace(a, b){
return b
},

prepend(a, b){
return String(b) + a
},

append(a, b){
return a + String(b)
},
}

const apply = (value, name, args) => {
if(name.startsWith(".")){
return value[name.substr(1)](...args)
}else{
return fns[name](value, ...args)
}
}

const t = (strs, ...values) => {
let v = null
v = apply(v, strs[0].trim(), values)
const rec = (strs, ...values) => {
const name = strs[0].trim()
if(name === ".."){
return v
}else{
v = apply(v, name, values)
return rec
}
}
return rec
}
t`replace ${12345}``add ${98765}``.toString ${16}``.split ${/[a-f]+/}``.join ${"/"}``prepend ${"##"}``append ${"!!"}``..`
##1/206!!

それぞれのテンプレートストリングには関数名と引数を書きます
fns で定義した関数名を直接文字列で書いて その後に ${} で値を渡すとそれが引数として渡されます
結果は次の関数の最初の引数として渡されます
最初の関数では null です

関数名を 「.」 から始めると以前の結果に対するメソッド呼び出しです
「..」が来るとそこで終了です

3

これは少し使えるかもしれません
heredocument です

function h(){
const texts = []
const rec = (strs, ...values) => {
if(strs.length === 1 && strs[0] === ""){
return texts.join("`")
}else{
texts.push(String.raw(strs, ...values))
return rec
}
}
return rec
}
h```
この中でバッククオート使うときは2つ書く → 「``」
2連続はできない
```
"
この中でバッククオート使うときは2つ書く → 「`」
2連続はできない
"

トリプルバッククオートで heredocument を作れるようにしました
もともとバッククオートは heredocument みたいなものですが 中で 「`」 を使う時に構文の制限で 「\`」 にしないといけないのですが そうすると実際の文字列もエスケープ文字がついています
それをなくしたのがこれです
バッククオート 2 つで通常のバッククオート 1 つになります

構文的にバッククオート 3 つがあるわけではないので一つでは済ませられません
最初と最後に空文字が入ったテンプレートストリングがあって間に複数のテンプレートストリングがあるというものです
色分けするとこうなります

h```
この中でバッククオート使うときは2つ書く → 「`
`」
2連続はできない
`
``

最後が空文字のテンプレートストリングであることを前提としているので 連続でバッククオートを書こうとして 4 つ以上のバッククオートを書いた場合は正常に動きません
一応それの対策で別バージョンも作りました
ただこっちだと 最後に終わりであることを示すために () で関数呼び出しが必要です

function here(strs, ...values){
const texts = []
texts.push(String.raw(strs, ...values))
const rec = (strs, ...values) => {
if(!strs){
return texts.join("`")
}else{
texts.push(String.raw(strs, ...values))
return rec
}
}
return rec
}
here`
こっちは連続できる
``````````````````````
けど最後に () が必要
`()
"
こっちは連続できる
```````````
けど最後に () が必要
"

ちなみに short ブログの方のタイトルバーの右下の方にある式 あれ結構気に入ってます