私が最近つまずいたより強力な概念の1つは、抽象的な構文ツリー、またはASTのアイデアです。錬金術を勉強したことがあるなら、錬金術師の動機全体が科学的または不可解な方法を通じて金に変身する方法を発見したことを思い出すかもしれません。
ASTはそのようなものです。 ASTを使用して、MarkdownをHTML、JSXにJavaScriptなどに変換できます。
なぜASTSが役立つのですか?
私のキャリアの早い段階で、Find-and Replaceメソッドを使用してファイルを変更しようとしました。これはかなり複雑になったので、正規表現を使用してみました。それはとても脆かったので、私はそのアイデアを放棄することになりました。誰かが私が予想していなかった方法でテキストを入力し、それが私の通常の表現を壊してアプリ全体を倒すため、アプリは常に壊れていました。
これが非常に困難だった理由は、HTMLが柔軟であるためです。そのため、正規表現を使用して解析することは非常に困難です。このような文字列ベースの交換は、試合を逃したり、一致しすぎたり、奇妙なことをしたり、無効なマークアップになってページをjankyに見せたりする可能性があるため、壊れやすいです。
一方、ASTは、HTMLをはるかに構造化されたものに変えます。これにより、テキストノードに飛び込み、そのテキストのみで交換を行うか、テキストに対処する必要なく要素を台無しにすることがはるかに簡単になります。
これにより、AST変換により、純粋に文字列ベースのソリューションよりも安全でエラーが発生しません。
ASTは何に使用されていますか?
まず、マークダウンの数行を使用して最小限のドキュメントを見てみましょう。これは、home.mdというファイルとして保存され、これをウェブサイトのコンテンツフォルダーに保存します。
# こんにちは世界! 愛らしいコーギー! さらにいくつかのテキストがここにあります。</https:>
マークダウンを知っていると仮定すると、このマークダウンが解析されると、「Hello World!」と書かれたH1タグになると推測できます。次に、テキストの2つの段落:最初の段落には、Corgiの画像とそれを説明することを目的としたテキストが含まれており、2番目のテキストには「さらにテキストがここにあります」と書かれています。
しかし、どのようにしてマークダウンからHTMLに変換されますか?
それがASTSが入ってくるところです!
複数の言語をサポートするため、Unist Syntax Treeの仕様、より具体的にはプロジェクトが統合されます。
依存関係をインストールします
まず、マークダウンをASTに解析してHTMLに変換するために必要な依存関係をインストールする必要があります。そのためには、フォルダをパッケージとして初期化したことを確認する必要があります。端末で次のコマンドを実行します。
#ルートフォルダーにいることを確認してください(「コンテンツ」があります) #このフォルダーをNPMパッケージとして初期化します npm init #依存関係をインストールします NPMインストール統一覚醒パースHTMLをインストールします
マークダウンがhome.mdに保存されていると仮定した場合、次のコードでASTを取得できます。
const fs = require( 'fs'); const unified = require( 'unified'); const markdown = require( 'aread-parse'); const html = require( 'arem-html'); const contents = unified() .use(Markdown) .use(html) .processsync(fs.readfilesync( `$ {process.cwd()}/content/home.md`))) .toString(); console.log(contents);
このコードは、Nodeの組み込みFSモジュールを利用して、ファイルシステムにアクセスして操作できるようになります。これがどのように機能するかの詳細については、公式ドキュメントをご覧ください。
これをsrc/index.jsとして保存し、ノードを使用してコマンドラインからこのスクリプトを実行すると、端末に次のことがわかります。
$ node src/index.js <h1 id="hello-world"> hello world!</h1> <p> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi">愛らしいcorgi!</p> <p>さらにいくつかのテキストがここにあります。</p>
Unifiedは、derear-parseを使用してMarkdownファイルをASTに変換し、derme-HTMLを使用してMarkdown ASTをHTMLに変えるように指示します。 toString()メソッドを使用すると、そのASTがブラウザに表示できる実際のHTMLの文字列に変換します!
オープンソースコミュニティのハードワークのおかげで、発言は私たちのためにマークダウンをHTMLに変えるというすべてのハードワークを行います。 (diffを参照)
次に、これが実際にどのように機能するかを見てみましょう。
ASTはどのように見えますか?
実際のASTを表示するには、小さなプラグインを記録してみましょう。
const fs = require( 'fs'); const unified = require( 'unified'); const markdown = require( 'aread-parse'); const html = require( 'arem-html'); const contents = unified() .use(Markdown) .use(()=> tree => console.log(json.stringify(tree、null、2)))) .use(html) .processsync(fs.readfilesync( `$ {process.cwd()}/content/home.md`))) .toString();
スクリプトの実行の出力は次のとおりです。
{ 「タイプ」:「ルート」、 "子供たち": [ { 「タイプ」:「見出し」、 「深さ」:1、 "子供たち": [ { 「タイプ」:「テキスト」、 「価値」:「Hello World!」、 "位置": {} } ]、、 "位置": {} }、 { 「タイプ」:「段落」、 "子供たち": [ { 「タイプ」:「画像」、 「タイトル」:ヌル、 「url」: "<https:>"、 「alt」:「カーディガン・コーギー」、 "位置": {} }、 { 「タイプ」:「テキスト」、 「価値」:「愛らしいコーギー!」、 "位置": {} } ]、、 "位置": {} }、 { 「タイプ」:「段落」、 "子供たち": [ { 「タイプ」:「テキスト」、 「値」:「さらにいくつかのテキストがここにあります。」、 "位置": {} } ]、、 "位置": {} } ]、、 "位置": {} }</https:>
スペースを節約するために位置値が切り捨てられていることに注意してください。ノードがドキュメント内にある場所に関する情報が含まれています。このチュートリアルの目的のために、この情報は使用しません。 (diffを参照)
これは少し圧倒されますが、ズームインすると、マークダウンの各部分がテキストノードの中にテキストノードを持つノードのタイプになることがわかります。
たとえば、見出しは次のとおりです。
{ 「タイプ」:「見出し」、 「深さ」:1、 "子供たち": [ { 「タイプ」:「テキスト」、 「価値」:「Hello World!」、 "位置": {} } ]、、 "位置": {} }
これが意味します:
- このタイプは、どのようなノードを扱っているかを教えてくれます。
- 各ノードタイプには、ノードを記述する追加のプロパティがあります。見出しの深さのプロパティは、それがどのレベルに見られるかを教えてくれます - 1の深さは、それが
タグ、2は
などであることを意味します。
- 子供の配列は、このノード内にあるものを教えてくれます。見出しと段落の両方で、テキストのみがありますが、のようなインライン要素も見ることができます。
これがASTSの力です。マークダウンドキュメントを、コンピューターが理解できるオブジェクトとして説明しました。これをマークダウンに戻したい場合、マークダウンコンパイラは、1の深さの「見出し」ノードが#から始まり、値「hello」を持つ子テキストノードは最終行が#helloでなければならないことを知っています。
AST変換の仕組み
ASTの変換は通常、訪問者パターンを使用して行われます。これがどのように生産的であるかについての内外を知ることは重要ではありませんが、あなたが興味があるなら、Soham Kamaniによる人間のJavaScriptのデザインパターンは、それがどのように機能するかを説明するのに役立つ素晴らしい例を持っています。知っておくべき重要なことは、AST作業のリソースの大部分が「ノードの訪問」について話していることです。これは、「ASTの一部を見つけて、それを使ってやることができる」ことです。これが練習の仕組みは、基準に一致するASTノードに適用される関数を記述することです。
それがどのように機能するかについてのいくつかの重要なメモ:
- ASTは巨大な場合があるため、パフォーマンスの理由でノードを直接変異させます。これは、私が通常物事にアプローチする方法に反しています - 一般的なルールとして、私はグローバルな状態を変異させたくありませんが、この文脈では意味があります。
- 訪問者は再帰的に働きます。つまり、ノードを処理して同じタイプの新しいノードを作成すると、訪問者に明示的に指示しない限り、訪問者も新しく作成されたノードで実行されます。
- このチュートリアルにはあまり深く進むつもりはありませんが、これらの2つのアイデアは、コードを台無しにし始めたときに何が起こっているのかを理解するのに役立ちます。
ASTのHTML出力を変更するにはどうすればよいですか?
ただし、マークダウンの出力を変更したい場合はどうなりますか?私たちの目標は、フィギュア要素で画像タグをラップし、このようなキャプションを提供することだとしましょう。
<img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="Cardigan Corgi"> <figcaption>愛らしいcorgi!</figcaption> 図>
これを達成するには、MarkdownがフィギュアまたはFigcaption要素を作成する方法がないため、Markdown ASTではなくHTML ASTを変換する必要があります。幸いなことに、Unifiedは複数のパーサーと相互運用可能であるため、多数のカスタムコードを作成せずにそれを行うことができます。
マークダウンASTをHTML ASTに変換します
Markdown ASTをHTML ASTに変換するには、ASTをHTMLに戻すために、吹き抜きを追加してRehype-Stringifyに切り替えます。
npm semple-rehype rehype-stringifyをインストールします
src/index.jsで次の変更を加えて、再ヒープに切り替えます。
const fs = require( 'fs'); const unified = require( 'unified'); const markdown = require( 'aread-parse'); const areme2rehype = require( 'arem-rehype'); const html = require( 'rehype-stringify'); const contents = unified() .use(Markdown) .use(derme2rehype) .use(()=> tree => console.log(json.stringify(tree、null、2)))) .use(html) .processsync(fs.readfilesync( 'corgi.md')) .toString(); console.log(contents);
HTML変数はdearm-htmlからrehype-stringifyに変更されたことに注意してください。
スクリプトを実行すると、ASTで画像要素がこのように見えるようになりました。
{ 「タイプ」:「要素」、 「tagname」:「img」 「プロパティ」:{ 「src」: "https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg"、 「alt」:「カーディガン・コーギー」 }、 "子供たち": []、 "位置": {} }
これは、画像のHTML表現のASTであるため、フィギュア要素を使用するために変更を開始できます。 (diffを参照)
Unifiedのプラグインを書きます
IMG要素をフィギュア要素で包むには、プラグインを書く必要があります。 Unifiedでは、プラグインが使用()メソッドが追加されます。これは、プラグインを最初の引数として受け入れ、2番目の引数としてオプションを受け入れます。
.use(プラグイン、オプション)
プラグインコードは、オプションを受信する関数(Unified Jargonの「アタッチャー」と呼ばれる)です。これらのオプションは、ASTを受信し、それを変換するために動作する新しい関数(「トランス」と呼ばれる)を作成するために使用されます。プラグインの詳細については、Unified Docsのプラグインの概要をご覧ください。
それが返す関数は、その引数としてAST全体を受け取り、何も返さない。 (覚えておいてください、ASTはグローバルに変異しています。)index.jsと同じフォルダーにIMG-to-figure.jsという新しいファイルを作成し、次の内部に置きます。
module.exports = options => tree => { console.log(tree); };
これを使用するには、src/index.jsに追加する必要があります。
const fs = require( 'fs'); const unified = require( 'unified'); const markdown = require( 'aread-parse'); const areme2rehype = require( 'arem-rehype'); const html = require( 'rehype-stringify'); const imgtofigure = require( './ img-to-figure'); const contents = unified() .use(Markdown) .use(derme2rehype) .use(imgtofigure) .processsync(fs.readfilesync( 'corgi.md')) .toString(); console.log(contents);
スクリプトを実行すると、コンソールでツリー全体がログアウトされていることがわかります。
{ タイプ:「ルート」、 子供たち: [ { タイプ:「要素」、 tagname: 'p'、 プロパティ:{}、 子供:[配列]、 位置:[オブジェクト] }、 {type: 'text'、value: '\\ n'}、 { タイプ:「要素」、 tagname: 'p'、 プロパティ:{}、 子供:[配列]、 位置:[オブジェクト] } ]、、 位置: { 開始:{行:1、列:1、オフセット:0}、 終了:{行:4、列:1、オフセット:129} } }
(diffを参照)
プラグインへの訪問者を追加します
次に、訪問者を追加する必要があります。これにより、実際にコードにアクセスできます。 Unifiedは、カスタムコードを作成せずにASTで一般的なことをすることができるUnist-Util-*が付いたすべてのユーティリティパッケージを利用しています。
unist-util-visitを使用してノードを変更できます。これにより、3つの議論を取る訪問ヘルパーが与えられます。
- 私たちが働いている全体のAST
- アクセスするノードを識別する述語関数
- 私たちが作りたいASTに変更を加えるための関数
インストールするには、コマンドラインで以下を実行します。
npm unist-util-visitをインストールします
次のコードを追加して、プラグインに訪問者を実装しましょう。
const visit = require( 'unist-util-visit'); module.exports = options => tree => { 訪問( 木、 // IMG要素を含むPタグのみにアクセス node => node.tagname === 'p' && node.children.some(n => n.tagname === 'img')、 node => { console.log(node); } ); };
これを実行すると、ログに記録されている段落ノードが1つだけあることがわかります。
{ タイプ:「要素」、 tagname: 'p'、 プロパティ:{}、 子供たち: [ { タイプ:「要素」、 tagname: 'img'、 プロパティ:[オブジェクト]、 子供たち: []、 位置:[オブジェクト] }、 {type: 'text'、value: 'a adorable corgi!'、position:[object]} ]、、 位置: { 開始:{行:3、列:1、オフセット:16}、 終了:{行:3、列:102、オフセット:117} } }
完璧!変更したい画像がある段落ノードのみを取得しています。今、私たちはASTを変換し始めることができます!
(diffを参照)
画像をフィギュア要素に巻き付けます
画像属性が整ったので、ASTを変更し始めることができます。 ASTSは非常に大きくなる可能性があるため、多くのコピーを作成し、スクリプトを減速させる可能性があるため、それらを配置して配置します。
まず、ノードのtagnameを段落の代わりに数字に変更することから始めます。残りの詳細は今のところ同じままです。
SRC/IMG-to-figure.jsで次の変更を加えます:
const visit = require( 'unist-util-visit'); module.exports = options => tree => { 訪問( 木、 // IMG要素を含むPタグのみにアクセス node => node.tagname === 'p' && node.children.some(n => n.tagname === 'img')、 node => { node.tagname = '図'; } ); };
スクリプトをもう一度実行して出力を見ると、近づいていることがわかります!
<h1 id="hello-world"> hello world!</h1> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi">愛らしいcorgi!図> <p>さらにいくつかのテキストがここにあります。</p>
(diffを参照)
画像の横にあるテキストをキャプションとして使用する
カスタム構文を作成する必要がないようにするために、画像のキャプションとして画像で渡されたテキストをインラインで使用します。
通常、画像にはマークダウンにインラインテキストがないという仮定を立てることができますが、マークダウンを書いている人に100%意図しないキャプションが表示される可能性があることは注目に値します。このチュートリアルでは、そのリスクを負います。これを生産に入れることを計画している場合は、トレードオフを比較検討し、状況に最適なものを選択してください。
テキストを使用するには、親ノード内のテキストノードを探します。見つけたら、キャプションとしてその価値をつかみたいと思います。キャプションが見つからない場合、このノードをまったく変換したくないので、早めに戻ることができます。
次の変更をSRC/IMG-to-figure.jsに変更して、キャプションを取得します。
const visit = require( 'unist-util-visit'); module.exports = options => tree => { 訪問( 木、 // IMG要素を含むPタグのみにアクセス node => node.tagname === 'p' && node.children.some(n => n.tagname === 'img')、 node => { //テキストノードを見つけます const textnode = node.children.find(n => n.type === 'text'); //キャプションがない場合、ノードを変換する必要はありません if(!textNode)return; const caption = textnode.value.trim(); console.log({キャプション}); node.tagname = '図'; } ); };
スクリプトを実行すると、キャプションが記録されているのがわかります。
{キャプション:「愛らしいコーギー!」 }
(diffを参照)
図にfigcaption要素を追加します
キャプションテキストができたので、それを表示するためにFigcaptionを追加できます。これは、新しいノードを作成して古いテキストノードを削除することでこれを行うことができますが、その所定の位置に変異しているため、テキストノードを要素に変更するだけでは少し複雑ではありません。
ただし、要素にはテキストがないため、キャプションテキストを表示するためにFigcaption要素の子として新しいテキストノードを追加する必要があります。
SRC/IMG-to-figure.jsに次の変更を加えて、マークアップにキャプションを追加します。
const visit = require( 'unist-util-visit'); module.exports = options => tree => { 訪問( 木、 // IMG要素を含むPタグのみにアクセス node => node.tagname === 'p' && node.children.some(n => n.tagname === 'img')、 node => { //テキストノードを見つけます const textnode = node.children.find(n => n.type === 'text'); //キャプションがない場合、ノードを変換する必要はありません if(!textNode)return; const caption = textnode.value.trim(); //テキストノードをテキストノードを含むfigcaption要素に変更します textnode.type = 'element'; textnode.tagname = 'figcaption'; textnode.children = [ { タイプ:「テキスト」、 値:キャプション } ]; node.tagname = '図'; } ); };
ノードSRC/index.jsで再度スクリプトを実行すると、変換された画像が図要素に包まれ、フィマで説明されています。
<h1 id="hello-world"> hello world!</h1> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi"> <figcaption>愛らしいコーギー! <p>さらにいくつかのテキストがここにあります。</p></figcaption>
(diffを参照)
変換されたコンテンツを新しいファイルに保存します
多数の変換を行ったので、それらを実際のファイルに保存して、それらを共有できるようにしたいと考えています。
マークダウンには完全なHTMLドキュメントは含まれていないため、Rehype-Documentという1つのRehypeプラグインを追加して、完全なドキュメント構造とタイトルタグを追加します。
実行によるインストール:
npm rehype-documentをインストールします
次に、SRC/index.jsに次の変更を加えます。
const fs = require( 'fs'); const unified = require( 'unified'); const markdown = require( 'aread-parse'); const areme2rehype = require( 'arem-rehype'); const doc = require( 'rehype-document'); const html = require( 'rehype-stringify'); const imgtofigure = require( './ img-to-figure'); const contents = unified() .use(Markdown) .use(derme2rehype) .use(imgtofigure) .use(doc、{title: 'transfirned document!'}) .use(html) .processsync(fs.readfilesync( `$ {process.cwd()}/content/home.md`))) .toString(); const outputdir = `$ {process.cwd()}/public`; if(!fs.existsync(outputdir)){ fs.mkdirsync(outputdir); } fs.writefilesync( `$ {outputdir}/home.html`、contents);
スクリプトをもう一度実行すると、publicと呼ばれるルートの新しいフォルダーが表示されます。内部では、変換されたドキュメントが保存されています!
<title>変換されたドキュメント!</title> <meta name="Viewport" content="width = device-width、initial-scale = 1"> <h1 id="hello-world"> hello world!</h1> <img src="<https://images.dog.ceo/breeds/corgi-cardigan/n02113186_1030.jpg>" alt="cardigan corgi"> <figcaption>愛らしいコーギー! <p>さらにいくつかのテキストがここにあります。</p> </figcaption>
(diffを参照)
パブリック/home.htmlをブラウザで開くと、変換されたマークダウンがキャプション付きのフィギュアとしてレンダリングされていることがわかります。
聖なるバケツ!その愛らしいコーギーを見てください!そして、キャプションがそう言っているので、私たちはそれが愛らしいことを知っています。
次に何をすべきか
ASTSを使用してファイルを変換することは非常に強力です。これにより、安全な方法で想像できるものをほとんど作成できます。正規表現や文字列解析は必要ありません!
ここからは、プラグインのエコシステムを深く掘り下げて、発言と再ヒープを掘り下げて、可能なことをもっと見て、独自のマークダウン駆動の静的サイトジェネレーターを構築することから、AST変換でできることについてより多くのアイデアを得ることができます。コードを内装することにより、パフォーマンスの改善を自動化する。あなたが想像できるものは何でも!
AST変換はコーディングスーパーパワーです。このデモのソースコードをチェックアウトすることから始めましょう。あなたがそれで構築するものを見るのが待ちきれません! Twitterでプロジェクトを共有してください。
以上が抽象的な構文ツリーでノードを変更する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

しばらくの間、iTunesはポッドキャストの大きな犬だったので、「ポッドキャストにサブスクライブ」をリンクした場合:

彼らが2013年にChromeに行ったとき、私たちはオペラを失いました。今年初めにChromeになったとき、Edgeと同じ取引。マイク・テイラーはこれらの変更を「減少させて」と呼びました

Trashy ClickBaitサイトから出版物の最大の8月まで、共有ボタンは長い間ウェブ全体でユビキタスでした。それでも、これらは議論の余地があります

今週のラウンドアップでは、AppleはWebコンポーネント、InstagramがどのようにInsta-Loadingスクリプトであるか、自己ホストの重要なリソースのための考えのための食べ物に入ります。

gitコマンドのドキュメントを調べていたとき、それらの多くが選択肢があることに気付きました。私は当初、これはただのものだと思っていました

難しい問題のように聞こえます。私たちはしばしば、何千もの色で製品ショットを持っていないので、withをひっくり返すことができます。私たちもそうしません

ウェブサイトにダークモードオプションがあるときが好きです。ダークモードにより、ウェブページが読みやすくなり、目がリラックスしているように感じます。を含む多くのウェブサイト

これは私が初めてHTML要素を見ていることです。私はしばらくの間それを知っていましたが、まだスピンしていませんでした。かなりクールです


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

Dreamweaver Mac版
ビジュアル Web 開発ツール

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SublimeText3 中国語版
中国語版、とても使いやすい

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール
