- 后端
- Web框架
【免费下载链接】CodeIgniter
Open Source PHP Framework (originally from EllisLab)
Typography 是 CodeIgniter 框架内置的文本格式化库,用于将普通纯文本自动转换为语义正确、排版规范的 HTML——包括自动识别段落、将引号转为弯引号实体、把连字符转为破折号、把三点省略号转为…等。本文以 Typography 库官方文档 为主线,结合 系统源码 与 单元测试 深入讲解其初始化方式、全部公开方法与核心属性,帮助你把它用于博客评论、内容投稿、论坛帖子等需要"用户输入 → 干净 HTML"场景。
一、初始化 Typography 类
与 CodeIgniter 中大多数类库一致,Typography 库在控制器中通过$this->load->library()加载:
$this->load->library('typography');加载完成后,类库实例通过$this->typography访问:
$this->typography->auto_typography($string);底层实现位于 system/libraries/Typography.php,类名为CI_Typography,它没有继承其他框架核心类,是一个独立的自包含工具类。除了通过$this->load->library()加载外,框架还提供了对应的辅助函数封装(详见本文第五节),可以在不显式加载库的情况下直接调用。
二、类属性:控制排版行为的开关
CI_Typography暴露了若干public属性,其中文档明确记录的是$protect_braced_quotes,其余属性则从源码注释可以确认,它们共同构成了排版引擎的行为配置。
2.1$protect_braced_quotes:保护花括号内的引号
- 类型:
bool - 默认值:
FALSE
当 Typography 库与 模板解析器 Parser 库 配合使用时,模板中的伪变量以花括号包裹,例如{blog_title}、{parse="foobar"}。如果先对含花括号的模板字符串做排版、之后再交给 Parser 解析,花括号内引号被提前转成弯引号实体,会导致 Parser 的变量匹配失败。
将protect_braced_quotes设为TRUE,即可让auto_typography()在排版时跳过花括号内的内容,原样保留其中的单双引号:
$this->load->library('typography'); $this->typography->protect_braced_quotes = TRUE;该开关对应源码中的处理逻辑(Typography.php):当属性为TRUE时,花括号内的字符会先通过_protect_characters()替换为临时标记,排版结束后再还原:
if ($this->protect_braced_quotes === TRUE) { $str = preg_replace_callback('#\{.+?\}#si', array($this, '_protect_characters'), $str); }单元测试 给出了开关开启与关闭的对比结果,非常直观:
$this->type->protect_braced_quotes = TRUE; $str = 'Test {parse="foobar"}'; // 结果: <p>Test {parse="foobar"}</p> —— 花括号内引号原样保留 $this->type->protect_braced_quotes = FALSE; $str = 'Test {parse="foobar"}'; // 结果: <p>Test {parse=“foobar”}</p> —— 引号被转成弯引号实体可见关闭该开关时,"foobar"中的双引号会被转换为“/”,从而破坏 Parser 的{parse="foobar"}匹配。需要提醒的是:该保护只作用于"引号"这一类字符,花括号内其他排版规则(如段落包裹)是否生效取决于具体输入,使用前建议结合你的模板内容做一次实际验证。
2.2 其他排版相关的类属性(源码可见)
从 Typography.php 的类属性声明可以确认以下内部配置:
| 属性 | 默认值 | 作用 |
|---|---|---|
$block_elements | address\|blockquote\|div\|dl\|fieldset\|form\|h\d\|hr\|noscript\|object\|ol\|p\|pre\|script\|table\|ul | 不应被<p>包裹的块级元素列表 |
$skip_elements | p\|pre\|ol\|ul\|dl\|object\|table\|h\d | 内部不应再插入<p>与<br />的元素 |
$inline_elements | a\|abbr\|acronym\|b\|bdo\|big\|br\|button\|cite\|code\|del\|dfn\|em\|i\|img\|ins\|input\|label\|map\|kbd\|q\|samp\|select\|small\|span\|strong\|sub\|sup\|textarea\|tt\|var | 解析拆分字符串时应整体忽略的内联标签 |
$inner_block_required | array('blockquote') | 内部内容必须处于另一个块级元素内的元素 |
$last_block_element | '' | 最近一次解析到的块级元素名 |
$protect_braced_quotes | FALSE | 是否保护花括号内的引号 |
这些属性是排版引擎区分"块级元素 / 跳过元素 / 内联元素"三类标签的依据:块级元素不会被包裹进<p>,但其包含的文本若含段落仍会被格式化;跳过元素内部不再插入<p>和<br />(<pre>也因此天然得到保护);内联标签在拆分时作为整体保留,避免<img>、<a>等标签被错误拆分。
三、方法详解:auto_typography($str[, $reduce_linebreaks = FALSE])
这是 Typography 库的核心方法,接收任意字符串,返回"语义与排版均正确的 HTML"。
- 参数:
string $str输入字符串 - 参数:
bool $reduce_linebreaks是否将连续多余换行压缩为两个(默认FALSE) - 返回:
string排版安全的 HTML 字符串
基本用法:
$string = $this->typography->auto_typography($string);3.1 官方文档列出的 7 大格式化规则
官方文档明确说明,auto_typography()会对输入做以下处理:
- 段落包裹:以"双换行"识别段落,将段落包裹进
<p></p>; - 单换行转
<br />:单个换行转换为<br />,但<pre>标签内的换行除外; - 块级元素不被包裹:
<div>等块级元素本身不会套上<p>,但其内部文本若包含段落,仍会得到格式化; - 弯引号转换:引号转换为方向正确的弯引号实体,标签内的引号除外;
- 弯撇号转换:撇号转换为弯撇号实体;
- 破折号转换:双连字符(无论是
-- this还是like--this形式)转换为长破折号(em-dash,—); - 省略号转换:单词前或后的连续三个句点转换为省略号(
…); - 句后双空格:句子后的双空格转换为不间断空格(
),以模拟双空格效果。
3.2 可选参数:压缩连续换行
$reduce_linebreaks决定是否把超过两个的连续换行压缩到两个:
$string = $this->typography->auto_typography($string, TRUE);源码中的对应实现(Typography.php):
if ($reduce_linebreaks === TRUE) { $str = preg_replace("/\n\n+/", "\n\n", $str); }测试用例 验证了其效果:
$str = "This has way too many linebreaks.\n\n\n\nSee?"; // 结果: <p>This has way too many linebreaks.</p>\n\n<p>See?</p>传入TRUE时,四个连续换行被压缩为两个,输出两个干净的<p>段落;此外在收尾清理阶段,TRUE模式还会移除空的<p>\n*</p>段落,而未开启时空段落会被填充为<p> </p>(Typography.php),确保浏览器能正确渲染为空段落而非被折叠。
3.3 源码级处理流水线
从源码看,auto_typography()的处理流程是一条精心设计的"保护-转换-还原"流水线(Typography.php):
- 空字符串短路:
$str === ''直接返回空串,避免后续正则开销; - 换行标准化:把所有
\r\n、\r统一为\n,保证后续匹配一致性; - (可选)压缩换行:见 3.2;
- 剥离 HTML 注释:
<!-- ... -->先被替换为{@HC0}、{@HC1}等占位符,处理结束后再按原位恢复; - 保护
<pre>块:整个<pre>...</pre>通过_protect_characters()整体占位,内部引号、双空格、双连字符全部换成临时标记,因此排版不会污染代码块; - 保护标签内字符:对所有
<.+?>标签调用_protect_characters(),将标签内的'、"、--、双空格分别替换为{@SQ}、{@DQ}、{@DD}、{@NBS}; - (可选)保护花括号:当
$protect_braced_quotes为TRUE时对\{.+?\}执行同样的保护; - 标记内联标签:
<开头且匹配$inline_elements的标签整体替换为{@TAG}...,避免在后续按标签拆串时被拆散; - 按标签拆串:用
preg_split()把字符串按 HTML 标签拆成数组(标签与文本交替),逐段循环处理; - 块级元素识别:循环中命中
$block_elements的片段原样保留;命中$skip_elements时切换$process标志,使<pre>、<ol>等内部文本跳过换行格式化; - 换行格式化:对普通文本调用
_format_newlines(),把\n\n替换为</p>\n\n<p>,把单个\n替换为<br />,最后整体包裹<p>...</p>; - 补开段落:若最终字符串不以块级元素开头,自动在最前补一个
<p>; - 字符级格式化:调用
format_characters()(见第四节)完成弯引号、破折号、省略号、不间断空格、&转义; - 还原 HTML 注释与全部占位标记,并执行最终清理:去重连续
</p>、清除块级元素前的游离<p></p>、修正></p>\n与</p></的换行问题等。
其中_format_newlines()(Typography.php)还专门处理了$inner_block_required中列出的blockquote:当最近解析的块级元素是blockquote时,即使文本中没有换行也会强制进入换行处理逻辑,从而保证<blockquote>内部内容始终有块级结构包裹。
测试套件 将auto_typography()拆成 6 个子场景逐一验证:空字符串、换行标准化、换行压缩、HTML 注释保留、<pre>保护、缺少开标签时的自动补齐,以及花括号引号保护,覆盖了上述流水线的关键分支。
3.4 性能注意与缓存建议
官方文档特别提醒:排版格式化可能非常消耗处理器资源,尤其当你需要格式化大量内容时。auto_typography()内部包含多轮正则匹配与逐段循环,若在每次请求中都对长文本执行,会成为性能瓶颈。
因此官方建议:如果决定使用此方法,应考虑对页面做缓存处理。实践上推荐两种策略:
- 对内容写入时排版、读取时直出:用户在投稿/评论提交时执行一次
auto_typography(),将结果存入数据库,展示时不再重复排版; - 对动态页面使用框架的输出缓存(页面缓存或驱动缓存),缓存渲染后的 HTML。
四、方法详解:format_characters($str)
format_characters()与auto_typography()类似,但只做字符级转换,不处理段落、换行与标签结构。
- 参数:
string $str输入字符串 - 返回:
string格式化后的字符串
$string = $this->typography->format_characters($string);4.1 官方文档列出的 5 类转换
- 弯引号:引号转换为方向正确的弯引号实体,标签内的引号除外;
- 弯撇号:撇号转换为弯撇号实体;
- 长破折号:双连字符(
-- this或like--this)转换为 em-dash; - 省略号:单词前或后的三个连续句点转换为
…; - 句后双空格:句子后的双空格转换为不间断空格。
实现上,转换表是一个静态正则数组(Typography.php),只在首次调用时构建,后续调用直接复用,避免重复创建:
static $table; if ( ! isset($table)) { $table = array( // 嵌套智能引号(英文语法最多两层,单引号通常在外部) '/\'"(\s|$)/' => '’”$1', '/(^|\s|<p>)\'"/' => '$1‘“', ... // 单引号智能引号 '/\'(\s|$)/' => '’$1', '/(^|\s|<p>)\'/' => '$1‘', ... // 双引号智能引号 '/"(\s|$)/' => '”$1', '/(^|\s|<p>)"/' => '$1“', ... // 撇号 "/(\w)'(\w)/" => '$1’$2', // 破折号与省略号 '/\s?\-\-\s?/' => '—', '/(\w)\.{3}/' => '$1…', // 句子后的双空格 '/(\W) /' => '$1 ', // 非实体 & 符号 '/&(?!#?[a-zA-Z0-9]{2,};)/' => '&' ); } return preg_replace(array_keys($table), $table, $str);引号方向判断的核心规则(源码注释明确说明):空白是决定引号弯向的主要因素,标点等非单词字符是空白之后的次要因素。因此"testing" in "theory"中的引号能正确识别为开/闭引号,而不是全部转成同一种方向的字符。
4.2 字符实体对照
format_characters()使用的实体及其对应字符如下:
| 输入 | 输出实体 | 含义 |
|---|---|---|
"(句首/空白前) | “ | 左双弯引号 |
"(句尾/空白后) | ” | 右双弯引号 |
'(词首) | ‘ | 左单弯引号 |
'(词尾/词中) | ’ | 右单弯引号 / 撇号 |
-- | — | em-dash 长破折号 |
...(\w后三个句点) | … | 省略号 |
| 句子后双空格 | | 不间断空格 + 空格 |
非实体& | & | 转义与符号 |
注意最后一条:&、 等已是合法实体的写法不会被二次转义。这一点在 测试用例 中有明确验证:
'&' => '&', '&' => '&', // 已有实体不再重复转义 ' '=> ' ', '--' => '—', 'foo...'=> 'foo…', 'foo..' => 'foo..', // 两个句点不转换 'test. new' => 'test. new',4.3 与auto_typography()的关系
auto_typography()在完成段落与换行处理后,内部最后一步就是调用format_characters()(Typography.php):
$str = $this->format_characters($str);因此可以这样理解两者的分工:format_characters()是"字符级排版引擎",auto_typography()是"结构级 + 字符级"的完整排版器。如果你的内容已经是结构完整的 HTML(例如由富文本编辑器生成),只想统一字符排版,可以直接使用format_characters()以避免段落结构被改写。
五、方法详解:nl2br_except_pre($str)
该方法将换行转换为<br />标签,但<pre>标签内的换行保持原样。
- 参数:
string $str输入字符串 - 返回:
string格式化后的字符串
$string = $this->typography->nl2br_except_pre($string);它与 PHP 原生nl2br()行为一致,唯一区别是忽略<pre>标签。实现思路非常巧妙(Typography.php):按pre>字符串切分输入,偶数下标片段(pre开标签之前、</pre之后的部分)调用原生nl2br(),奇数下标片段(<pre>与</pre>之间的内容)原样保留:
public function nl2br_except_pre($str) { $newstr = ''; for ($ex = explode('pre>', $str), $ct = count($ex), $i = 0; $i < $ct; $i++) { $newstr .= (($i % 2) === 0) ? nl2br($ex[$i]) : $ex[$i]; if ($ct - 1 !== $i) { $newstr .= 'pre>'; } } return $newstr; }测试用例 验证了行为:<pre>块内部的空行与换行全部原样保留,而块外的每个换行都被转换为<br />(包括</pre>之后紧接着的换行)。
六、辅助函数:无需显式加载库的快捷调用
除了通过$this->typography调用方法,框架还在 system/helpers/typography_helper.php 中提供了对应的辅助函数,加载方式:
$this->load->helper('typography');6.1auto_typography($str[, $reduce_linebreaks = FALSE])
CI_Typography::auto_typography()的别名函数,内部自动加载 Typography 库并委托调用(typography_helper.php):
function auto_typography($str, $reduce_linebreaks = FALSE) { $CI =& get_instance(); $CI->load->library('typography'); return $CI->typography->auto_typography($str, $reduce_linebreaks); }用法:
$string = auto_typography($string);6.2nl2br_except_pre($str)
同样是对库方法的封装(typography_helper.php):
$string = nl2br_except_pre($string);6.3entity_decode($str, $charset = NULL)
该文件还提供了一个相关函数entity_decode(),用于把 HTML 实体解码回字符。注意它并非 Typography 库的方法,而是CI_Security::entity_decode()的别名(typography_helper.php),详见安全库文档。由于auto_typography()/format_characters()会把引号等字符转成实体,entity_decode()常与之配套用于"排版 → 存储 → 反向还原"的场景。
七、综合实战:一个完整的排版流程示例
把本文介绍的能力组合起来,一个典型的"用户评论排版"流程如下:
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Comments extends CI_Controller { public function save() { $this->load->library('typography'); $this->load->helper('typography'); // 1. 从表单获取原始输入 $raw = $this->input->post('body'); // 2. 如需与模板解析器配合,先开启花括号引号保护 // $this->typography->protect_braced_quotes = TRUE; // 3. 执行完整排版(压缩多余换行) $formatted = $this->typography->auto_typography($raw, TRUE); // 或使用辅助函数等价写法: // $formatted = auto_typography($raw, TRUE); // 4. 存入数据库,展示时直接输出 $formatted $this->db->insert('comments', array('body' => $formatted)); } public function show() { // 读取已排版内容直接输出(不再重复排版,避免性能开销) $comment = $this->db->get_where('comments', array('id' => 1))->row(); echo $comment->body; } }如果只想把换行转<br />而保留pre块原样(例如输出用户贴的代码片段),则:
$string = nl2br_except_pre($string);八、总结与使用建议
Typography 库以三个公开方法覆盖了从"纯文本"到"排版 HTML"的完整链路:
auto_typography($str, $reduce_linebreaks):结构级 + 字符级完整排版,适合直接渲染用户内容;format_characters($str):仅字符级转换,适合已有完整 HTML 结构的场景;nl2br_except_pre($str):轻量换行转换,保留<pre>内容。
使用时的三条关键建议(均有文档或源码依据):
- 注意性能:官方文档明确提示
auto_typography()属于处理器密集型操作,建议配合缓存或"写入时排版"策略; - 保护模板变量:与 Parser 模板解析库 联用时,务必按需开启
$protect_braced_quotes,否则花括号内的引号会被实体化导致变量无法匹配; - 善用测试预期:Typography_test.php 中每个断言都可当作"输入 → 期望输出"的参考样例,在接入你自己的内容格式前,可先对照这些用例确认行为是否符合预期。
- 后端
- Web框架
【免费下载链接】CodeIgniter
Open Source PHP Framework (originally from EllisLab)
相关推荐
CodeIgniter Typography Helper 详解:语义化文本格式化与排版增强实战
CodeIgniter Typography Helper 详解:语义化文本格式化与排版增强实战 导读 Typography Helper(排版辅助函数)是 C
后端Web框架ant-design-vue Typography 排版组件完全指南:文本、标题、段落与可交互能力深度解析
ant design vue Typography 排版组件完全指南:文本、标题、段落与可交互能力深度解析 导读 Typography 是 ant design
前端UI组件设计系统Skia文本排版终极指南:从RTL到LTR多语言段落处理
Skia文本排版终极指南:从RTL到LTR多语言段落处理 Skia作为Google开发的完整2D图形库,提供了强大的文本排版功能,特别是针对多语言环境下的双向文
图形学图像处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考