Skip to content

Commit

Permalink
feat: add highlightjs code block extension to the editor (#24)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Wang <[email protected]>
Co-authored-by: Ryan Wang <[email protected]>
  • Loading branch information
LIlGG and ruibaby authored Sep 2, 2024
1 parent a4ad911 commit c245913
Show file tree
Hide file tree
Showing 217 changed files with 10,169 additions and 7,881 deletions.
510 changes: 510 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
ci:
uses: halo-sigs/reusable-workflows/.github/workflows/plugin-ci.yaml@v1
with:
skip-node-setup: true
ui-path: "ui"
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ application-local.yml
application-local.yaml
application-local.properties

/admin-frontend/node_modules/
/workplace/
/src/main/resources/console/
22 changes: 22 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
plugins {
id "com.github.node-gradle.node" version "7.0.2"
id "run.halo.plugin.devtools" version "0.0.7"
id "io.freefair.lombok" version "8.0.1"
id 'java'
Expand Down Expand Up @@ -30,6 +31,27 @@ test {
useJUnitPlatform()
}

node {
nodeProjectDir = file("${project.projectDir}/ui")
}

tasks.register('buildFrontend', PnpmTask) {
args = ['build']
dependsOn('installDepsForUI')
}

tasks.register('installDepsForUI', PnpmTask) {
args = ['install']
}


build {
// build frontend before build
tasks.named('compileJava').configure {
dependsOn('buildFrontend')
}
}

halo {
version = "2.12.2"
}
101 changes: 40 additions & 61 deletions src/main/java/run/halo/highlightjs/HighlightJSHeadProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import org.springframework.web.util.pattern.PathPatternParser;
import org.springframework.web.util.pattern.PathPatternRouteMatcher;
import org.springframework.web.util.pattern.PatternParseException;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.Contexts;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.model.IModel;
import org.thymeleaf.model.IModelFactory;
import org.thymeleaf.processor.element.IElementModelStructureHandler;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.web.IWebRequest;
import reactor.core.publisher.Mono;
import run.halo.app.plugin.ReactiveSettingFetcher;
Expand All @@ -37,10 +40,16 @@ public class HighlightJSHeadProcessor implements TemplateHeadProcessor {

private final RouteMatcher routeMatcher = createRouteMatcher();

private final TemplateEngine templateEngine = new SpringTemplateEngine();

@Override
public Mono<Void> process(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) {
return reactiveSettingFetcher.fetch("basic", BasicConfig.class)
.doOnNext(basicConfig -> {
if (!basicConfig.enableThemeSideRender) {
return;
}

if (mismatchedRoute(context, basicConfig) && notContentTemplate(context)) {
return;
}
Expand All @@ -57,65 +66,35 @@ public Mono<Void> process(ITemplateContext context, IModel model, IElementModelS
}

private String highlightJsScript(BasicConfig basicConfig) {
StringBuilder injectCode = new StringBuilder();
injectCode.append("""
<!-- PluginHighlightJS start -->
<link href="/plugins/PluginHighlightJS/assets/static/styles/%s" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/highlight.min.js"></script>
""".formatted(basicConfig.getStyle()));

if (basicConfig.isShowCopyButton()) {
injectCode.append("""
<link href="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.css" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.js"></script>
""");
}

injectCode.append("""
<link href="/plugins/PluginHighlightJS/assets/static/plugins/override.css" rel="stylesheet"/>
<script>
""");

injectCode.append("""
document.addEventListener("DOMContentLoaded", async function () {
""");

if (basicConfig.isShowCopyButton()) {
injectCode.append("""
hljs.addPlugin(new CopyButtonPlugin({ lang: "zh"}));
""");
}

var extraLanguages = basicConfig.getExtra_languages();

injectCode.append("""
const extraLanguages = "%s".split(",").filter((x) => x);
for (let i = 0; i < extraLanguages.length; i++) {
const lang = extraLanguages[i];
if (lang) {
await loadScript(`/plugins/PluginHighlightJS/assets/static/languages/${lang}.min.js`);
}
}
document.querySelectorAll("pre code").forEach((el) => {
hljs.highlightElement(el);
});
});
function loadScript(url) {
return new Promise(function (resolve, reject) {
const script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
</script>
<!-- PluginHighlightJS end -->
""".formatted(extraLanguages != null ? extraLanguages : ""));
return injectCode.toString();
var context = new Context();
context.setVariable("config", basicConfig);
var code = templateEngine.process(
"""
<!-- PluginHighlightJS start -->
<link th:href="|/plugins/PluginHighlightJS/assets/static/styles/${config.style}|" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/highlight.min.js"></script>
<th:block th:if="${config.showCopyButton}">
<link href="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.css" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.js"></script>
</th:block>
<link href="/plugins/PluginHighlightJS/assets/static/plugins/override.css" rel="stylesheet"/>
<script th:inline="javascript">
document.addEventListener("DOMContentLoaded", function () {
[# th:if="${config.showCopyButton}"]
hljs.addPlugin(new CopyButtonPlugin({ lang: "zh"}));
[/]
document.querySelectorAll("pre code").forEach((el) => {
hljs.highlightElement(el);
});
});
</script>
<!-- PluginHighlightJS end -->
""",
context);
return code;
}

public boolean notContentTemplate(ITemplateContext context) {
Expand Down Expand Up @@ -159,7 +138,7 @@ public static class PathMatchRule {

@Data
public static class BasicConfig {
String extra_languages;
boolean enableThemeSideRender;
String style;
List<PathMatchRule> rules;
boolean showCopyButton;
Expand All @@ -168,4 +147,4 @@ public List<PathMatchRule> nullSafeRules() {
return ObjectUtils.defaultIfNull(rules, List.of());
}
}
}
}
18 changes: 12 additions & 6 deletions src/main/resources/extensions/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ spec:
- group: basic
label: 基本设置
formSchema:
- $formkit: checkbox
name: enableThemeSideRender
id: enableThemeSideRender
label: 启用主题侧渲染
help: 启用之后会自动渲染文章中的代码块,以及根据下面的页面匹配规则渲染代码块。取消勾选之后,此插件仅会在编辑器中渲染代码块。
value: true
- $formkit: repeater
if: "$get(enableThemeSideRender).value"
name: rules
id: rules
key: rules
label: 页面匹配规则
value: [ ]
value: []
children:
- $formkit: text
name: pathPattern
label: 路径匹配
value: ""
validation: required
help: 用于匹配页面路径的符合 Ant-style 的表达式 ,如:/archives/**,被匹配的页面将会被添加代码高亮功能
- $formkit: textarea
name: extra_languages
label: 代码块额外高亮语言
help: "默认已经包含:php,diff,java,css,bash,json,perl,swift,plaintext,ruby,yaml,sql,vbnet,ini,scss,less,cpp,typescript,csharp,rust,python,python-repl,objectivec,r,shell,makefile,go,xml,markdown,lua,javascript,php-template,kotlin,c 如果需要添加其他语言,请按照相同格式添加。"
- $formkit: select
if: "$get(enableThemeSideRender).value"
name: style
label: 代码块高亮主题
value: "default.min.css"
Expand Down Expand Up @@ -170,7 +176,7 @@ spec:
- value: "xt256.min.css"
label: "xt256.min.css"
- $formkit: checkbox
if: "$get(enableThemeSideRender).value"
label: 显示复制按钮
value: false
name: showCopyButton

2 changes: 1 addition & 1 deletion src/main/resources/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
spec:
enabled: true
version: 1.0.0
requires: ">=2.10.0"
requires: ">=2.19.0"
author:
name: Halo
website: https://github.com/halo-dev
Expand Down
Loading

0 comments on commit c245913

Please sign in to comment.