预过滤器 Prefilter
DouView 在编译前对模板源执行预过滤(Prefilter),前台与后台各一套。预过滤器在 DouView::compileSource 里、真正编译之前运行。
一、前台 FrontPrefilter
- 主题静态资源烘焙为绝对路径:把模板里的相对资源引用(
images/、css/、js/,含../前缀)替换为当前主题的绝对 URL。主题路径优先取$GLOBALS['_THEME_PATH'],其次取已 assign 的theme_path,再次由site.site_theme+ROOT_URL拼接。 - 移除旧式 meta:删除行首的
meta http-equiv="Content-Type"声明。 - 还原 HTML 注释包裹的标签:把注释内的模板标签激活(见第三节)。
因为是编译期字面烘焙,前台编译产物与主题强绑定,切主题 / 升级引擎须清缓存(靠 COMPILE_REVISION 自动失效),详见「编译流程与缓存 Compile Cache」篇。
二、后台 AdminPrefilter
- 静态资源加后台前缀:
css//js//images/分别前缀为{$admin_url}view/css/等({$admin_url}渲染期解析,含 host),使后台在伪静态深路径下不受相对基准目录影响; - 裸链接绝对化:仅限
href/action属性里的裸index.php?route=链接,前缀为{$admin_url}index.php?route=(避免误伤{url ... back='index.php?route=...'}这类标签参数); - 移除旧式 meta:同前台;
- 还原 HTML 注释包裹的标签:同前台。
三、HTML 注释包裹标签的还原
两份预过滤器都会把「HTML 注释里的模板标签」还原为真正生效的标签。这使得模板可以用 HTML 注释包裹标签,在未渲染时(如直接用浏览器打开)仍保持合法 HTML 结构,渲染时注释被去掉、标签被执行:
<ul>
<!-- {foreach from=$list item=item} -->
<li>{$item.title}</li>
<!-- {/foreach} -->
</ul>
这是 DouPHP 模板的常见写法。还原算法(restoreCommentTags)的三条关键规则:
- 注释体内全部
{..}标签都要激活:只保留首个标签会丢{/foreach}等闭合配对,导致编译期报 mismatched tag; - 文本只保留在成对块内部:如
<!-- {if !$first}、{/if} -->中成对{if}/{/if}之间的「、」会保留;而成对结构之外的说明文字(如<!-- {if $rec eq 'default'} 起始页 -->的「起始页」)丢弃,避免泄漏为页面可见文本(与旧remove_html_comments口径一致); - 块标签全集:参与配对判定的块标签集合 = Parser 入栈容器
if/foreach/list/category/strip加上 Lexer 保护区literal(漏literal会把注释内{literal}块的内部文本误处理)。
若注释体内没有任何完整 {..} 标签,restoreCommentTags 返回 null,调用方保留原注释不动。
四、工程约定
- 前台与后台的
restoreCommentTags逐字一致,任何改动都要同步两份,否则会前后台行为漂移; - 改动预过滤语义必须同步 bump
DouView::COMPILE_REVISION,否则模板源 mtime 未变时旧编译缓存不会重编。