@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 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: /&lt;!--[\s\S]*?--&gt;/ },
60
+ { name: 'tag', reg: /&lt;\/?[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: /&lt;!--[\s\S]*?--&gt;/ },
182
+ { name: 'tag', reg: /&lt;\/?[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
+
@@ -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 => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[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: /&lt;!--[\s\S]*?--&gt;/ },
120
+ { name: 'doctype', reg: /&lt;!DOCTYPE[\s\S]*?&gt;/i },
121
+ // 匹配标签名: <div, </div
122
+ { name: 'tag', reg: /&lt;\/?[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: /\/?&gt;/ }
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=>({"&":"&amp;","<":"&lt;",">":"&gt;"}[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:/&lt;!--[\s\S]*?--&gt;/},{name:"doctype",reg:/&lt;!DOCTYPE[\s\S]*?&gt;/i},{name:"tag",reg:/&lt;\/?[a-zA-Z0-9]+/},{name:"attr",reg:/[a-zA-Z-]+(?=\s*=\s*)/},{name:"string",reg:/(['"])(?:\\.|[^\\])*?\1/},{name:"bracket",reg:/\/?&gt;/}]}),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:/(\?\.|![:\.]|[+\-*/%=<>!&|^~]+)/}]});
@@ -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 => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[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: /&lt;!--[\s\S]*?--&gt;/ },
118
+ { name: 'doctype', reg: /&lt;!DOCTYPE[\s\S]*?&gt;/i },
119
+ // 匹配标签名: <div, </div
120
+ { name: 'tag', reg: /&lt;\/?[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: /\/?&gt;/ }
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
+ });