WikiChree.COM 新規   編集   添付   管理  



トップ   編集 編集〔GUI〕 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS   ログイン

Pkript/文法/JSX の変更点

#author("2026-08-31T22:15:08+09:00","default:guide","guide")
* Pkript/文法/JSX [#j1d6268f]
#author("2026-09-04T00:06:06+09:00","default:mcp","bot-mcp")
* Pkript/文法/JSX [#kd8fa19f]

式中に HTML タグを直接記述する構文。
HTML要素を式として記述する記法。文字列連結の代わりに使う。

** リファレンス [#q3400424]
** リファレンス [#x916181f]

*** 構文 [#o4cbe103]
*** 構文 [#ad1b5edc]

#pkript(highlight){{
#highlight{{
<タグ 属性="値">{式}</タグ>
}}

- 設定定数 PKRIPT_JSX が 1 の場合に利用可能
- {} 内に渡された文字列は自動で HTML エスケープ処理が行われる
- JSX 要素同士を {} 内に埋め込んだ場合、エスケープされず要素の入れ子として展開される
- 単一の親要素、またはフラグメント <> ... </> で囲む必要がある
- 設定定数 PKRIPT_JSX が 1(既定)の場合に利用できる。0 にすると &lt; は比較演算子としてだけ働く
- {} 内に渡された文字列は自動でHTMLエスケープされる
- JSX要素どうしを {} 内に埋め込んだ場合はエスケープされず、入れ子としてそのまま展開される
- 単一の親要素、またはフラグメント &lt;&gt; ... &lt;/&gt; で囲む

#highlight{{
function plugin_hello_convert(e) {
    const name = e.args[0];
    return <p class="greeting">こんにちは、{name} さん</p>;
}
}}

** 使用法 [#e13a22b8]
*** 書ける形 [#p616b045]

*** 変数を埋め込んでコンポーネントを出力する [#jefdc937]
**** 要素と入れ子 [#form_nest]

#pkript(highlight){{
#highlight{{
return <ul><li>a</li><li>b</li></ul>;
}}

**** 空要素 [#form_void]

#highlight{{
return <br />;
}}

閉じスラッシュが要る。&lt;br&gt; だけでは閉じタグ待ちになる。

**** フラグメント [#form_fragment]

複数の要素を、囲む要素なしで並べる。

#highlight{{
return <><p>a</p><p>b</p></>;
}}

**** 属性 [#form_attr]

文字列か {式} を書く。

#highlight{{
const cls = e.opts["class"];
return <p class="fixed">x</p>;
return <p class={cls}>x</p>;
return <p title={42}>x</p>;
}}

- className と書いても class になる
- 値が null の属性は出力されない
- {...obj} のスプレッド属性には対応していない

**** {} の中身 [#form_expr]

式なら何でも書ける。

#highlight{{
return <div><span>{1 + 1}</span></div>;
return <ul>{items.map((x) => <li>{x}</li>).join("")}</ul>;
}}

null, false, 空文字列は何も出力しない。0 は "0" と出る。

*** エスケープの規則 [#s4d26f32]

ここがJSXの要点。文字列は必ずエスケープされ、JSX要素はされない。

#highlight{{
const s = "<li>x</li>";        // ただの文字列
return <ul>{s}</ul>;           // <ul>&lt;li&gt;x&lt;/li&gt;</ul>

const el = <li>x</li>;         // JSX要素
return <ul>{el}</ul>;          // <ul><li>x</li></ul>
}}

wiki.convert() の戻り値もエスケープされない。Wiki記法から作ったHTMLをそのまま埋め込める。

#highlight{{
return <div>{wiki.convert(e.body)}</div>;
}}

**** htmlsc は使わない [#escape_htmlsc]

{} の中は自動でエスケープされる。htmlsc() を重ねると二重エスケープになる。

#highlight{{
return <p>{htmlsc("<b>")}</p>;    // &amp;lt;b&amp;gt; と出てしまう
return <p>{"<b>"}</p>;            // &lt;b&gt; が正しい
}}

**** 属性値も同じ [#escape_attr]

属性値に入れた文字列はエスケープされる。引用符を混ぜて属性を抜け出すことはできない。

#highlight{{
const c = "a\" onclick=\"alert(1)";
return <p class={c}>y</p>;        // class ごと落とされる
}}

*** サニタイザとの関係 [#m9847ca9]

JSXで書いたHTMLも、他の出力と同じようにサニタイザを通る。JSXは記法を短くするだけで、出せるHTMLの範囲は変わらない。

|~書いたもの|~出力|h
|&lt;script&gt;alert(1)&lt;/script&gt;|タグごと削除|
|&lt;p onclick="..."&gt;|onclick が削除|
|&lt;p id="a"&gt;|id="pkript-a" に変換|
|&lt;a href="javascript:..."&gt;|href が削除|
|&lt;p style="position: fixed"&gt;|position の宣言のみ削除(他の値は使える)|
|&lt;form&gt;|action が自Wikiに補完|

詳しくは [[Pkript/設定/サニタイザ]] を参照。


** 使用法 [#l5abaadf]

*** 変数を埋め込んでコンポーネントを出力する [#usage_component]

#highlight{{
function plugin_profile_convert(e) {
    const name = e.args[0] || "ゲスト";
    return (
        <div class="profile-box">
            <h3>プロフィール</h3>
            <p>名前: {name}</p>
        </div>
    );
}
}}

*** 配列から要素を組み立てる [#usage_list]

** 注意点 [#pebe1d78]
#highlight{{
const items = e.args;
return <ul>{items.map((x) => <li>{x}</li>).join("")}</ul>;
}}

{} 内に htmlsc() を適用すると二重エスケープになるため直接変数を指定する。

** 注意点 [#kf841ec8]

*** 要素を文字列として切り貼りしない [#note_string]

JSX要素は、出力の直前まで内部の目印として持ち回る。length や charAt の結果は、表示されるHTMLと一致しない。

#highlight{{
const el = <b>x</b>;
return el.length;        // 8 ではない
}}

連結(+)と join() は安全。

#highlight{{
return <b>a</b> + <i>b</i>;
return items.map((x) => <li>{x}</li>).join("");
}}

*** タグの間の空白は消える [#note_space]

#highlight{{
return <ul>
  <li>a</li>
  <li>b</li>
</ul>;
}}

上は &lt;ul&gt;&lt;li&gt;a&lt;/li&gt;&lt;li&gt;b&lt;/li&gt;&lt;/ul&gt; になる。要素の中の文字列に含まれる空白はそのまま残る。

*** HTMLコメントは書けない [#note_comment]

&lt;!-- --&gt; は使えない。

*** &lt; が比較演算子になる場合 [#note_lt]

直前のトークンで判断する。値や ) の後ろの &lt; は比較演算子、それ以外は JSX の始まり。

#highlight{{
if (n < 10) { }          // 比較
return <p>x</p>;         // JSX
}}