@codady/coax 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/LICENSE +24 -0
- package/README.md +236 -0
- package/dist/coax.cjs.js +181 -0
- package/dist/coax.cjs.min.js +15 -0
- package/dist/coax.esm.js +179 -0
- package/dist/coax.esm.min.js +15 -0
- package/dist/coax.umd.js +186 -0
- package/dist/coax.umd.min.js +15 -0
- package/examples/css-highlight.html +62 -0
- package/examples/html-highlight.html +43 -0
- package/examples/js-highlight.html +64 -0
- package/examples/ts-highlight.html +65 -0
- package/package.json +74 -0
- package/rollup.config.js +68 -0
- package/script-mini.js +43 -0
- package/script-note.js +34 -0
- package/src/Coax.js +192 -0
- package/src/Coax.ts +217 -0
- package/tsconfig.json +108 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All changes to Coax including new features, updates, and removals are documented here.
|
|
4
|
+
|
|
5
|
+
## [v0.0.1] - 2026-1-4
|
|
6
|
+
|
|
7
|
+
### Distribution Files
|
|
8
|
+
- **JS**: https://unpkg.com/@codady/coax@0.0.1/dist/coax.umd.js
|
|
9
|
+
|
|
10
|
+
### Changes
|
|
11
|
+
|
|
12
|
+
#### Fixed
|
|
13
|
+
- Null
|
|
14
|
+
|
|
15
|
+
#### Added
|
|
16
|
+
- Publish the first version.
|
|
17
|
+
|
|
18
|
+
#### Removed
|
|
19
|
+
- Null
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 AXUI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
Please keep our copyright information. If you have any questions,
|
|
24
|
+
please contact us: 3217728223@qq.com.
|
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
|
|
2
|
+
# Coax: A Code Syntax Highlighter for Web Components
|
|
3
|
+
|
|
4
|
+
## Overview
|
|
5
|
+
|
|
6
|
+
**Coax** is a custom web component that enables syntax highlighting for various programming languages inside your HTML documents. It allows you to easily embed highlighted code using web standards (Web Components) and modern CSS. This plugin automatically highlights code using regular expressions and supports dynamic theming and customization.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Custom Web Component**: Easily use `<ax-code>` to render syntax-highlighted code.
|
|
13
|
+
- **Language Support**: Register custom language configurations for syntax highlighting (e.g., `HTML`, `CSS`, `JavaScript`, `TypeScript`).
|
|
14
|
+
- **Custom Themes**: Add language-specific themes using CSS variables for customization.
|
|
15
|
+
- **Shadow DOM**: Isolated styling and functionality using the Shadow DOM for better encapsulation.
|
|
16
|
+
- **Dynamic CSS**: Dynamically generate styles for each language based on rules.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Simply include the `Coax` JavaScript file in your project, or use the module system if you're using a build tool like Webpack or Rollup.
|
|
23
|
+
|
|
24
|
+
### Direct inclusion (via script tag)
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script src="path/to/coax.js"></script>
|
|
28
|
+
````
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
To use the Coax code highlighting component, follow these steps:
|
|
35
|
+
|
|
36
|
+
### 1. Define the `<ax-code>` element
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<ax-code lang="js">
|
|
40
|
+
// Your JavaScript code here
|
|
41
|
+
</ax-code>
|
|
42
|
+
|
|
43
|
+
<ax-code lang="css">
|
|
44
|
+
/* Your CSS code here */
|
|
45
|
+
</ax-code>
|
|
46
|
+
|
|
47
|
+
<ax-code lang="html">
|
|
48
|
+
<!-- Your HTML code here -->
|
|
49
|
+
</ax-code>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Register Language Configurations
|
|
53
|
+
|
|
54
|
+
You can register languages with their syntax rules and themes using the `Coax.register` method.
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
Coax.register('html', {
|
|
58
|
+
rules: [
|
|
59
|
+
{ name: 'comment', reg: /<!--[\s\S]*?-->/ },
|
|
60
|
+
{ name: 'tag', reg: /<\/?[a-zA-Z0-9]+/ },
|
|
61
|
+
{ name: 'attr', reg: /[a-zA-Z-]+(?=\s*=\s*)/ },
|
|
62
|
+
{ name: 'string', reg: /(['"])(?:\\.|[^\\])*?\1/ },
|
|
63
|
+
],
|
|
64
|
+
theme: {
|
|
65
|
+
'tag': '#e06c75', // red
|
|
66
|
+
'attr': '#d19a66', // orange
|
|
67
|
+
'string': '#98c379', // green
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Customization
|
|
73
|
+
|
|
74
|
+
You can customize the code highlighting by modifying the language's rules, theme colors, or internal CSS using the `theme`, `internalCss`, and `cssPrefix` properties.
|
|
75
|
+
|
|
76
|
+
Example:
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
Coax.register('css', {
|
|
80
|
+
rules: [
|
|
81
|
+
{ name: 'comment', reg: /\/\*[\s\S]*?\*\// },
|
|
82
|
+
{ name: 'property', reg: /[a-z-]+(?=\s*:)/ },
|
|
83
|
+
{ name: 'selector', reg: /[.#a-z0-9, \n\t>:+()_-]+(?=\s*\{)/i },
|
|
84
|
+
{ name: 'unit', reg: /(?<=\d)(px|em|rem|%|vh|vw|ms|s|deg)/ },
|
|
85
|
+
],
|
|
86
|
+
theme: {
|
|
87
|
+
'keyword': '#61afef', // blue
|
|
88
|
+
'string': '#98c379', // green
|
|
89
|
+
'op': '#abb2bf', // gray
|
|
90
|
+
},
|
|
91
|
+
internalCss: `
|
|
92
|
+
.ax-css-string { color: var(--ax-code-string); }
|
|
93
|
+
`
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 4. Optional Attributes
|
|
98
|
+
|
|
99
|
+
You can customize the code block's height and max height:
|
|
100
|
+
|
|
101
|
+
```html
|
|
102
|
+
<ax-code lang="js" height="200px" max-height="400px">
|
|
103
|
+
const x = 10;
|
|
104
|
+
</ax-code>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Development
|
|
110
|
+
|
|
111
|
+
If you'd like to extend or modify the plugin, the source code is available for you to contribute or adapt.
|
|
112
|
+
|
|
113
|
+
* **Clone the repository**: `git clone https://github.com/your-repository`
|
|
114
|
+
* **Run build tools** (e.g., Webpack, Babel) for production optimization.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT License. Feel free to use and modify it for your projects.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
# 中文文档
|
|
125
|
+
|
|
126
|
+
## 概述
|
|
127
|
+
|
|
128
|
+
**Coax** 是一个自定义 Web 组件,可以在 HTML 文档中嵌入高亮的代码。它允许您使用现代 Web 标准(Web 组件)和 CSS 来轻松实现代码高亮。该插件通过正则表达式自动高亮代码,并支持动态主题和自定义设置。
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 特性
|
|
133
|
+
|
|
134
|
+
* **自定义 Web 组件**:使用 `<ax-code>` 标签轻松渲染代码高亮。
|
|
135
|
+
* **语言支持**:为每种编程语言注册自定义语法高亮配置(例如,`HTML`,`CSS`,`JavaScript`,`TypeScript`)。
|
|
136
|
+
* **自定义主题**:使用 CSS 变量添加语言特定的主题,支持个性化定制。
|
|
137
|
+
* **Shadow DOM**:使用 Shadow DOM 实现样式和功能的隔离。
|
|
138
|
+
* **动态 CSS**:基于规则动态生成每种语言的样式。
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 安装
|
|
143
|
+
|
|
144
|
+
只需将 `Coax` 的 JavaScript 文件包含到您的项目中,或使用构建工具(如 Webpack 或 Rollup)进行模块化引入。
|
|
145
|
+
|
|
146
|
+
### 直接引入(通过 `<script>` 标签)
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<script src="path/to/coax.js"></script>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 使用方法
|
|
155
|
+
|
|
156
|
+
要使用 Coax 代码高亮组件,请按照以下步骤进行操作:
|
|
157
|
+
|
|
158
|
+
### 1. 定义 `<ax-code>` 元素
|
|
159
|
+
|
|
160
|
+
```html
|
|
161
|
+
<ax-code lang="js">
|
|
162
|
+
// 这里是您的 JavaScript 代码
|
|
163
|
+
</ax-code>
|
|
164
|
+
|
|
165
|
+
<ax-code lang="css">
|
|
166
|
+
/* 这里是您的 CSS 代码 */
|
|
167
|
+
</ax-code>
|
|
168
|
+
|
|
169
|
+
<ax-code lang="html">
|
|
170
|
+
<!-- 这里是您的 HTML 代码 -->
|
|
171
|
+
</ax-code>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 2. 注册语言配置
|
|
175
|
+
|
|
176
|
+
您可以使用 `Coax.register` 方法注册语言的语法规则和主题。
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
Coax.register('html', {
|
|
180
|
+
rules: [
|
|
181
|
+
{ name: 'comment', reg: /<!--[\s\S]*?-->/ },
|
|
182
|
+
{ name: 'tag', reg: /<\/?[a-zA-Z0-9]+/ },
|
|
183
|
+
{ name: 'attr', reg: /[a-zA-Z-]+(?=\s*=\s*)/ },
|
|
184
|
+
{ name: 'string', reg: /(['"])(?:\\.|[^\\])*?\1/ },
|
|
185
|
+
],
|
|
186
|
+
theme: {
|
|
187
|
+
'tag': '#e06c75', // 红色
|
|
188
|
+
'attr': '#d19a66', // 橙色
|
|
189
|
+
'string': '#98c379', // 绿色
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 3. 自定义设置
|
|
195
|
+
|
|
196
|
+
您可以通过修改语言的规则、主题颜色或内部 CSS 来定制代码高亮,具体方法如下:
|
|
197
|
+
|
|
198
|
+
```javascript
|
|
199
|
+
Coax.register('css', {
|
|
200
|
+
rules: [
|
|
201
|
+
{ name: 'comment', reg: /\/\*[\s\S]*?\*\// },
|
|
202
|
+
{ name: 'property', reg: /[a-z-]+(?=\s*:)/ },
|
|
203
|
+
{ name: 'selector', reg: /[.#a-z0-9, \n\t>:+()_-]+(?=\s*\{)/i },
|
|
204
|
+
{ name: 'unit', reg: /(?<=\d)(px|em|rem|%|vh|vw|ms|s|deg)/ },
|
|
205
|
+
],
|
|
206
|
+
theme: {
|
|
207
|
+
'keyword': '#61afef', // 蓝色
|
|
208
|
+
'string': '#98c379', // 绿色
|
|
209
|
+
'op': '#abb2bf', // 灰色
|
|
210
|
+
},
|
|
211
|
+
internalCss: `
|
|
212
|
+
.ax-css-string { color: var(--ax-code-string); }
|
|
213
|
+
`
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 4. 可选属性
|
|
218
|
+
|
|
219
|
+
您可以通过 `height` 和 `max-height` 属性自定义代码块的高度和最大高度:
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
<ax-code lang="js" height="200px" max-height="400px">
|
|
223
|
+
const x = 10;
|
|
224
|
+
</ax-code>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 许可证
|
|
230
|
+
|
|
231
|
+
MIT 许可证。可以自由使用和修改代码以适应您的项目需求。
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
package/dist/coax.cjs.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
|
|
2
|
+
/*!
|
|
3
|
+
* @since Last modified: 2026-1-4 16:0:48
|
|
4
|
+
* @name Coax event management system.
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @author AXUI development team <3217728223@qq.com>
|
|
7
|
+
* @description Coax is a custom web component that enables syntax highlighting for various programming languages inside your HTML documents.
|
|
8
|
+
* @see {@link https://coax.axui.cn|Official website}
|
|
9
|
+
* @see {@link https://github.com/codady/coax/issues|github issues}
|
|
10
|
+
* @see {@link https://gitee.com/codady/coax/issues|Gitee issues}
|
|
11
|
+
* @see {@link https://www.npmjs.com/package/@codady/coax|NPM}
|
|
12
|
+
* @issue QQ Group No.1:952502085
|
|
13
|
+
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'coax', 'Coax' and 'COAX' within the software.
|
|
14
|
+
* @license MIT license
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
class Coax extends HTMLElement {
|
|
20
|
+
// A static Map to hold the configuration for different languages
|
|
21
|
+
static languages = new Map();
|
|
22
|
+
// Raw code as text from the HTML content
|
|
23
|
+
rawCode;
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
// Attach a Shadow DOM to the custom element
|
|
27
|
+
this.attachShadow({ mode: 'open' });
|
|
28
|
+
// Remove leading/trailing whitespace from the raw code content
|
|
29
|
+
this.rawCode = this.textContent?.replace(/^\s*\n|\n\s*$/g, '') || '';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static register(name, { rules, theme = {}, internalCss = '', cssPrefix = '' }) {
|
|
33
|
+
// Store the language configuration in the static map
|
|
34
|
+
this.languages.set(name, { rules, theme, internalCss, cssPrefix });
|
|
35
|
+
// Render the highlighted code for all elements with the registered language
|
|
36
|
+
document.querySelectorAll('ax-code').forEach(el => {
|
|
37
|
+
if (el.getAttribute('lang') === name)
|
|
38
|
+
el.render();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Called when the element is connected to the DOM
|
|
42
|
+
connectedCallback() { this.render(); }
|
|
43
|
+
// Observed attributes for changes
|
|
44
|
+
static get observedAttributes() { return ['lang', 'height', 'max-height']; }
|
|
45
|
+
|
|
46
|
+
attributeChangedCallback() {
|
|
47
|
+
this.render();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
render() {
|
|
51
|
+
// Get language name, fallback to 'js' if not provided
|
|
52
|
+
const lang = this.getAttribute('lang') || 'js',
|
|
53
|
+
// Get the language configuration
|
|
54
|
+
config = Coax.languages.get(lang),
|
|
55
|
+
// Default to language name if no prefix is set
|
|
56
|
+
cssPrefix = config?.cssPrefix || lang, height = this.getAttribute('height'), maxHeight = this.getAttribute('max-height');
|
|
57
|
+
let highlightedCode = '', dynamicStyles = '';
|
|
58
|
+
if (config) {
|
|
59
|
+
//Generate the highlighted HTML by applying the syntax rules
|
|
60
|
+
const combinedRegex = new RegExp(config.rules.map((r) => `(${r.reg.source})`).join('|'), 'g'), escaped = this.rawCode.replace(/[&<>]/g, m => ({ '&': '&', '<': '<', '>': '>' }[m]));
|
|
61
|
+
// Replace code with highlighted syntax
|
|
62
|
+
highlightedCode = escaped.replace(combinedRegex, (match, ...args) => {
|
|
63
|
+
const index = args.findIndex(val => val !== undefined);
|
|
64
|
+
return index !== -1 && config.rules[index] ? `<span class="ax-${cssPrefix}-${config.rules[index].name}">${match}</span>` : match;
|
|
65
|
+
});
|
|
66
|
+
//Generate dynamic CSS classes for each syntax rule
|
|
67
|
+
// 为 rules 中的每一个 name 生成类似 .hl-name { color: var(--ax-code-name); }
|
|
68
|
+
dynamicStyles = config.rules.map((rule) => `
|
|
69
|
+
.ax-${cssPrefix}-${rule.name} { color: var(--ax-${cssPrefix}-${rule.name}); }
|
|
70
|
+
`).join('\n');
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// If no config, display raw code without highlighting
|
|
74
|
+
highlightedCode = this.rawCode;
|
|
75
|
+
}
|
|
76
|
+
//Generate CSS theme variables if a theme is provided
|
|
77
|
+
const themeVars = config?.theme
|
|
78
|
+
? Object.entries(config.theme).map(([k, v]) => `--ax-${cssPrefix}-${k}: ${v};`).join('\n')
|
|
79
|
+
: '';
|
|
80
|
+
// Set the inner HTML of the shadow root, including styles and highlighted code
|
|
81
|
+
this.shadowRoot.innerHTML = `
|
|
82
|
+
<style>
|
|
83
|
+
:host {
|
|
84
|
+
${themeVars}
|
|
85
|
+
|
|
86
|
+
font-size: var(--ax-code-fs,14px);
|
|
87
|
+
display: block;
|
|
88
|
+
padding: var(--ax-code-p,1em);
|
|
89
|
+
box-sizing:border-box;
|
|
90
|
+
line-height: var(--ax-code-lh,1.5);
|
|
91
|
+
background-color:var(--ax-code-bg,rgba(0,0,0,0.02));
|
|
92
|
+
color:var(--ax-code-c,#333);
|
|
93
|
+
border:var(--ax-code-bw,1px) solid var(--ax-code-bc,rgba(0,0,0,0.08));
|
|
94
|
+
height:${height || 'var(--ax-code-h,auto)'};
|
|
95
|
+
max-height:${maxHeight || 'var(--ax-code-mh,500px)'};
|
|
96
|
+
overflow:auto;
|
|
97
|
+
transition: border-color 0.3s ease,color 0.3s ease;
|
|
98
|
+
border-radius: var(--ax-code-r,9px);
|
|
99
|
+
}
|
|
100
|
+
pre,code{
|
|
101
|
+
font-family:"Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", "monospace", "microsoft yahei", "Microsoft JhengHei", "Yu Mincho", "simsun";
|
|
102
|
+
margin:0;
|
|
103
|
+
padding:0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
${dynamicStyles}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
${config?.internalCss || ''}
|
|
112
|
+
</style>
|
|
113
|
+
<pre><code>${highlightedCode}</code></pre>`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
customElements.define('ax-code', Coax);
|
|
117
|
+
Coax.register('html', {
|
|
118
|
+
rules: [
|
|
119
|
+
{ name: 'comment', reg: /<!--[\s\S]*?-->/ },
|
|
120
|
+
{ name: 'doctype', reg: /<!DOCTYPE[\s\S]*?>/i },
|
|
121
|
+
// 匹配标签名: <div, </div
|
|
122
|
+
{ name: 'tag', reg: /<\/?[a-zA-Z0-9]+/ },
|
|
123
|
+
// 匹配属性名: class=
|
|
124
|
+
{ name: 'attr', reg: /[a-zA-Z-]+(?=\s*=\s*)/ },
|
|
125
|
+
// 匹配属性值: "value"
|
|
126
|
+
{ name: 'string', reg: /(['"])(?:\\.|[^\\])*?\1/ },
|
|
127
|
+
// 匹配标签闭合: >, />
|
|
128
|
+
{ name: 'bracket', reg: /\/?>/ }
|
|
129
|
+
],
|
|
130
|
+
//添加root变量:--ax-html-keyword
|
|
131
|
+
|
|
132
|
+
});
|
|
133
|
+
Coax.register('css', {
|
|
134
|
+
rules: [
|
|
135
|
+
{ name: 'comment', reg: /\/\*[\s\S]*?\*\// },
|
|
136
|
+
{ name: 'value', reg: /(?:'|")(?:\\.|[^\\'"\b])*?(?:'|")/ },
|
|
137
|
+
{ name: 'func', reg: /[a-z-]+\(?=/ },
|
|
138
|
+
{ name: 'property', reg: /[a-z-]+(?=\s*:)/ },
|
|
139
|
+
{ name: 'selector', reg: /[.#a-z0-9, \n\t>:+()_-]+(?=\s*\{)/i },
|
|
140
|
+
{ name: 'unit', reg: /(?<=\d)(px|em|rem|%|vh|vw|ms|s|deg)/ },
|
|
141
|
+
{ name: 'number', reg: /\b\d+(\.\d+)?\b/ },
|
|
142
|
+
{ name: 'punct', reg: /[{}();:]/ }
|
|
143
|
+
],
|
|
144
|
+
//添加root变量:--ax-code-keyword
|
|
145
|
+
theme: {
|
|
146
|
+
'type': '#61afef', // 蓝色选择器
|
|
147
|
+
'keyword': '#d19a66', // 橙色属性名
|
|
148
|
+
'string': '#98c379', // 绿色属性值
|
|
149
|
+
'op': '#abb2bf' // 灰色符号
|
|
150
|
+
},
|
|
151
|
+
internalCss: `
|
|
152
|
+
.ax-css-string { color: var(--ax-code-string); }
|
|
153
|
+
.ax-css-string::first-letter { color: var(--ax-code-c); }
|
|
154
|
+
`
|
|
155
|
+
});
|
|
156
|
+
Coax.register('js', {
|
|
157
|
+
rules: [
|
|
158
|
+
{ name: 'comment', reg: /\/\/[^\n]*|\/\*[\s\S]*?\*\// },
|
|
159
|
+
{ name: 'string', reg: /(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/ },
|
|
160
|
+
{ name: 'keyword', reg: /\b(async|await|break|case|catch|class|const|continue|default|delete|do|else|export|extends|finally|for|function|if|import|in|instanceof|new|return|super|switch|this|throw|try|typeof|var|while|with|yield|let|static)\b/ },
|
|
161
|
+
{ name: 'builtin', reg: /\b(console|window|document|Math|JSON|true|false|null|undefined|Object|Array|Promise)\b/ },
|
|
162
|
+
{ name: 'number', reg: /\b\d+\b/ },
|
|
163
|
+
{ name: 'func', reg: /\b[a-zA-Z_]\w*(?=\s*\()/ },
|
|
164
|
+
{ name: 'op', reg: /[+\-*/%=<>!&|^~]+/ }
|
|
165
|
+
],
|
|
166
|
+
|
|
167
|
+
});
|
|
168
|
+
Coax.register('ts', {
|
|
169
|
+
rules: [
|
|
170
|
+
{ name: 'comment', reg: /\/\/[^\n]*|\/\*[\s\S]*?\*\// },
|
|
171
|
+
{ name: 'string', reg: /(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/ },
|
|
172
|
+
{ name: 'decorator', reg: /@[a-zA-Z_]\w*/ },
|
|
173
|
+
{ name: 'keyword', reg: /\b(abstract|as|async|await|break|case|catch|class|const|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|package|private|protected|public|readonly|return|set|static|super|switch|this|throw|try|type|typeof|var|while|with|yield)\b/ },
|
|
174
|
+
{ name: 'builtin', reg: /\b(any|boolean|never|number|string|symbol|unknown|void|undefined|null|boolean|true|false|console|window|document)\b/ },
|
|
175
|
+
{ name: 'type', reg: /\b[A-Z]\w*\b/ },
|
|
176
|
+
{ name: 'number', reg: /\b\d+\b/ },
|
|
177
|
+
{ name: 'func', reg: /\b[a-zA-Z_]\w*(?=\s*\()/ },
|
|
178
|
+
{ name: 'op', reg: /(\?\.|![:\.]|[+\-*/%=<>!&|^~]+)/ }
|
|
179
|
+
],
|
|
180
|
+
|
|
181
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* @since Last modified: 2026-1-4 16:0:48
|
|
3
|
+
* @name Coax event management system.
|
|
4
|
+
* @version 0.0.1
|
|
5
|
+
* @author AXUI development team <3217728223@qq.com>
|
|
6
|
+
* @description Coax is a custom web component that enables syntax highlighting for various programming languages inside your HTML documents.
|
|
7
|
+
* @see {@link https://coax.axui.cn|Official website}
|
|
8
|
+
* @see {@link https://github.com/codady/coax/issues|github issues}
|
|
9
|
+
* @see {@link https://gitee.com/codady/coax/issues|Gitee issues}
|
|
10
|
+
* @see {@link https://www.npmjs.com/package/@codady/coax|NPM}
|
|
11
|
+
* @issue QQ Group No.1:952502085
|
|
12
|
+
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'coax', 'Coax' and 'COAX' within the software.
|
|
13
|
+
* @license MIT license
|
|
14
|
+
*/
|
|
15
|
+
"use strict";class Coax extends HTMLElement{static languages=new Map;rawCode;constructor(){super(),this.attachShadow({mode:"open"}),this.rawCode=this.textContent?.replace(/^\s*\n|\n\s*$/g,"")||""}static register(e,{rules:n,theme:t={},internalCss:a="",cssPrefix:r=""}){this.languages.set(e,{rules:n,theme:t,internalCss:a,cssPrefix:r}),document.querySelectorAll("ax-code").forEach(n=>{n.getAttribute("lang")===e&&n.render()})}connectedCallback(){this.render()}static get observedAttributes(){return["lang","height","max-height"]}attributeChangedCallback(){this.render()}render(){const e=this.getAttribute("lang")||"js",n=Coax.languages.get(e),t=n?.cssPrefix||e,a=this.getAttribute("height"),r=this.getAttribute("max-height");let s="",o="";if(n){const e=new RegExp(n.rules.map(e=>`(${e.reg.source})`).join("|"),"g");s=this.rawCode.replace(/[&<>]/g,e=>({"&":"&","<":"<",">":">"}[e])).replace(e,(e,...a)=>{const r=a.findIndex(e=>void 0!==e);return-1!==r&&n.rules[r]?`<span class="ax-${t}-${n.rules[r].name}">${e}</span>`:e}),o=n.rules.map(e=>`\n .ax-${t}-${e.name} { color: var(--ax-${t}-${e.name}); }\n `).join("\n")}else s=this.rawCode;const i=n?.theme?Object.entries(n.theme).map(([e,n])=>`--ax-${t}-${e}: ${n};`).join("\n"):"";this.shadowRoot.innerHTML=`\n <style>\n :host { \n ${i} \n\n font-size: var(--ax-code-fs,14px);\n display: block; \n padding: var(--ax-code-p,1em);\n box-sizing:border-box;\n line-height: var(--ax-code-lh,1.5);\n background-color:var(--ax-code-bg,rgba(0,0,0,0.02));\n color:var(--ax-code-c,#333);\n border:var(--ax-code-bw,1px) solid var(--ax-code-bc,rgba(0,0,0,0.08));\n height:${a||"var(--ax-code-h,auto)"};\n max-height:${r||"var(--ax-code-mh,500px)"};\n overflow:auto;\n transition: border-color 0.3s ease,color 0.3s ease; \n border-radius: var(--ax-code-r,9px);\n }\n pre,code{\n font-family:"Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", "monospace", "microsoft yahei", "Microsoft JhengHei", "Yu Mincho", "simsun";\n margin:0;\n padding:0;\n }\n \n \n \n ${o}\n \n \n ${n?.internalCss||""}\n </style>\n <pre><code>${s}</code></pre>`}}customElements.define("ax-code",Coax),Coax.register("html",{rules:[{name:"comment",reg:/<!--[\s\S]*?-->/},{name:"doctype",reg:/<!DOCTYPE[\s\S]*?>/i},{name:"tag",reg:/<\/?[a-zA-Z0-9]+/},{name:"attr",reg:/[a-zA-Z-]+(?=\s*=\s*)/},{name:"string",reg:/(['"])(?:\\.|[^\\])*?\1/},{name:"bracket",reg:/\/?>/}]}),Coax.register("css",{rules:[{name:"comment",reg:/\/\*[\s\S]*?\*\//},{name:"value",reg:/(?:'|")(?:\\.|[^\\'"\b])*?(?:'|")/},{name:"func",reg:/[a-z-]+\(?=/},{name:"property",reg:/[a-z-]+(?=\s*:)/},{name:"selector",reg:/[.#a-z0-9, \n\t>:+()_-]+(?=\s*\{)/i},{name:"unit",reg:/(?<=\d)(px|em|rem|%|vh|vw|ms|s|deg)/},{name:"number",reg:/\b\d+(\.\d+)?\b/},{name:"punct",reg:/[{}();:]/}],theme:{type:"#61afef",keyword:"#d19a66",string:"#98c379",op:"#abb2bf"},internalCss:"\n .ax-css-string { color: var(--ax-code-string); }\n .ax-css-string::first-letter { color: var(--ax-code-c); }\n "}),Coax.register("js",{rules:[{name:"comment",reg:/\/\/[^\n]*|\/\*[\s\S]*?\*\//},{name:"string",reg:/(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/},{name:"keyword",reg:/\b(async|await|break|case|catch|class|const|continue|default|delete|do|else|export|extends|finally|for|function|if|import|in|instanceof|new|return|super|switch|this|throw|try|typeof|var|while|with|yield|let|static)\b/},{name:"builtin",reg:/\b(console|window|document|Math|JSON|true|false|null|undefined|Object|Array|Promise)\b/},{name:"number",reg:/\b\d+\b/},{name:"func",reg:/\b[a-zA-Z_]\w*(?=\s*\()/},{name:"op",reg:/[+\-*/%=<>!&|^~]+/}]}),Coax.register("ts",{rules:[{name:"comment",reg:/\/\/[^\n]*|\/\*[\s\S]*?\*\//},{name:"string",reg:/(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/},{name:"decorator",reg:/@[a-zA-Z_]\w*/},{name:"keyword",reg:/\b(abstract|as|async|await|break|case|catch|class|const|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|package|private|protected|public|readonly|return|set|static|super|switch|this|throw|try|type|typeof|var|while|with|yield)\b/},{name:"builtin",reg:/\b(any|boolean|never|number|string|symbol|unknown|void|undefined|null|boolean|true|false|console|window|document)\b/},{name:"type",reg:/\b[A-Z]\w*\b/},{name:"number",reg:/\b\d+\b/},{name:"func",reg:/\b[a-zA-Z_]\w*(?=\s*\()/},{name:"op",reg:/(\?\.|![:\.]|[+\-*/%=<>!&|^~]+)/}]});
|
package/dist/coax.esm.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
|
|
2
|
+
/*!
|
|
3
|
+
* @since Last modified: 2026-1-4 16:0:48
|
|
4
|
+
* @name Coax event management system.
|
|
5
|
+
* @version 0.0.1
|
|
6
|
+
* @author AXUI development team <3217728223@qq.com>
|
|
7
|
+
* @description Coax is a custom web component that enables syntax highlighting for various programming languages inside your HTML documents.
|
|
8
|
+
* @see {@link https://coax.axui.cn|Official website}
|
|
9
|
+
* @see {@link https://github.com/codady/coax/issues|github issues}
|
|
10
|
+
* @see {@link https://gitee.com/codady/coax/issues|Gitee issues}
|
|
11
|
+
* @see {@link https://www.npmjs.com/package/@codady/coax|NPM}
|
|
12
|
+
* @issue QQ Group No.1:952502085
|
|
13
|
+
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'coax', 'Coax' and 'COAX' within the software.
|
|
14
|
+
* @license MIT license
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
class Coax extends HTMLElement {
|
|
18
|
+
// A static Map to hold the configuration for different languages
|
|
19
|
+
static languages = new Map();
|
|
20
|
+
// Raw code as text from the HTML content
|
|
21
|
+
rawCode;
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
// Attach a Shadow DOM to the custom element
|
|
25
|
+
this.attachShadow({ mode: 'open' });
|
|
26
|
+
// Remove leading/trailing whitespace from the raw code content
|
|
27
|
+
this.rawCode = this.textContent?.replace(/^\s*\n|\n\s*$/g, '') || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static register(name, { rules, theme = {}, internalCss = '', cssPrefix = '' }) {
|
|
31
|
+
// Store the language configuration in the static map
|
|
32
|
+
this.languages.set(name, { rules, theme, internalCss, cssPrefix });
|
|
33
|
+
// Render the highlighted code for all elements with the registered language
|
|
34
|
+
document.querySelectorAll('ax-code').forEach(el => {
|
|
35
|
+
if (el.getAttribute('lang') === name)
|
|
36
|
+
el.render();
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// Called when the element is connected to the DOM
|
|
40
|
+
connectedCallback() { this.render(); }
|
|
41
|
+
// Observed attributes for changes
|
|
42
|
+
static get observedAttributes() { return ['lang', 'height', 'max-height']; }
|
|
43
|
+
|
|
44
|
+
attributeChangedCallback() {
|
|
45
|
+
this.render();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
render() {
|
|
49
|
+
// Get language name, fallback to 'js' if not provided
|
|
50
|
+
const lang = this.getAttribute('lang') || 'js',
|
|
51
|
+
// Get the language configuration
|
|
52
|
+
config = Coax.languages.get(lang),
|
|
53
|
+
// Default to language name if no prefix is set
|
|
54
|
+
cssPrefix = config?.cssPrefix || lang, height = this.getAttribute('height'), maxHeight = this.getAttribute('max-height');
|
|
55
|
+
let highlightedCode = '', dynamicStyles = '';
|
|
56
|
+
if (config) {
|
|
57
|
+
//Generate the highlighted HTML by applying the syntax rules
|
|
58
|
+
const combinedRegex = new RegExp(config.rules.map((r) => `(${r.reg.source})`).join('|'), 'g'), escaped = this.rawCode.replace(/[&<>]/g, m => ({ '&': '&', '<': '<', '>': '>' }[m]));
|
|
59
|
+
// Replace code with highlighted syntax
|
|
60
|
+
highlightedCode = escaped.replace(combinedRegex, (match, ...args) => {
|
|
61
|
+
const index = args.findIndex(val => val !== undefined);
|
|
62
|
+
return index !== -1 && config.rules[index] ? `<span class="ax-${cssPrefix}-${config.rules[index].name}">${match}</span>` : match;
|
|
63
|
+
});
|
|
64
|
+
//Generate dynamic CSS classes for each syntax rule
|
|
65
|
+
// 为 rules 中的每一个 name 生成类似 .hl-name { color: var(--ax-code-name); }
|
|
66
|
+
dynamicStyles = config.rules.map((rule) => `
|
|
67
|
+
.ax-${cssPrefix}-${rule.name} { color: var(--ax-${cssPrefix}-${rule.name}); }
|
|
68
|
+
`).join('\n');
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// If no config, display raw code without highlighting
|
|
72
|
+
highlightedCode = this.rawCode;
|
|
73
|
+
}
|
|
74
|
+
//Generate CSS theme variables if a theme is provided
|
|
75
|
+
const themeVars = config?.theme
|
|
76
|
+
? Object.entries(config.theme).map(([k, v]) => `--ax-${cssPrefix}-${k}: ${v};`).join('\n')
|
|
77
|
+
: '';
|
|
78
|
+
// Set the inner HTML of the shadow root, including styles and highlighted code
|
|
79
|
+
this.shadowRoot.innerHTML = `
|
|
80
|
+
<style>
|
|
81
|
+
:host {
|
|
82
|
+
${themeVars}
|
|
83
|
+
|
|
84
|
+
font-size: var(--ax-code-fs,14px);
|
|
85
|
+
display: block;
|
|
86
|
+
padding: var(--ax-code-p,1em);
|
|
87
|
+
box-sizing:border-box;
|
|
88
|
+
line-height: var(--ax-code-lh,1.5);
|
|
89
|
+
background-color:var(--ax-code-bg,rgba(0,0,0,0.02));
|
|
90
|
+
color:var(--ax-code-c,#333);
|
|
91
|
+
border:var(--ax-code-bw,1px) solid var(--ax-code-bc,rgba(0,0,0,0.08));
|
|
92
|
+
height:${height || 'var(--ax-code-h,auto)'};
|
|
93
|
+
max-height:${maxHeight || 'var(--ax-code-mh,500px)'};
|
|
94
|
+
overflow:auto;
|
|
95
|
+
transition: border-color 0.3s ease,color 0.3s ease;
|
|
96
|
+
border-radius: var(--ax-code-r,9px);
|
|
97
|
+
}
|
|
98
|
+
pre,code{
|
|
99
|
+
font-family:"Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", "monospace", "microsoft yahei", "Microsoft JhengHei", "Yu Mincho", "simsun";
|
|
100
|
+
margin:0;
|
|
101
|
+
padding:0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
${dynamicStyles}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
${config?.internalCss || ''}
|
|
110
|
+
</style>
|
|
111
|
+
<pre><code>${highlightedCode}</code></pre>`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
customElements.define('ax-code', Coax);
|
|
115
|
+
Coax.register('html', {
|
|
116
|
+
rules: [
|
|
117
|
+
{ name: 'comment', reg: /<!--[\s\S]*?-->/ },
|
|
118
|
+
{ name: 'doctype', reg: /<!DOCTYPE[\s\S]*?>/i },
|
|
119
|
+
// 匹配标签名: <div, </div
|
|
120
|
+
{ name: 'tag', reg: /<\/?[a-zA-Z0-9]+/ },
|
|
121
|
+
// 匹配属性名: class=
|
|
122
|
+
{ name: 'attr', reg: /[a-zA-Z-]+(?=\s*=\s*)/ },
|
|
123
|
+
// 匹配属性值: "value"
|
|
124
|
+
{ name: 'string', reg: /(['"])(?:\\.|[^\\])*?\1/ },
|
|
125
|
+
// 匹配标签闭合: >, />
|
|
126
|
+
{ name: 'bracket', reg: /\/?>/ }
|
|
127
|
+
],
|
|
128
|
+
//添加root变量:--ax-html-keyword
|
|
129
|
+
|
|
130
|
+
});
|
|
131
|
+
Coax.register('css', {
|
|
132
|
+
rules: [
|
|
133
|
+
{ name: 'comment', reg: /\/\*[\s\S]*?\*\// },
|
|
134
|
+
{ name: 'value', reg: /(?:'|")(?:\\.|[^\\'"\b])*?(?:'|")/ },
|
|
135
|
+
{ name: 'func', reg: /[a-z-]+\(?=/ },
|
|
136
|
+
{ name: 'property', reg: /[a-z-]+(?=\s*:)/ },
|
|
137
|
+
{ name: 'selector', reg: /[.#a-z0-9, \n\t>:+()_-]+(?=\s*\{)/i },
|
|
138
|
+
{ name: 'unit', reg: /(?<=\d)(px|em|rem|%|vh|vw|ms|s|deg)/ },
|
|
139
|
+
{ name: 'number', reg: /\b\d+(\.\d+)?\b/ },
|
|
140
|
+
{ name: 'punct', reg: /[{}();:]/ }
|
|
141
|
+
],
|
|
142
|
+
//添加root变量:--ax-code-keyword
|
|
143
|
+
theme: {
|
|
144
|
+
'type': '#61afef', // 蓝色选择器
|
|
145
|
+
'keyword': '#d19a66', // 橙色属性名
|
|
146
|
+
'string': '#98c379', // 绿色属性值
|
|
147
|
+
'op': '#abb2bf' // 灰色符号
|
|
148
|
+
},
|
|
149
|
+
internalCss: `
|
|
150
|
+
.ax-css-string { color: var(--ax-code-string); }
|
|
151
|
+
.ax-css-string::first-letter { color: var(--ax-code-c); }
|
|
152
|
+
`
|
|
153
|
+
});
|
|
154
|
+
Coax.register('js', {
|
|
155
|
+
rules: [
|
|
156
|
+
{ name: 'comment', reg: /\/\/[^\n]*|\/\*[\s\S]*?\*\// },
|
|
157
|
+
{ name: 'string', reg: /(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/ },
|
|
158
|
+
{ name: 'keyword', reg: /\b(async|await|break|case|catch|class|const|continue|default|delete|do|else|export|extends|finally|for|function|if|import|in|instanceof|new|return|super|switch|this|throw|try|typeof|var|while|with|yield|let|static)\b/ },
|
|
159
|
+
{ name: 'builtin', reg: /\b(console|window|document|Math|JSON|true|false|null|undefined|Object|Array|Promise)\b/ },
|
|
160
|
+
{ name: 'number', reg: /\b\d+\b/ },
|
|
161
|
+
{ name: 'func', reg: /\b[a-zA-Z_]\w*(?=\s*\()/ },
|
|
162
|
+
{ name: 'op', reg: /[+\-*/%=<>!&|^~]+/ }
|
|
163
|
+
],
|
|
164
|
+
|
|
165
|
+
});
|
|
166
|
+
Coax.register('ts', {
|
|
167
|
+
rules: [
|
|
168
|
+
{ name: 'comment', reg: /\/\/[^\n]*|\/\*[\s\S]*?\*\// },
|
|
169
|
+
{ name: 'string', reg: /(?:'|"|`)(?:\\.|[^\\'"\b])*?(?:'|"|`)/ },
|
|
170
|
+
{ name: 'decorator', reg: /@[a-zA-Z_]\w*/ },
|
|
171
|
+
{ name: 'keyword', reg: /\b(abstract|as|async|await|break|case|catch|class|const|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|package|private|protected|public|readonly|return|set|static|super|switch|this|throw|try|type|typeof|var|while|with|yield)\b/ },
|
|
172
|
+
{ name: 'builtin', reg: /\b(any|boolean|never|number|string|symbol|unknown|void|undefined|null|boolean|true|false|console|window|document)\b/ },
|
|
173
|
+
{ name: 'type', reg: /\b[A-Z]\w*\b/ },
|
|
174
|
+
{ name: 'number', reg: /\b\d+\b/ },
|
|
175
|
+
{ name: 'func', reg: /\b[a-zA-Z_]\w*(?=\s*\()/ },
|
|
176
|
+
{ name: 'op', reg: /(\?\.|![:\.]|[+\-*/%=<>!&|^~]+)/ }
|
|
177
|
+
],
|
|
178
|
+
|
|
179
|
+
});
|