Skip to content

Commit 663aff5

Browse files
committed
feat: Improve Pangu spacing service robustness and logging
1 parent e4e7f1d commit 663aff5

10 files changed

Lines changed: 316 additions & 140 deletions

File tree

README.md

Lines changed: 82 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,17 @@
7474
- [文章字数统计 API](#文章字数统计-api)
7575
- [HTML 内容字数统计 API](#html-内容字数统计-api)
7676
- [渲染 API](#渲染-api)
77-
- [代码高亮 API](#代码高亮-api)
7877
- [中英文混排格式化 API](#中英文混排格式化-api)
78+
- [代码高亮 API](#代码高亮-api)
7979
- [处理器文档](#处理器文档)
80+
- [中英文混排格式化处理器](#中英文混排格式化处理器)
81+
- [功能说明](#功能说明)
82+
- [配置选项](#配置选项)
83+
- [补充说明](#补充说明)
8084
- [代码高亮处理器](#代码高亮处理器)
8185
- [特点](#特点)
82-
- [配置选项](#配置选项)
86+
- [配置选项](#配置选项-1)
8387
- [支持的主题](#支持的主题)
84-
- [补充说明](#补充说明)
85-
- [中英文混排格式化处理器](#中英文混排格式化处理器)
86-
- [功能说明](#功能说明)
87-
- [使用说明](#使用说明)
8888
- [补充说明](#补充说明-1)
8989
- [版本说明](#版本说明)
9090
- [轻量版的优势](#轻量版的优势)
@@ -402,42 +402,6 @@ extraApiStatsFinder.getContentWordCount({
402402

403403
### 渲染 API
404404

405-
**Finder 名称:** `extraApiRenderFinder`
406-
407-
#### 代码高亮 API
408-
409-
```javascript
410-
extraApiRenderFinder.renderCodeHtml(htmlContent)
411-
```
412-
413-
**参数**
414-
415-
- `htmlContent`
416-
- 类型:`string`
417-
- 解释:包含代码块的 HTML 内容,通常是文章或页面的内容字段。
418-
419-
**返回值**
420-
421-
- 类型:`string`
422-
- 解释:渲染后的 HTML 内容,渲染样式已内联,渲染失败时返回原始内容
423-
424-
**描述**
425-
426-
- 功能特性:
427-
-[处理器文档 - 代码高亮(通过 Shiki.js 渲染)](#代码高亮处理器) 中描述的功能特性一致。也受同样的配置项影响。
428-
429-
**使用示例**
430-
431-
```html
432-
<!--/* 渲染文章内容中的代码块,下面这段代码可直接用于 /templates/post.html */-->
433-
<div th:utext="${extraApiRenderFinder.renderCodeHtml(post.content?.content)}"></div>
434-
435-
<!--/* 在模板中使用,下面这段代码可直接用于 /templates/moment.html */-->
436-
<div th:with="renderedContent=${extraApiRenderFinder.renderCodeHtml(moment.spec.content?.html)}">
437-
<div th:utext="${renderedContent}"></div>
438-
</div>
439-
```
440-
441405
#### 中英文混排格式化 API
442406

443407
**Finder 名称:** `extraApiPanguFinder`
@@ -542,8 +506,83 @@ extraApiPanguFinder.spacingText(text)
542506
- HTML 解析失败时返回原始内容
543507
- 不会抛出异常,保证页面渲染稳定性
544508

509+
#### 代码高亮 API
510+
511+
**Finder 名称:** `extraApiRenderFinder`
512+
513+
```javascript
514+
extraApiRenderFinder.renderCodeHtml(htmlContent)
515+
```
516+
517+
**参数**
518+
519+
- `htmlContent`
520+
- 类型:`string`
521+
- 解释:包含代码块的 HTML 内容,通常是文章或页面的内容字段。
522+
523+
**返回值**
524+
525+
- 类型:`string`
526+
- 解释:渲染后的 HTML 内容,渲染样式已内联,渲染失败时返回原始内容
527+
528+
**描述**
529+
530+
- 功能特性:
531+
-[处理器文档 - 代码高亮(通过 Shiki.js 渲染)](#代码高亮处理器) 中描述的功能特性一致。也受同样的配置项影响。
532+
533+
**使用示例**
534+
535+
```html
536+
<!--/* 渲染文章内容中的代码块,下面这段代码可直接用于 /templates/post.html */-->
537+
<div th:utext="${extraApiRenderFinder.renderCodeHtml(post.content?.content)}"></div>
538+
539+
<!--/* 在模板中使用,下面这段代码可直接用于 /templates/moment.html */-->
540+
<div th:with="renderedContent=${extraApiRenderFinder.renderCodeHtml(moment.spec.content?.html)}">
541+
<div th:utext="${renderedContent}"></div>
542+
</div>
543+
```
544+
545+
545546
## 处理器文档
546547

548+
### 中英文混排格式化处理器
549+
550+
插件提供了自动化的中英文混排格式化处理器,无需在模板中手动调用,即可对文章和页面内容自动应用 Pangu 空格处理。
551+
552+
此功能在轻量版和全量版中均可用。
553+
554+
#### 功能说明
555+
556+
- 自动处理范围:
557+
- 处理器会自动处理文章(post)和页面(page)内容中的段落标签(`<p>`
558+
- 在中日韩字符与英文、数字、符号之间自动插入空格
559+
- 处理规则:
560+
- 自动在 CJK 字符和英文字母之间添加空格
561+
- 自动在 CJK 字符和数字之间添加空格
562+
- 自动在 CJK 字符和常见符号之间添加空格
563+
- 智能跳过 `<code>``<pre>``<script>``<style>``<textarea>` 等标签
564+
- 性能特点:
565+
- 纯 Java 实现,无需 JavaScript 运行时
566+
- 处理速度快,对页面加载影响极小
567+
- 不涉及缓存,每次渲染时实时处理
568+
- 错误处理:
569+
- 处理失败时保持原始内容不变
570+
- 不会因格式化问题影响页面正常渲染
571+
572+
#### 配置选项
573+
574+
此处理器默认启用。开箱即用,无需额外配置。
575+
576+
在“插件设置 - 中英文混排格式化”提供以下配置项:
577+
- 自动渲染: 启用之后会自动处理文章和单页中段落标签的中英文混排格式,在中日韩字符与英文、数字、符号之间自动插入空格。注:Finder API 渲染不受此配置项影响。
578+
579+
#### 补充说明
580+
581+
- 此功能使用 [Pangu.java](https://github.com/vinta/pangu.java) 库实现
582+
- 仅处理可见文本内容,不影响 HTML 结构
583+
- 递归处理嵌套元素,确保完整覆盖
584+
- 与本插件提供的其他处理器兼容,互不影响
585+
547586
### 代码高亮处理器
548587

549588
插件提供了自动化的代码高亮处理器,无需在模板中手动调用,即可对文章和页面内容中的代码块进行语法高亮渲染。
@@ -576,6 +615,7 @@ extraApiPanguFinder.spacingText(text)
576615

577616
#### 配置选项
578617

618+
在“插件设置 - 代码高亮(仅全量版可用)”提供以下配置项:
579619
- 自动渲染: 启用之后会自动渲染文章和单页中的代码块。注:Finder API 渲染不受此配置项影响。
580620
- 自定义注入 CSS 样式:启用自动渲染时将在页面 head 注入样式以优化 Shiki 渲染效果,默认值提供了边距调整/行号显示/基于媒体查询的明暗切换功能。
581621
- 额外注入规则: 指定额外的页面路径规则,支持通配符。
@@ -627,48 +667,6 @@ extraApiPanguFinder.spacingText(text)
627667
- 补充说明:
628668
- 双主题模式会生成两个并列的 div 元素
629669

630-
### 中英文混排格式化处理器
631-
632-
插件提供了自动化的中英文混排格式化处理器,无需在模板中手动调用,即可对文章和页面内容自动应用 Pangu 空格处理。
633-
634-
此功能在轻量版和全量版中均可用。
635-
636-
#### 功能说明
637-
638-
- **自动处理范围**:
639-
- 处理器会自动处理文章(post)和页面(page)内容中的段落标签(`<p>`)
640-
- 在中日韩字符与英文、数字、符号之间自动插入空格
641-
642-
- **处理规则**:
643-
- 自动在 CJK 字符和英文字母之间添加空格
644-
- 自动在 CJK 字符和数字之间添加空格
645-
- 自动在 CJK 字符和常见符号之间添加空格
646-
- 智能跳过 `<code>`、`<pre>`、`<script>``<style>``<textarea>` 等标签
647-
648-
- **性能特点**:
649-
- 纯 Java 实现,无需 JavaScript 运行时
650-
- 处理速度快,对页面加载影响极小
651-
- 不涉及缓存,每次渲染时实时处理
652-
653-
- **错误处理**:
654-
- 处理失败时保持原始内容不变
655-
- 不会因格式化问题影响页面正常渲染
656-
657-
#### 使用说明
658-
659-
处理器默认启用,无需额外配置。如果您希望禁用自动处理,可以通过以下方式:
660-
661-
1. 在 Halo 管理后台进入插件设置页面
662-
2. 找到"中英文混排格式化"相关选项(如果提供)
663-
3. 或者仅使用 [Finder API](#中英文混排格式化-api) 在需要的地方手动调用
664-
665-
#### 补充说明
666-
667-
- 此功能使用 [Pangu.java](https://github.com/vinta/pangu.java) 库实现
668-
- 仅处理可见文本内容,不影响 HTML 结构
669-
- 递归处理嵌套元素,确保完整覆盖
670-
- 与代码高亮处理器兼容,互不影响
671-
672670
## 版本说明
673671

674672
插件提供两个版本:

src/main/java/top/howiehz/halo/plugin/extra/api/finder/basic/ExtraApiPanguFinder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public interface ExtraApiPanguFinder {
2222
* 对 HTML 内容中的指定标签元素应用 Pangu 空格。
2323
*
2424
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
25-
* @param tagName the tag name to process (e.g., "p", "div") / 要处理的标签名称(例如 "p"、"div")
25+
* @param tagName the tag name to process (e.g., "p", "div") / 要处理的标签名称(例如 "p"、"div")
2626
* @return Mono emitting processed HTML content / 发出处理后的 HTML 内容的 Mono
2727
*/
2828
Mono<String> spacingElementByTagName(String htmlContent, String tagName);
@@ -32,7 +32,7 @@ public interface ExtraApiPanguFinder {
3232
* 对 HTML 内容中具有指定 ID 的元素应用 Pangu 空格。
3333
*
3434
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
35-
* @param id the element ID to process / 要处理的元素 ID
35+
* @param id the element ID to process / 要处理的元素 ID
3636
* @return Mono emitting processed HTML content / 发出处理后的 HTML 内容的 Mono
3737
*/
3838
Mono<String> spacingElementById(String htmlContent, String id);
@@ -42,7 +42,7 @@ public interface ExtraApiPanguFinder {
4242
* 对 HTML 内容中具有指定 class 的元素应用 Pangu 空格。
4343
*
4444
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
45-
* @param className the class name to process / 要处理的 class 名称
45+
* @param className the class name to process / 要处理的 class 名称
4646
* @return Mono emitting processed HTML content / 发出处理后的 HTML 内容的 Mono
4747
*/
4848
Mono<String> spacingElementByClassName(String htmlContent, String className);

src/main/java/top/howiehz/halo/plugin/extra/api/finder/basic/impl/ExtraApiPanguFinderImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,24 @@
2222
@RequiredArgsConstructor
2323
@Finder("extraApiPanguFinder")
2424
public class ExtraApiPanguFinderImpl implements ExtraApiPanguFinder {
25-
25+
2626
private final PanguSpacingService panguSpacingService;
2727

2828
@Override
2929
public Mono<String> spacingElementByTagName(String htmlContent, String tagName) {
30-
return Mono.fromCallable(() ->
30+
return Mono.fromCallable(() ->
3131
panguSpacingService.spacingElementByTagName(htmlContent, tagName));
3232
}
3333

3434
@Override
3535
public Mono<String> spacingElementById(String htmlContent, String id) {
36-
return Mono.fromCallable(() ->
36+
return Mono.fromCallable(() ->
3737
panguSpacingService.spacingElementById(htmlContent, id));
3838
}
3939

4040
@Override
4141
public Mono<String> spacingElementByClassName(String htmlContent, String className) {
42-
return Mono.fromCallable(() ->
42+
return Mono.fromCallable(() ->
4343
panguSpacingService.spacingElementByClassName(htmlContent, className));
4444
}
4545

src/main/java/top/howiehz/halo/plugin/extra/api/finder/basic/impl/ExtraApiStatsFinderImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,16 @@ public Mono<BigInteger> getPostWordCount(Map<String, Object> params) {
5757
public Mono<BigInteger> getContentWordCount(Map<String, Object> params) {
5858
Map<String, Object> map = params == null ? java.util.Collections.emptyMap() : params;
5959
Object htmlContentObj = map.get("htmlContent");
60-
60+
6161
if (htmlContentObj == null) {
6262
return Mono.just(BigInteger.ZERO);
6363
}
64-
64+
6565
String htmlContent = String.valueOf(htmlContentObj);
6666
if ("null".equals(htmlContent) || htmlContent.isBlank()) {
6767
return Mono.just(BigInteger.ZERO);
6868
}
69-
69+
7070
return Mono.fromCallable(() -> PostWordCountUtil.countHTMLWords(htmlContent))
7171
.onErrorReturn(BigInteger.ZERO);
7272
}

src/main/java/top/howiehz/halo/plugin/extra/api/service/basic/post/render/pangu/PanguPostContentRenderHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
@Component
2828
@RequiredArgsConstructor
2929
public class PanguPostContentRenderHandler implements ReactivePostContentHandler {
30-
30+
3131
private final PanguSpacingService panguSpacingService;
3232
private final Supplier<Mono<PanguConfig>> panguConfigSupplier;
3333

@@ -47,20 +47,20 @@ public Mono<PostContentContext> handle(@NotNull PostContentContext contentContex
4747
log.debug("Pangu auto-render is disabled, skipping processing");
4848
return Mono.just(contentContext);
4949
}
50-
50+
5151
return Mono.fromCallable(() -> {
5252
try {
5353
String originalContent = contentContext.getContent();
54-
54+
5555
// 对 <p> 标签应用 Pangu 空格处理
5656
String processedContent = panguSpacingService.spacingElementByTagName(
5757
originalContent, "p");
58-
58+
5959
contentContext.setContent(processedContent);
60-
60+
6161
log.debug("Successfully applied Pangu spacing to post content");
6262
return contentContext;
63-
63+
6464
} catch (Exception e) {
6565
log.error("Error occurred while applying Pangu spacing: {}",
6666
Throwables.getStackTraceAsString(e));

src/main/java/top/howiehz/halo/plugin/extra/api/service/basic/post/render/pangu/PanguSinglePageContentRenderHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
@Component
2828
@RequiredArgsConstructor
2929
public class PanguSinglePageContentRenderHandler implements ReactiveSinglePageContentHandler {
30-
30+
3131
private final PanguSpacingService panguSpacingService;
3232
private final Supplier<Mono<PanguConfig>> panguConfigSupplier;
3333

@@ -47,20 +47,20 @@ public Mono<SinglePageContentContext> handle(@NotNull SinglePageContentContext c
4747
log.debug("Pangu auto-render is disabled, skipping processing");
4848
return Mono.just(contentContext);
4949
}
50-
50+
5151
return Mono.fromCallable(() -> {
5252
try {
5353
String originalContent = contentContext.getContent();
54-
54+
5555
// 对 <p> 标签应用 Pangu 空格处理
5656
String processedContent = panguSpacingService.spacingElementByTagName(
5757
originalContent, "p");
58-
58+
5959
contentContext.setContent(processedContent);
60-
60+
6161
log.debug("Successfully applied Pangu spacing to single page content");
6262
return contentContext;
63-
63+
6464
} catch (Exception e) {
6565
log.error("Error occurred while applying Pangu spacing: {}",
6666
Throwables.getStackTraceAsString(e));

src/main/java/top/howiehz/halo/plugin/extra/api/service/basic/post/render/pangu/PanguSpacingService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public interface PanguSpacingService {
1818
* 对 HTML 内容中的指定标签元素应用 Pangu 空格。
1919
*
2020
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
21-
* @param tagName the tag name to process (e.g., "p", "div") / 要处理的标签名称(例如 "p"、"div")
21+
* @param tagName the tag name to process (e.g., "p", "div") / 要处理的标签名称(例如 "p"、"div")
2222
* @return processed HTML content / 处理后的 HTML 内容
2323
*/
2424
String spacingElementByTagName(String htmlContent, String tagName);
@@ -28,7 +28,7 @@ public interface PanguSpacingService {
2828
* 对 HTML 内容中具有指定 ID 的元素应用 Pangu 空格。
2929
*
3030
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
31-
* @param id the element ID to process / 要处理的元素 ID
31+
* @param id the element ID to process / 要处理的元素 ID
3232
* @return processed HTML content / 处理后的 HTML 内容
3333
*/
3434
String spacingElementById(String htmlContent, String id);
@@ -38,7 +38,7 @@ public interface PanguSpacingService {
3838
* 对 HTML 内容中具有指定 class 的元素应用 Pangu 空格。
3939
*
4040
* @param htmlContent the HTML content to process / 要处理的 HTML 内容
41-
* @param className the class name to process / 要处理的 class 名称
41+
* @param className the class name to process / 要处理的 class 名称
4242
* @return processed HTML content / 处理后的 HTML 内容
4343
*/
4444
String spacingElementByClassName(String htmlContent, String className);

0 commit comments

Comments
 (0)