あなたが話していることがそこにあるかどうかはわかりません。似たようなものが必要だったので、単純なテキスト置換スクリプトを作成する方が、既存のソリューションを比較して使用方法を学ぶよりも速いと考えました。
このスクリプトは本番環境には対応していません (もっとテストする必要があり、API は奇妙です) が、これを実行する方法の 1 つについてのアイデアが得られるはずです。
設定方法は次のとおりです。
ドキュメントへのテンプレートの保存
テンプレート テキストはtype
、「text/javascript」以外の属性を持つスクリプト タグに格納されます。各テンプレートには一意の id 属性があります。
<script id="some_template" type="text/plain">
a valid template
</script>
ブラウザはこれらをレンダリングすべきではありません。任意の文字を使用でき ( を除く</script>
)、エスケープする必要はありません。
プレースホルダー
プレースホルダーは次のようになります{@some_identifier}
。
<script id="image_template" type="text/plain">
<a href="{@img_url}"><img src="{@img_url}"></a>
</script>
各プレースホルダーは次のいずれかに置き換えられます。
- 別のテンプレートから渡された値、
- テンプレートのコピーを取得するときに JavaScript 関数に渡される引数、または
- 置換値が見つからない場合は空の文字列。
あるテンプレートを別のテンプレートに含める
「@@
疑似タグ」には、現在のテンプレートに別のテンプレートのコンテンツが含まれています。
<script id="photo_template" type="text/plain">
<@@ image_template></@@>
<div class="photo-caption">{@caption}</div>
</script>
photo_template
含まれてい image_template
ます。インクルージョンの置換はすべて、プレースホルダーの置換の前に行われるため、およびプレースホルダーphoto_template
も同様です。{@img_url}
{@caption}
プレースホルダー置換による包含
これが「ラッピング」の由来です。理想的には、プレースホルダーは、テンプレートのコピーを取得するときに渡される値ではなく、ほとんどの場合、他のテンプレートのコンテンツに置き換えられます。
<script id="missing_photo_template" type="text/plain">
<@@ photo_template>
<@ img_url>notfound.png</@>
</@@>
</script>
missing_photo_template
を含みphoto_template
、 の代わりを提供するため{@img_url}
、プレースホルダーmissing_photo_template
のみが含まれます。{@caption}
JavaScript
API は今のところ最悪ですが、基本的にメインの名前空間at
には と の 2 つの関数がtxt
ありnode
ます。1 つ目はテンプレートのコピーをテキストとして取得し、2 つ目はコピーを要素として取得します (上記の例とは異なり、1 つのルート ノードが必要です)。
ここにあります:
/**
Atrocious Templates
*/
var at = (function(){
var rTemplate = /<@@\s*(.*?)>((?:[\w\W](?!<@@))*?)<\/@@>/gm,
rOption = /<@\s*(.*?)>([\w\W]*?)<\/@>/gm,
rValue = /\{@(.*?)\}/g,
rTag = /<(\w+)/i,
rSpace = /\s+/,
templates = {},
doc = document.implementation.createHTMLDocument('');
/**
Inlcude inner templates.
@private
@param {string} m0
The full inclusion text.
@param {string} m1
The ID of the included template.
@param {string} m2
Values passed to included template.
@return {string}
*/
function includeTemplates(m0, m1, m2) {
var opts = {};
m2.replace(rOption, function(m0, m1, m2) { opts[m1] = m2; });
return txt(m1, opts, true);
}
/**
Get text contents of a template.
@private
@param {string} id
The ID of the template.
@return {string}
*/
function get(id) {
if (templates[id]) return templates[id];
var last, t = document.getElementById(id).innerHTML;
while (last != t && (last = t)) t = t.replace(rTemplate, includeTemplates);
return (templates[id] = t);
}
/**
Get a text copy of a template.
@param {string} id
The ID of the template.
@param {Object.<string|function ():string>} options
Properties of this object will replace placeholder tokens.
Each property can be either a string, or a function which
returns a string.
@param {boolean=} noStrip
By default, placeholders for which no replacement text is
found are removed. Setting this to `true` overrides that
behavior, leaving non-replaced placeholders intact.
@return {string}
*/
function txt(id, options, noStrip) {
if (!options) options = {};
return get(id).replace(rValue, function(m0, m1) {
var v = options[m1];
return noStrip && !v && m0 || v && (v.call ? v() : v) || '';
});
}
/**
Get a node copy of a template.
@param {string} id
The ID of the template.
@param {Object.<string|function ():string>} options
Properties of this object will replace placeholder tokens.
@return {string}
*/
function node(id, options) {
var text = txt(id, options),
root = text.match(rTag)[1];
doc.open; doc.write(text); doc.close();
return doc.getElementsByTagName(root)[0];
}
// exports
return { txt: txt, node: node };
}());
繰り返しますが、これはあまりテストされていないため (正常に動作しているように見えますが)、本番環境で使用することはお勧めしませんが、希望することを達成する方法についていくつかのアイデアが得られることを願っています.