feat: support compression rules for punctuation marks
This commit is contained in:
parent
5a7182fcca
commit
911ddb7170
10 changed files with 194 additions and 60 deletions
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
预览:[https://sivan.github.io/heti/](https://sivan.github.io/heti/)
|
预览:[https://sivan.github.io/heti/](https://sivan.github.io/heti/)
|
||||||
|
|
||||||
|
![Preview](https://raw.githubusercontent.com/sivan/heti/master/_site/assets/screenshot-grid.png)
|
||||||
|
|
||||||
主要特性:
|
主要特性:
|
||||||
- 贴合网格的排版;
|
- 贴合网格的排版;
|
||||||
- 全标签样式美化;
|
- 全标签样式美化;
|
||||||
|
@ -11,7 +13,7 @@
|
||||||
- 预置多种排版样式(行间注、多栏、竖排等);
|
- 预置多种排版样式(行间注、多栏、竖排等);
|
||||||
- 多种预设字体族(仅限桌面端);
|
- 多种预设字体族(仅限桌面端);
|
||||||
- 简/繁体中文支持;
|
- 简/繁体中文支持;
|
||||||
- 中西文混排美化(基于JavaScript脚本实现);
|
- 中西文混排美化,不再手敲空格👏(基于JavaScript脚本);
|
||||||
- 兼容 *normalize.css*、*CSS Reset* 等常见样式重置;
|
- 兼容 *normalize.css*、*CSS Reset* 等常见样式重置;
|
||||||
- 移动端支持;
|
- 移动端支持;
|
||||||
- ……
|
- ……
|
||||||
|
|
BIN
_site/assets/screenshot-grid.png
Normal file
BIN
_site/assets/screenshot-grid.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 KiB |
BIN
_site/assets/screenshot.png
Normal file
BIN
_site/assets/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 244 KiB |
|
@ -654,28 +654,32 @@
|
||||||
* Add right spacing between CJK & ANS characters
|
* Add right spacing between CJK & ANS characters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 正则表达式来自 pangu.js https://github.com/vinta/pangu.js
|
const hasOwn = {}.hasOwnProperty;
|
||||||
const CJK = '\u2e80-\u2eff\u2f00-\u2fdf\u3040-\u309f\u30a0-\u30fa\u30fc-\u30ff\u3100-\u312f\u3200-\u32ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff';
|
|
||||||
const A = 'A-Za-z\u0370-\u03ff';
|
|
||||||
const N = '0-9';
|
|
||||||
const S = '`~!@#\\$%\\^&\\*\\(\\)-_=\\+\\[\\]{}\\\\\\|;:\'",<.>\\/\\?';
|
|
||||||
const ANS = `${A}${N}${S}`;
|
|
||||||
const HETI_NON_CONTIGUOUS_ELEMENTS = Object.assign({}, findAndReplaceDOMText.NON_CONTIGUOUS_PROSE_ELEMENTS, {
|
const HETI_NON_CONTIGUOUS_ELEMENTS = Object.assign({}, findAndReplaceDOMText.NON_CONTIGUOUS_PROSE_ELEMENTS, {
|
||||||
// Inline elements
|
|
||||||
ins: 1, del: 1, s: 1,
|
ins: 1, del: 1, s: 1,
|
||||||
});
|
});
|
||||||
const HETI_SKIPPED_ELEMENTS = Object.assign({}, findAndReplaceDOMText.NON_PROSE_ELEMENTS, {
|
const HETI_SKIPPED_ELEMENTS = Object.assign({}, findAndReplaceDOMText.NON_PROSE_ELEMENTS, {
|
||||||
pre: 1, code: 1, sup: 1, sub: 1,
|
pre: 1, code: 1, sup: 1, sub: 1, 'heti-spacing': 1, 'heti-close': 1,
|
||||||
// Heti elements
|
|
||||||
'heti-spacing': 1,
|
|
||||||
});
|
});
|
||||||
const HETI_SKIPPED_CLASS = 'heti-skip';
|
const HETI_SKIPPED_CLASS = 'heti-skip';
|
||||||
const hasOwn = {}.hasOwnProperty;
|
|
||||||
const REG_FULL = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
// 部分正则表达式修改自 pangu.js https://github.com/vinta/pangu.js
|
||||||
const REG_FULL_FIX = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
const CJK = '\u2e80-\u2eff\u2f00-\u2fdf\u3040-\u309f\u30a0-\u30fa\u30fc-\u30ff\u3100-\u312f\u3200-\u32ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff';
|
||||||
const REG_START = `([${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
const A = 'A-Za-z\u0080-\u00ff\u0370-\u03ff';
|
||||||
const REG_END = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;
|
const N = '0-9';
|
||||||
const REG_END_FIX = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;
|
const S = '`~!@#\\$%\\^&\\*\\(\\)-_=\\+\\[\\]{}\\\\\\|;:\'",<.>\\/\\?';
|
||||||
|
const ANS = `${A}${N}${S}`;
|
||||||
|
const REG_CJK_FULL = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
||||||
|
const REG_CJK_START = `([${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
||||||
|
const REG_CJK_END = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;
|
||||||
|
const REG_CJK_FULL_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;
|
||||||
|
const REG_CJK_END_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;
|
||||||
|
const REG_BD_STOP = `。.,、:;!‼?⁇`;
|
||||||
|
const REG_BD_SEP = `·・‧`;
|
||||||
|
const REG_BD_OPEN = `「『(《〈【〖〔[{`;
|
||||||
|
const REG_BD_CLOSE = `」』)》〉】〗〕]}`;
|
||||||
|
const REG_BD_START = `${REG_BD_OPEN}${REG_BD_CLOSE}`;
|
||||||
|
const REG_BD_END = `${REG_BD_STOP}${REG_BD_OPEN}${REG_BD_CLOSE}`;
|
||||||
|
|
||||||
class Heti {
|
class Heti {
|
||||||
constructor (rootSelector) {
|
constructor (rootSelector) {
|
||||||
|
@ -689,13 +693,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rootSelector = rootSelector || '.heti';
|
this.rootSelector = rootSelector || '.heti';
|
||||||
this.REG_FULL = new RegExp(supportLookBehind ? REG_FULL : REG_FULL_FIX, 'g');
|
this.REG_FULL = new RegExp(supportLookBehind ? REG_CJK_FULL : REG_CJK_FULL_WITHOUT_LOOKBEHIND, 'g');
|
||||||
this.REG_START = new RegExp(REG_START, 'g');
|
this.REG_START = new RegExp(REG_CJK_START, 'g');
|
||||||
this.REG_END = new RegExp(supportLookBehind ? REG_END : REG_END_FIX, 'g');
|
this.REG_END = new RegExp(supportLookBehind ? REG_CJK_END : REG_CJK_END_WITHOUT_LOOKBEHIND, 'g');
|
||||||
this.offsetWidth = supportLookBehind ? 0 : 1;
|
this.offsetWidth = supportLookBehind ? 0 : 1;
|
||||||
this.funcForceContext = function forceContext (el) {
|
this.funcForceContext = function forceContext (el) {
|
||||||
return hasOwn.call(HETI_NON_CONTIGUOUS_ELEMENTS, el.nodeName.toLowerCase())
|
return hasOwn.call(HETI_NON_CONTIGUOUS_ELEMENTS, el.nodeName.toLowerCase())
|
||||||
// return true
|
|
||||||
};
|
};
|
||||||
this.funcFilterElements = function filterElements (el) {
|
this.funcFilterElements = function filterElements (el) {
|
||||||
return (
|
return (
|
||||||
|
@ -716,8 +719,8 @@
|
||||||
forceContext: this.funcForceContext,
|
forceContext: this.funcForceContext,
|
||||||
filterElements: this.funcFilterElements,
|
filterElements: this.funcFilterElements,
|
||||||
};
|
};
|
||||||
const getWrapper = function (classList, text) {
|
const getWrapper = function (elementName, classList, text) {
|
||||||
const $$r = document.createElement('heti-spacing');
|
const $$r = document.createElement(elementName);
|
||||||
$$r.className = classList;
|
$$r.className = classList;
|
||||||
$$r.textContent = text.trim();
|
$$r.textContent = text.trim();
|
||||||
return $$r
|
return $$r
|
||||||
|
@ -725,18 +728,30 @@
|
||||||
|
|
||||||
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_FULL,
|
find: this.REG_FULL,
|
||||||
replace: portion => getWrapper('heti-spacing-start heti-spacing-end', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-start heti-spacing-end', portion.text),
|
||||||
offset: this.offsetWidth,
|
offset: this.offsetWidth,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_START,
|
find: this.REG_START,
|
||||||
replace: portion => getWrapper('heti-spacing-start', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-start', portion.text),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_END,
|
find: this.REG_END,
|
||||||
replace: portion => getWrapper('heti-spacing-end', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-end', portion.text),
|
||||||
|
offset: this.offsetWidth,
|
||||||
|
}));
|
||||||
|
|
||||||
|
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
||||||
|
find: new RegExp(`([${REG_BD_STOP}])(?=[${REG_BD_START}])|([${REG_BD_OPEN}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_END}])`,'g'),
|
||||||
|
replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-half', portion.text),
|
||||||
|
offset: this.offsetWidth,
|
||||||
|
}));
|
||||||
|
|
||||||
|
findAndReplaceDOMText($$elm, Object.assign({}, commonConfig, {
|
||||||
|
find: new RegExp(`([${REG_BD_SEP}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_SEP}])`,'g'),
|
||||||
|
replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-quarter', portion.text),
|
||||||
offset: this.offsetWidth,
|
offset: this.offsetWidth,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -802,3 +802,15 @@
|
||||||
.heti .heti-spacing-end {
|
.heti .heti-spacing-end {
|
||||||
margin-inline-start: 0.25em;
|
margin-inline-start: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heti heti-adjacent {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heti .heti-adjacent-half {
|
||||||
|
margin-inline-end: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heti .heti-adjacent-quarter {
|
||||||
|
margin-inline-end: -0.25em;
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<main class="container">
|
<main class="container">
|
||||||
<article class="article heti heti--classic">
|
<article class="article heti heti--classic">
|
||||||
<h1>赫蹏</h1>
|
<h1>赫蹏</h1>
|
||||||
<blockquote>古代称用以书写的小幅绢帛。后亦以借指纸。《汉书·外戚传下·孝成赵皇后》:<q>武(籍武 )发篋中,有裹药二枚,赫蹏书。</q><u>颜师古</u>注:<q><u>邓展</u>曰:<q>赫音兄弟鬩墙之鬩。</q><u>应劭</u>曰:<q>赫蹏,薄小纸也。</q></q><u>宋</u><u>赵彦卫</u> 《云麓漫钞》卷七:<q>《赵后传》所谓『赫蹏』者,注云<q>薄小纸</q>,然其寔亦縑帛。</q></blockquote>
|
<blockquote>古代称用以书写的小幅绢帛。后亦以借指纸。《汉书·外戚传下·孝成赵皇后》:「武(籍武 )发篋中,有裹药二枚,赫蹏书。」<u>颜师古</u>注:「<u>邓展</u>曰:『赫音兄弟鬩墙之鬩。』<u>应劭</u>曰:『赫蹏,薄小纸也。』」<u>宋</u><u>赵彦卫</u> 《云麓漫钞》卷七:「《赵后传》所谓『赫蹏』者,注云『薄小纸』,然其寔亦縑帛。」</blockquote>
|
||||||
|
|
||||||
<nav class="article__toc heti-skip">
|
<nav class="article__toc heti-skip">
|
||||||
<details open>
|
<details open>
|
||||||
|
@ -55,7 +55,8 @@
|
||||||
<li>预置多种排版样式(行间注、多栏、竖排等);</li>
|
<li>预置多种排版样式(行间注、多栏、竖排等);</li>
|
||||||
<li>多种预设字体族(仅限桌面端);</li>
|
<li>多种预设字体族(仅限桌面端);</li>
|
||||||
<li>简/繁体中文支持;</li>
|
<li>简/繁体中文支持;</li>
|
||||||
<li>中西文混排美化(基于JavaScript脚本实现);</li>
|
<li>中西文混排美化,不再手敲空格(基于JavaScript脚本);</li>
|
||||||
|
<li>标点挤压(基于JavaScript脚本);</li>
|
||||||
<li>兼容<i>normalize.css</i>、<i>CSS Reset<sup><a id="ref-01" href="#fn-01">[1]</a></sup></i>等常见样式重置;</li>
|
<li>兼容<i>normalize.css</i>、<i>CSS Reset<sup><a id="ref-01" href="#fn-01">[1]</a></sup></i>等常见样式重置;</li>
|
||||||
<li>移动端支持;</li>
|
<li>移动端支持;</li>
|
||||||
<li>……</li>
|
<li>……</li>
|
||||||
|
@ -464,15 +465,89 @@
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<h3 id="javascript">增强脚本<sup>beta</sup><a class="anchor" href="#javascript">#</a></h3>
|
<h3 id="javascript">增强脚本<sup>beta</sup><a class="anchor" href="#javascript">#</a></h3>
|
||||||
<p>由于部分CSS特性尚未有浏览器,所以可选择使用增强脚本进行中西文混排优化。无论你的输入习惯是否在中西文之间加入「空格」,都会统一成一样的间距(1/4字宽的空白)。</p>
|
<p>由于部分CSS特性尚未有浏览器支持等原因,可选择使用增强脚本进行排版效果优化。目前增强脚本的功能有:</p>
|
||||||
|
<ul>
|
||||||
|
<li>中英文混排优化:无论你的输入习惯是否在中西文之间留有「空格」<sup><a id="ref-03" href="#fn-03">[3]</a></sup>,都会统一成标准间距(¼字宽的空白);</li>
|
||||||
|
<li>标点挤压:自动对中文标点进行½字宽的挤压(间隔符挤压¼字宽)。</li>
|
||||||
|
</ul>
|
||||||
<details>
|
<details>
|
||||||
<summary>查看使用说明</summary>
|
<summary>使用方法与效果</summary>
|
||||||
<p>在页面的<code></body></code>标签前引入JavaScript脚本:</p>
|
<p>在页面的<code></body></code>标签前引入JavaScript脚本:</p>
|
||||||
<pre><code><script src="//unpkg.com/heti/umd/heti-addon.min.js"></script>
|
<pre><code><script src="//unpkg.com/heti/umd/heti-addon.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
const heti = new Heti();
|
const heti = new Heti('.heti');
|
||||||
heti.autoSpacing();
|
heti.autoSpacing();
|
||||||
</script></code></pre>
|
</script></code></pre>
|
||||||
|
<section>
|
||||||
|
<table>
|
||||||
|
<caption>增强脚本示例表</caption>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">中英文间距</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 80px;">默认文本</th>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="heti-skip"><b>Hello, world!</b>是大家第一次学习Programming时最常写的demo,它看似简单,但对有些人来说寥寥数语有时也会产生bug。</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>脚本效果</th>
|
||||||
|
<td colspan="3">
|
||||||
|
<div><b>Hello, world!</b>是大家第一次学习Programming时最常写的demo,它看似简单,但对有些人来说寥寥数语有时也会产生bug。</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">标点挤压</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>默认文本</th>
|
||||||
|
<td colspan="3">
|
||||||
|
<blockquote class="heti-skip" style="margin-inline-start: 0; margin-inline-end: 0;">古代称用以书写的小幅绢帛。后亦以借指纸<mark>。《</mark>汉书·外戚传下·孝成赵皇后<mark>》:「</mark>武(籍武 )发篋中,有裹药二枚,赫蹏书。」<u>颜师古</u>注:「<u>邓展</u>曰:『赫音兄弟鬩墙之鬩。』<u>应劭</u>曰:『赫蹏,薄小纸也。』」<u>宋</u><u>赵彦卫</u> 《云麓漫钞》卷七:「《赵后传》所谓『赫蹏』者,注云『薄小纸』,然其寔亦縑帛。」</blockquote>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>脚本效果</th>
|
||||||
|
<td colspan="3">
|
||||||
|
<blockquote style="margin-inline-start: 0; margin-inline-end: 0;">古代称用以书写的小幅绢帛。后亦以借指纸<mark>。《</mark>汉书·外戚传下·孝成赵皇后<mark>》:「</mark>武(籍武 )发篋中,有裹药二枚,赫蹏书。」<u>颜师古</u>注:「<u>邓展</u>曰:『赫音兄弟鬩墙之鬩。』<u>应劭</u>曰:『赫蹏,薄小纸也。』」<u>宋</u><u>赵彦卫</u> 《云麓漫钞》卷七:「《赵后传》所谓『赫蹏』者,注云『薄小纸』,然其寔亦縑帛。」</blockquote>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<!--
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">标点挤压</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>默认文本</th>
|
||||||
|
<td>
|
||||||
|
<ul class="heti-skip">
|
||||||
|
<li>结束。」</li>
|
||||||
|
<li>结束」,</li>
|
||||||
|
<li>开始。「</li>
|
||||||
|
<li>连接」「</li>
|
||||||
|
<li>连续「『</li>
|
||||||
|
<li>连续』」</li>
|
||||||
|
<li>间隔号」·</li>
|
||||||
|
<li>间隔号·「</li>
|
||||||
|
<li>不改「」</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<th>脚本效果</th>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
<li>结束。」</li>
|
||||||
|
<li>结束」,</li>
|
||||||
|
<li>开始。「</li>
|
||||||
|
<li>连接」「</li>
|
||||||
|
<li>连续「『</li>
|
||||||
|
<li>连续』」</li>
|
||||||
|
<li>间隔号」·</li>
|
||||||
|
<li>间隔号·「</li>
|
||||||
|
<li>不改「」</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
-->
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<h3 id="license">开源协议<a class="anchor" href="#tags">#</a></h3>
|
<h3 id="license">开源协议<a class="anchor" href="#tags">#</a></h3>
|
||||||
|
@ -482,8 +557,8 @@
|
||||||
|
|
||||||
<h2 id="wip">待开发功能<a class="anchor" href="#wip">#</a></h2>
|
<h2 id="wip">待开发功能<a class="anchor" href="#wip">#</a></h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>☑ 标点挤压</li>
|
<li>☑ 自适应黑暗模式</li>
|
||||||
<li>☑ 标点悬挂</li>
|
<li>✅ 标点挤压</li>
|
||||||
<li>✅ 中、西文混排</li>
|
<li>✅ 中、西文混排</li>
|
||||||
<li>✅ 诗词版式</li>
|
<li>✅ 诗词版式</li>
|
||||||
<li>✅ 行间注版式</li>
|
<li>✅ 行间注版式</li>
|
||||||
|
@ -499,6 +574,9 @@
|
||||||
<a href="#ref-02" title="移至">^</a>
|
<a href="#ref-02" title="移至">^</a>
|
||||||
《中文排版需求》:https://w3c.github.io/clreq/
|
《中文排版需求》:https://w3c.github.io/clreq/
|
||||||
</li>
|
</li>
|
||||||
|
<li id="fn-03">
|
||||||
|
<a href="#ref-03" title="移至">^</a>在当下前端技术尚不能完美解决中西文混排间距的情况下,常见的输入习惯是手动在中西文间加入空格(https://github.com/vinta/pangu.js)。这样做的弊端一是间距不可控(有时显得过大),二是通过空格符来排版只能算无奈之举。好消息是在最新的macOS、iOS中,使用原生语言开发的文本区域会自动处理中西文混排的间距(无论是否加空格),期待不用手敲空格的日子早日到来。
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</footer>
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -5,28 +5,32 @@
|
||||||
|
|
||||||
import Finder from 'heti-findandreplacedomtext'
|
import Finder from 'heti-findandreplacedomtext'
|
||||||
|
|
||||||
// 正则表达式来自 pangu.js https://github.com/vinta/pangu.js
|
const hasOwn = {}.hasOwnProperty
|
||||||
const CJK = '\u2e80-\u2eff\u2f00-\u2fdf\u3040-\u309f\u30a0-\u30fa\u30fc-\u30ff\u3100-\u312f\u3200-\u32ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff'
|
|
||||||
const A = 'A-Za-z\u0370-\u03ff'
|
|
||||||
const N = '0-9'
|
|
||||||
const S = '`~!@#\\$%\\^&\\*\\(\\)-_=\\+\\[\\]{}\\\\\\|;:\'",<.>\\/\\?'
|
|
||||||
const ANS = `${A}${N}${S}`
|
|
||||||
const HETI_NON_CONTIGUOUS_ELEMENTS = Object.assign({}, Finder.NON_CONTIGUOUS_PROSE_ELEMENTS, {
|
const HETI_NON_CONTIGUOUS_ELEMENTS = Object.assign({}, Finder.NON_CONTIGUOUS_PROSE_ELEMENTS, {
|
||||||
// Inline elements
|
|
||||||
ins: 1, del: 1, s: 1,
|
ins: 1, del: 1, s: 1,
|
||||||
})
|
})
|
||||||
const HETI_SKIPPED_ELEMENTS = Object.assign({}, Finder.NON_PROSE_ELEMENTS, {
|
const HETI_SKIPPED_ELEMENTS = Object.assign({}, Finder.NON_PROSE_ELEMENTS, {
|
||||||
pre: 1, code: 1, sup: 1, sub: 1,
|
pre: 1, code: 1, sup: 1, sub: 1, 'heti-spacing': 1, 'heti-close': 1,
|
||||||
// Heti elements
|
|
||||||
'heti-spacing': 1,
|
|
||||||
})
|
})
|
||||||
const HETI_SKIPPED_CLASS = 'heti-skip'
|
const HETI_SKIPPED_CLASS = 'heti-skip'
|
||||||
const hasOwn = {}.hasOwnProperty
|
|
||||||
const REG_FULL = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
// 部分正则表达式修改自 pangu.js https://github.com/vinta/pangu.js
|
||||||
const REG_FULL_FIX = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
const CJK = '\u2e80-\u2eff\u2f00-\u2fdf\u3040-\u309f\u30a0-\u30fa\u30fc-\u30ff\u3100-\u312f\u3200-\u32ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff'
|
||||||
const REG_START = `([${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
const A = 'A-Za-z\u0080-\u00ff\u0370-\u03ff'
|
||||||
const REG_END = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`
|
const N = '0-9'
|
||||||
const REG_END_FIX = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`
|
const S = '`~!@#\\$%\\^&\\*\\(\\)-_=\\+\\[\\]{}\\\\\\|;:\'",<.>\\/\\?'
|
||||||
|
const ANS = `${A}${N}${S}`
|
||||||
|
const REG_CJK_FULL = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
||||||
|
const REG_CJK_START = `([${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
||||||
|
const REG_CJK_END = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`
|
||||||
|
const REG_CJK_FULL_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`
|
||||||
|
const REG_CJK_END_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`
|
||||||
|
const REG_BD_STOP = `。.,、:;!‼?⁇`
|
||||||
|
const REG_BD_SEP = `·・‧`
|
||||||
|
const REG_BD_OPEN = `「『(《〈【〖〔[{`
|
||||||
|
const REG_BD_CLOSE = `」』)》〉】〗〕]}`
|
||||||
|
const REG_BD_START = `${REG_BD_OPEN}${REG_BD_CLOSE}`
|
||||||
|
const REG_BD_END = `${REG_BD_STOP}${REG_BD_OPEN}${REG_BD_CLOSE}`
|
||||||
|
|
||||||
class Heti {
|
class Heti {
|
||||||
constructor (rootSelector) {
|
constructor (rootSelector) {
|
||||||
|
@ -40,13 +44,12 @@ class Heti {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rootSelector = rootSelector || '.heti'
|
this.rootSelector = rootSelector || '.heti'
|
||||||
this.REG_FULL = new RegExp(supportLookBehind ? REG_FULL : REG_FULL_FIX, 'g')
|
this.REG_FULL = new RegExp(supportLookBehind ? REG_CJK_FULL : REG_CJK_FULL_WITHOUT_LOOKBEHIND, 'g')
|
||||||
this.REG_START = new RegExp(REG_START, 'g')
|
this.REG_START = new RegExp(REG_CJK_START, 'g')
|
||||||
this.REG_END = new RegExp(supportLookBehind ? REG_END : REG_END_FIX, 'g')
|
this.REG_END = new RegExp(supportLookBehind ? REG_CJK_END : REG_CJK_END_WITHOUT_LOOKBEHIND, 'g')
|
||||||
this.offsetWidth = supportLookBehind ? 0 : 1
|
this.offsetWidth = supportLookBehind ? 0 : 1
|
||||||
this.funcForceContext = function forceContext (el) {
|
this.funcForceContext = function forceContext (el) {
|
||||||
return hasOwn.call(HETI_NON_CONTIGUOUS_ELEMENTS, el.nodeName.toLowerCase())
|
return hasOwn.call(HETI_NON_CONTIGUOUS_ELEMENTS, el.nodeName.toLowerCase())
|
||||||
// return true
|
|
||||||
}
|
}
|
||||||
this.funcFilterElements = function filterElements (el) {
|
this.funcFilterElements = function filterElements (el) {
|
||||||
return (
|
return (
|
||||||
|
@ -67,8 +70,8 @@ class Heti {
|
||||||
forceContext: this.funcForceContext,
|
forceContext: this.funcForceContext,
|
||||||
filterElements: this.funcFilterElements,
|
filterElements: this.funcFilterElements,
|
||||||
}
|
}
|
||||||
const getWrapper = function (classList, text) {
|
const getWrapper = function (elementName, classList, text) {
|
||||||
const $$r = document.createElement('heti-spacing')
|
const $$r = document.createElement(elementName)
|
||||||
$$r.className = classList
|
$$r.className = classList
|
||||||
$$r.textContent = text.trim()
|
$$r.textContent = text.trim()
|
||||||
return $$r
|
return $$r
|
||||||
|
@ -76,18 +79,30 @@ class Heti {
|
||||||
|
|
||||||
Finder($$elm, Object.assign({}, commonConfig, {
|
Finder($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_FULL,
|
find: this.REG_FULL,
|
||||||
replace: portion => getWrapper('heti-spacing-start heti-spacing-end', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-start heti-spacing-end', portion.text),
|
||||||
offset: this.offsetWidth,
|
offset: this.offsetWidth,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
Finder($$elm, Object.assign({}, commonConfig, {
|
Finder($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_START,
|
find: this.REG_START,
|
||||||
replace: portion => getWrapper('heti-spacing-start', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-start', portion.text),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
Finder($$elm, Object.assign({}, commonConfig, {
|
Finder($$elm, Object.assign({}, commonConfig, {
|
||||||
find: this.REG_END,
|
find: this.REG_END,
|
||||||
replace: portion => getWrapper('heti-spacing-end', portion.text),
|
replace: portion => getWrapper('heti-spacing', 'heti-spacing-end', portion.text),
|
||||||
|
offset: this.offsetWidth,
|
||||||
|
}))
|
||||||
|
|
||||||
|
Finder($$elm, Object.assign({}, commonConfig, {
|
||||||
|
find: new RegExp(`([${REG_BD_STOP}])(?=[${REG_BD_START}])|([${REG_BD_OPEN}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_END}])`,'g'),
|
||||||
|
replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-half', portion.text),
|
||||||
|
offset: this.offsetWidth,
|
||||||
|
}))
|
||||||
|
|
||||||
|
Finder($$elm, Object.assign({}, commonConfig, {
|
||||||
|
find: new RegExp(`([${REG_BD_SEP}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_SEP}])`,'g'),
|
||||||
|
replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-quarter', portion.text),
|
||||||
offset: this.offsetWidth,
|
offset: this.offsetWidth,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,16 @@
|
||||||
.heti-spacing-end {
|
.heti-spacing-end {
|
||||||
margin-inline-start: 0.25em;
|
margin-inline-start: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
heti-adjacent {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heti-adjacent-half {
|
||||||
|
margin-inline-end: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heti-adjacent-quarter {
|
||||||
|
margin-inline-end: -0.25em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "heti",
|
"name": "heti",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "heti",
|
"name": "heti",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"description": "赫蹏是专为中文内容展示设计的排版样式增强。它基于通行的中文排版规范而来,可以为网站的读者带来更好的文章阅读体验。",
|
"description": "赫蹏是专为中文内容展示设计的排版样式增强。它基于通行的中文排版规范而来,可以为网站的读者带来更好的文章阅读体验。",
|
||||||
"main": "lib/heti.scss",
|
"main": "lib/heti.scss",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
Loading…
Reference in a new issue