@ktjs/core 0.6.12 → 0.6.16

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/dist/index.d.ts CHANGED
@@ -89,10 +89,6 @@ type KTEventHandlersOrAttribute = {
89
89
  [EventName in keyof HTMLElementEventMap]?: ((ev: HTMLElementEventMap[EventName]) => void) | string;
90
90
  };
91
91
 
92
- /**
93
- * Event handlers with @ prefix (e.g., @click, @input)
94
- * When key starts with @, it's always registered as an event handler
95
- */
96
92
  type KTPrefixedEventHandlers = {
97
93
  [EventName in keyof HTMLElementEventMap as `on:${EventName}`]?: (ev: HTMLElementEventMap[EventName]) => void;
98
94
  };
@@ -110,7 +106,7 @@ type HTML<T extends HTMLTag & otherstring> = T extends HTMLTag ? HTMLElementTagN
110
106
  * ## About
111
107
  * @package @ktjs/core
112
108
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
113
- * @version 0.6.12 (Last Update: 2025.12.24 21:28:18.471)
109
+ * @version 0.6.16 (Last Update: 2025.12.24 22:15:40.697)
114
110
  * @license MIT
115
111
  * @link https://github.com/baendlorel/kt.js
116
112
  * @link https://baendlorel.github.io/ Welcome to my site!
@@ -1 +1,307 @@
1
- var __ktjs_core__=function(e){"use strict";const t=e=>{throw new Error("kt.js: "+e)},n=Array.isArray,o=Object.keys,r=Object.defineProperties,s=(e,t)=>r(e,{t:{value:t,configurable:!0}}),i=()=>({});"undefined"==typeof Promise&&(window.Promise={resolve:i,reject:i}),(()=>{const e="__ktjs__";if(e in window)return;const n=Object.create(null);r(n,{throws:{value:t,enumerable:!0},defines:{value:r,enumerable:!0},mark:{value:s,enumerable:!0}}),r(window,{[e]:{value:n,enumerable:!0}})})();const u=Object.create(null),c=HTMLElement.prototype.appendChild,a=HTMLElement.prototype.append,l="function"==typeof a?function(...e){const t=e.filter(e=>e!==u);return a.apply(this,t)}:function(...e){if(e.length<50)for(let t=0;t<e.length;t++){const n=e[t];"string"==typeof n?c.call(this,document.createTextNode(n)):n!==u&&c.call(this,n)}else{const t=document.createDocumentFragment();for(let n=0;n<e.length;n++){const o=e[n];"string"==typeof o?c.call(t,document.createTextNode(o)):o!==u&&c.call(t,o)}c.call(this,t)}};function f(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function d(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}const m={checked:f,selected:f,value:d,valueAsDate:d,valueAsNumber:d,defaultValue:d,defaultChecked:f,defaultSelected:f,disabled:f,readOnly:f,multiple:f,required:f,autofocus:f,open:f,controls:f,autoplay:f,loop:f,muted:f,defer:f,async:f,hidden:function(e,t,n){e.hidden=!!n}},p=function(e,t,n){return e.setAttribute(t,n)};function b(e,n){"string"==typeof n?e.className=n:"object"==typeof n&&null!==n?function(e,t){const n=t.class,r=t.style;if(void 0!==n&&(e.className=n,delete t.class),r){if("string"==typeof r)e.setAttribute("style",r);else if("object"==typeof r)for(const t in r)e.style[t]=r[t];delete t.style}const s=o(t);for(let n=s.length-1;n>=0;n--){const o=s[n],r=t[o];o.startsWith("on:")?e.addEventListener(o.slice(1),r):"function"!=typeof r?(m[o]||p)(e,o,r):e.addEventListener(o,r)}void 0!==n&&(t.class=n),void 0!==r&&(t.style=r)}(e,n):t("attr must be an object/string.")}const y=(e,o="",r="")=>{"string"!=typeof e&&t("__func__ tagName must be a string.");const s=document.createElement(e);return b(s,o),function(e,t){n(t)?l.apply(e,t):"number"==typeof t?l.call(e,t.toString()):l.call(e,t)}(s,r),s};s(y,"h");const _={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};return e.h=y,e.ktnull=u,e.notSupportTextNode=function(e){return _[e]},e}({});
1
+ var __ktjs_core__ = (function (exports) {
2
+ 'use strict';
3
+
4
+ const $throw = (message) => {
5
+ throw new Error('kt.js: ' + message);
6
+ };
7
+
8
+ const $isArray = Array.isArray;
9
+ const $keys = Object.keys;
10
+ const $defines = Object.defineProperties;
11
+ const $mark = (func, tag) => $defines(func, { __ktjs_h__: { value: tag, configurable: true } });
12
+ const emptyPromiseHandler = () => ({});
13
+ if (typeof Promise === 'undefined') {
14
+ window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
15
+ }
16
+
17
+ (() => {
18
+ const runtimeKey = '__ktjs__';
19
+ if (runtimeKey in window) {
20
+ return;
21
+ }
22
+ const __ktjs__ = Object.create(null);
23
+ // & We can add new functions when we need more
24
+ const descriptor = {
25
+ throws: { value: $throw, enumerable: true },
26
+ defines: { value: $defines, enumerable: true },
27
+ mark: { value: $mark, enumerable: true },
28
+ };
29
+ $defines(__ktjs__, descriptor);
30
+ $defines(window, { [runtimeKey]: { value: __ktjs__, enumerable: true } });
31
+ return {};
32
+ })();
33
+
34
+ /**
35
+ * This is a `falsy` value used to indicate "no node" in `h` function.
36
+ * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
37
+ */
38
+ const ktnull = Object.create(null);
39
+
40
+ /**
41
+ * & Remove `bind` because it is shockingly slower than wrapper
42
+ * & `window.document` is safe because it is not configurable and its setter is undefined
43
+ */
44
+ const $appendChild = HTMLElement.prototype.appendChild;
45
+ const originAppend = HTMLElement.prototype.append;
46
+ const $append = // for ie 9/10/11
47
+ typeof originAppend === 'function'
48
+ ? function (...args) {
49
+ const nodes = args.filter((a) => a !== ktnull);
50
+ return originAppend.apply(this, nodes);
51
+ }
52
+ : function (...nodes) {
53
+ if (nodes.length < 50) {
54
+ for (let i = 0; i < nodes.length; i++) {
55
+ const node = nodes[i];
56
+ if (typeof node === 'string') {
57
+ $appendChild.call(this, document.createTextNode(node));
58
+ }
59
+ else if (node !== ktnull) {
60
+ $appendChild.call(this, node);
61
+ }
62
+ }
63
+ }
64
+ else {
65
+ const fragment = document.createDocumentFragment();
66
+ for (let i = 0; i < nodes.length; i++) {
67
+ const node = nodes[i];
68
+ if (typeof node === 'string') {
69
+ $appendChild.call(fragment, document.createTextNode(node));
70
+ }
71
+ else if (node !== ktnull) {
72
+ $appendChild.call(fragment, node);
73
+ }
74
+ }
75
+ $appendChild.call(this, fragment);
76
+ }
77
+ };
78
+
79
+ function booleanHandler(element, key, value) {
80
+ if (key in element) {
81
+ element[key] = !!value;
82
+ }
83
+ else {
84
+ element.setAttribute(key, value);
85
+ }
86
+ }
87
+ function valueHandler(element, key, value) {
88
+ if (key in element) {
89
+ element[key] = value;
90
+ }
91
+ else {
92
+ element.setAttribute(key, value);
93
+ }
94
+ }
95
+ // Attribute handlers map for optimized lookup
96
+ const handlers = {
97
+ checked: booleanHandler,
98
+ selected: booleanHandler,
99
+ value: valueHandler,
100
+ valueAsDate: valueHandler,
101
+ valueAsNumber: valueHandler,
102
+ defaultValue: valueHandler,
103
+ defaultChecked: booleanHandler,
104
+ defaultSelected: booleanHandler,
105
+ disabled: booleanHandler,
106
+ readOnly: booleanHandler,
107
+ multiple: booleanHandler,
108
+ required: booleanHandler,
109
+ autofocus: booleanHandler,
110
+ open: booleanHandler,
111
+ controls: booleanHandler,
112
+ autoplay: booleanHandler,
113
+ loop: booleanHandler,
114
+ muted: booleanHandler,
115
+ defer: booleanHandler,
116
+ async: booleanHandler,
117
+ hidden: function (element, _key, value) {
118
+ element.hidden = !!value;
119
+ },
120
+ };
121
+ const defaultHandler = function (element, key, value) {
122
+ return element.setAttribute(key, value);
123
+ };
124
+ function attrIsObject(element, attr) {
125
+ const classValue = attr.class;
126
+ const style = attr.style;
127
+ if (classValue !== undefined) {
128
+ element.className = classValue;
129
+ delete attr.class;
130
+ }
131
+ if (style) {
132
+ if (typeof style === 'string') {
133
+ element.setAttribute('style', style);
134
+ }
135
+ else if (typeof style === 'object') {
136
+ for (const key in style) {
137
+ element.style[key] = style[key];
138
+ }
139
+ }
140
+ delete attr.style;
141
+ }
142
+ const keys = $keys(attr);
143
+ for (let i = keys.length - 1; i >= 0; i--) {
144
+ const key = keys[i];
145
+ const o = attr[key];
146
+ // force register on:xxx as an event handler
147
+ // !if o is not valid, the throwing job will be done by `on`, not kt.js
148
+ if (key.startsWith('on:')) {
149
+ element.addEventListener(key.slice(3), o); // chop off the `@`
150
+ continue;
151
+ }
152
+ if (typeof o !== 'function') {
153
+ (handlers[key] || defaultHandler)(element, key, o);
154
+ }
155
+ else {
156
+ element.addEventListener(key, o);
157
+ }
158
+ }
159
+ if (classValue !== undefined) {
160
+ attr.class = classValue;
161
+ }
162
+ if (style !== undefined) {
163
+ attr.style = style;
164
+ }
165
+ }
166
+ function applyAttr(element, attr) {
167
+ if (typeof attr === 'string') {
168
+ element.className = attr;
169
+ }
170
+ else if (typeof attr === 'object' && attr !== null) {
171
+ attrIsObject(element, attr);
172
+ }
173
+ else {
174
+ $throw('attr must be an object/string.');
175
+ }
176
+ }
177
+
178
+ function applyContent(element, content) {
179
+ if ($isArray(content)) {
180
+ $append.apply(element, content);
181
+ }
182
+ else {
183
+ if (typeof content === 'number') {
184
+ $append.call(element, content.toString());
185
+ }
186
+ else {
187
+ $append.call(element, content);
188
+ }
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Create an enhanced HTMLElement.
194
+ * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
195
+ * @param tag tag of an `HTMLElement`
196
+ * @param attr attribute object or className
197
+ * @param content a string or an array of HTMLEnhancedElement as child nodes
198
+ *
199
+ * ## About
200
+ * @package @ktjs/core
201
+ * @author Kasukabe Tsumugi <futami16237@gmail.com>
202
+ * @version 0.6.16 (Last Update: 2025.12.24 22:15:40.697)
203
+ * @license MIT
204
+ * @link https://github.com/baendlorel/kt.js
205
+ * @link https://baendlorel.github.io/ Welcome to my site!
206
+ * @description Core functionality for kt.js - DOM manipulation utilities
207
+ * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
208
+ */
209
+ const h = (tag, attr = '', content = '') => {
210
+ if (typeof tag !== 'string') {
211
+ $throw('__func__ tagName must be a string.');
212
+ }
213
+ // * start creating the element
214
+ const element = document.createElement(tag);
215
+ // * Handle content
216
+ applyAttr(element, attr);
217
+ applyContent(element, content);
218
+ return element;
219
+ };
220
+ $mark(h, 'h');
221
+
222
+ /**
223
+ * # Specialized Ehancement
224
+ *
225
+ * Different elements should be enhanced in different ways. For example, we should have `kvalue` to handle `<input>` values.
226
+ * While we have no need to have `ktext` for `<br>` tags.
227
+ *
228
+ * ## Tags where appending a text node has no effect
229
+ *
230
+ * There are some HTML elements that appending a text node as their child takes no effect.
231
+ * They are mostly void elements, but some non-void elements are also included.
232
+ *
233
+ * ## What means no effect
234
+ * 1. appending a text node to these tags takes no effect.
235
+ * 2. No effect means `innerText` does not include the text in the text node.
236
+ *
237
+ * After testing 15 browsers testing, I found that these elements are:
238
+ *
239
+ * - FireFox(as base):
240
+ * - script -- this is skipped due to some bugs in The World 7
241
+ * - area, audio, base, basefont, br, canvas, datalist, details, dialog, frameset, head, iframe, img, input, link, meta, meter, noembed, noframes, noscript, optgroup, param, progress, rp, select, style, template, textarea, title, video, wbr
242
+ * - 360: embed
243
+ * - 2345: embed
244
+ * - maxthon: embed
245
+ * - quark: embed
246
+ * - uc: embed
247
+ * - chrome: embed,frame
248
+ * - qq: embed
249
+ * - sogou: embed
250
+ * - cent: embed
251
+ * - world: embed,frame,keygen,option
252
+ * - opera: embed
253
+ * - edge: embed
254
+ * - liebao: embed
255
+ * - 360turbo: embed,frame
256
+ *
257
+ * Since `Set.prototype.has` is about 80 times faster than `Array.prototype.includes`,
258
+ * We put these tags into a `Set` object.
259
+ */
260
+ const INVALID_TAGS = {
261
+ area: true,
262
+ audio: true,
263
+ base: true,
264
+ basefont: true,
265
+ br: true,
266
+ canvas: true,
267
+ datalist: true,
268
+ details: true,
269
+ dialog: true,
270
+ frameset: true,
271
+ head: true,
272
+ iframe: true,
273
+ img: true,
274
+ input: true,
275
+ link: true,
276
+ meta: true,
277
+ meter: true,
278
+ noembed: true,
279
+ noframes: true,
280
+ noscript: true,
281
+ optgroup: true,
282
+ param: true,
283
+ progress: true,
284
+ rp: true,
285
+ select: true,
286
+ style: true,
287
+ template: true,
288
+ textarea: true,
289
+ title: true,
290
+ video: true,
291
+ wbr: true,
292
+ embed: true,
293
+ frame: true,
294
+ keygen: true,
295
+ option: true,
296
+ };
297
+ function notSupportTextNode(tag) {
298
+ return INVALID_TAGS[tag];
299
+ }
300
+
301
+ exports.h = h;
302
+ exports.ktnull = ktnull;
303
+ exports.notSupportTextNode = notSupportTextNode;
304
+
305
+ return exports;
306
+
307
+ })({});
@@ -1 +1,320 @@
1
- var __ktjs_core__=function(e){"use strict";var t=function(e){throw new Error("kt.js: "+e)},n=Array.isArray,r=Object.keys,o=Object.defineProperties,a=function(e,t){return o(e,{t:{value:t,configurable:!0}})},i=function(){return{}};"undefined"==typeof Promise&&(window.Promise={resolve:i,reject:i}),function(){var e,n="__ktjs__";if(!(n in window)){var r=Object.create(null);o(r,{throws:{value:t,enumerable:!0},defines:{value:o,enumerable:!0},mark:{value:a,enumerable:!0}}),o(window,((e={})[n]={value:r,enumerable:!0},e))}}();var u=Object.create(null),f=HTMLElement.prototype.appendChild,l=HTMLElement.prototype.append,c="function"==typeof l?function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=e.filter(function(e){return e!==u});return l.apply(this,n)}:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(e.length<50)for(var n=0;n<e.length;n++){"string"==typeof(o=e[n])?f.call(this,document.createTextNode(o)):o!==u&&f.call(this,o)}else{var r=document.createDocumentFragment();for(n=0;n<e.length;n++){var o;"string"==typeof(o=e[n])?f.call(r,document.createTextNode(o)):o!==u&&f.call(r,o)}f.call(this,r)}};function s(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function d(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}var v={checked:s,selected:s,value:d,valueAsDate:d,valueAsNumber:d,defaultValue:d,defaultChecked:s,defaultSelected:s,disabled:s,readOnly:s,multiple:s,required:s,autofocus:s,open:s,controls:s,autoplay:s,loop:s,muted:s,defer:s,async:s,hidden:function(e,t,n){e.hidden=!!n}},m=function(e,t,n){return e.setAttribute(t,n)};function p(e,n){"string"==typeof n?e.className=n:"object"==typeof n&&null!==n?function(e,t){var n=t.class,o=t.style;if(void 0!==n&&(e.className=n,delete t.class),o){if("string"==typeof o)e.setAttribute("style",o);else if("object"==typeof o)for(var a in o)e.style[a]=o[a];delete t.style}for(var i=r(t),u=i.length-1;u>=0;u--){var f=t[a=i[u]];a.startsWith("on:")?e.addEventListener(a.slice(1),f):"function"!=typeof f?(v[a]||m)(e,a,f):e.addEventListener(a,f)}void 0!==n&&(t.class=n),void 0!==o&&(t.style=o)}(e,n):t("attr must be an object/string.")}var b=function(e,r,o){void 0===r&&(r=""),void 0===o&&(o=""),"string"!=typeof e&&t("__func__ tagName must be a string.");var a=document.createElement(e);return p(a,r),function(e,t){n(t)?c.apply(e,t):"number"==typeof t?c.call(e,t.toString()):c.call(e,t)}(a,o),a};a(b,"h");var y={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};return e.h=b,e.ktnull=u,e.notSupportTextNode=function(e){return y[e]},e}({});
1
+ var __ktjs_core__ = (function (exports) {
2
+ 'use strict';
3
+
4
+ var $throw = function (message) {
5
+ throw new Error('kt.js: ' + message);
6
+ };
7
+
8
+ var $isArray = Array.isArray;
9
+ var $keys = Object.keys;
10
+ var $defines = Object.defineProperties;
11
+ var $mark = function (func, tag) {
12
+ return $defines(func, { __ktjs_h__: { value: tag, configurable: true } });
13
+ };
14
+ var emptyPromiseHandler = function () { return ({}); };
15
+ if (typeof Promise === 'undefined') {
16
+ window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
17
+ }
18
+
19
+ ((function () {
20
+ var _a;
21
+ var runtimeKey = '__ktjs__';
22
+ if (runtimeKey in window) {
23
+ return;
24
+ }
25
+ var __ktjs__ = Object.create(null);
26
+ // & We can add new functions when we need more
27
+ var descriptor = {
28
+ throws: { value: $throw, enumerable: true },
29
+ defines: { value: $defines, enumerable: true },
30
+ mark: { value: $mark, enumerable: true },
31
+ };
32
+ $defines(__ktjs__, descriptor);
33
+ $defines(window, (_a = {}, _a[runtimeKey] = { value: __ktjs__, enumerable: true }, _a));
34
+ return {};
35
+ }))();
36
+
37
+ /**
38
+ * This is a `falsy` value used to indicate "no node" in `h` function.
39
+ * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
40
+ */
41
+ var ktnull = Object.create(null);
42
+
43
+ /**
44
+ * & Remove `bind` because it is shockingly slower than wrapper
45
+ * & `window.document` is safe because it is not configurable and its setter is undefined
46
+ */
47
+ var $appendChild = HTMLElement.prototype.appendChild;
48
+ var originAppend = HTMLElement.prototype.append;
49
+ var $append = // for ie 9/10/11
50
+ typeof originAppend === 'function'
51
+ ? function () {
52
+ var args = [];
53
+ for (var _i = 0; _i < arguments.length; _i++) {
54
+ args[_i] = arguments[_i];
55
+ }
56
+ var nodes = args.filter(function (a) { return a !== ktnull; });
57
+ return originAppend.apply(this, nodes);
58
+ }
59
+ : function () {
60
+ var nodes = [];
61
+ for (var _i = 0; _i < arguments.length; _i++) {
62
+ nodes[_i] = arguments[_i];
63
+ }
64
+ if (nodes.length < 50) {
65
+ for (var i = 0; i < nodes.length; i++) {
66
+ var node = nodes[i];
67
+ if (typeof node === 'string') {
68
+ $appendChild.call(this, document.createTextNode(node));
69
+ }
70
+ else if (node !== ktnull) {
71
+ $appendChild.call(this, node);
72
+ }
73
+ }
74
+ }
75
+ else {
76
+ var fragment = document.createDocumentFragment();
77
+ for (var i = 0; i < nodes.length; i++) {
78
+ var node = nodes[i];
79
+ if (typeof node === 'string') {
80
+ $appendChild.call(fragment, document.createTextNode(node));
81
+ }
82
+ else if (node !== ktnull) {
83
+ $appendChild.call(fragment, node);
84
+ }
85
+ }
86
+ $appendChild.call(this, fragment);
87
+ }
88
+ };
89
+
90
+ function booleanHandler(element, key, value) {
91
+ if (key in element) {
92
+ element[key] = !!value;
93
+ }
94
+ else {
95
+ element.setAttribute(key, value);
96
+ }
97
+ }
98
+ function valueHandler(element, key, value) {
99
+ if (key in element) {
100
+ element[key] = value;
101
+ }
102
+ else {
103
+ element.setAttribute(key, value);
104
+ }
105
+ }
106
+ // Attribute handlers map for optimized lookup
107
+ var handlers = {
108
+ checked: booleanHandler,
109
+ selected: booleanHandler,
110
+ value: valueHandler,
111
+ valueAsDate: valueHandler,
112
+ valueAsNumber: valueHandler,
113
+ defaultValue: valueHandler,
114
+ defaultChecked: booleanHandler,
115
+ defaultSelected: booleanHandler,
116
+ disabled: booleanHandler,
117
+ readOnly: booleanHandler,
118
+ multiple: booleanHandler,
119
+ required: booleanHandler,
120
+ autofocus: booleanHandler,
121
+ open: booleanHandler,
122
+ controls: booleanHandler,
123
+ autoplay: booleanHandler,
124
+ loop: booleanHandler,
125
+ muted: booleanHandler,
126
+ defer: booleanHandler,
127
+ async: booleanHandler,
128
+ hidden: function (element, _key, value) {
129
+ element.hidden = !!value;
130
+ },
131
+ };
132
+ var defaultHandler = function (element, key, value) {
133
+ return element.setAttribute(key, value);
134
+ };
135
+ function attrIsObject(element, attr) {
136
+ var classValue = attr.class;
137
+ var style = attr.style;
138
+ if (classValue !== undefined) {
139
+ element.className = classValue;
140
+ delete attr.class;
141
+ }
142
+ if (style) {
143
+ if (typeof style === 'string') {
144
+ element.setAttribute('style', style);
145
+ }
146
+ else if (typeof style === 'object') {
147
+ for (var key in style) {
148
+ element.style[key] = style[key];
149
+ }
150
+ }
151
+ delete attr.style;
152
+ }
153
+ var keys = $keys(attr);
154
+ for (var i = keys.length - 1; i >= 0; i--) {
155
+ var key = keys[i];
156
+ var o = attr[key];
157
+ // force register on:xxx as an event handler
158
+ // !if o is not valid, the throwing job will be done by `on`, not kt.js
159
+ if (key.startsWith('on:')) {
160
+ element.addEventListener(key.slice(3), o); // chop off the `@`
161
+ continue;
162
+ }
163
+ if (typeof o !== 'function') {
164
+ (handlers[key] || defaultHandler)(element, key, o);
165
+ }
166
+ else {
167
+ element.addEventListener(key, o);
168
+ }
169
+ }
170
+ if (classValue !== undefined) {
171
+ attr.class = classValue;
172
+ }
173
+ if (style !== undefined) {
174
+ attr.style = style;
175
+ }
176
+ }
177
+ function applyAttr(element, attr) {
178
+ if (typeof attr === 'string') {
179
+ element.className = attr;
180
+ }
181
+ else if (typeof attr === 'object' && attr !== null) {
182
+ attrIsObject(element, attr);
183
+ }
184
+ else {
185
+ $throw('attr must be an object/string.');
186
+ }
187
+ }
188
+
189
+ function applyContent(element, content) {
190
+ if ($isArray(content)) {
191
+ $append.apply(element, content);
192
+ }
193
+ else {
194
+ if (typeof content === 'number') {
195
+ $append.call(element, content.toString());
196
+ }
197
+ else {
198
+ $append.call(element, content);
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Create an enhanced HTMLElement.
205
+ * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
206
+ * @param tag tag of an `HTMLElement`
207
+ * @param attr attribute object or className
208
+ * @param content a string or an array of HTMLEnhancedElement as child nodes
209
+ *
210
+ * ## About
211
+ * @package @ktjs/core
212
+ * @author Kasukabe Tsumugi <futami16237@gmail.com>
213
+ * @version 0.6.16 (Last Update: 2025.12.24 22:15:40.697)
214
+ * @license MIT
215
+ * @link https://github.com/baendlorel/kt.js
216
+ * @link https://baendlorel.github.io/ Welcome to my site!
217
+ * @description Core functionality for kt.js - DOM manipulation utilities
218
+ * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
219
+ */
220
+ var h = function (tag, attr, content) {
221
+ if (attr === void 0) { attr = ''; }
222
+ if (content === void 0) { content = ''; }
223
+ if (typeof tag !== 'string') {
224
+ $throw('__func__ tagName must be a string.');
225
+ }
226
+ // * start creating the element
227
+ var element = document.createElement(tag);
228
+ // * Handle content
229
+ applyAttr(element, attr);
230
+ applyContent(element, content);
231
+ return element;
232
+ };
233
+ $mark(h, 'h');
234
+
235
+ /**
236
+ * # Specialized Ehancement
237
+ *
238
+ * Different elements should be enhanced in different ways. For example, we should have `kvalue` to handle `<input>` values.
239
+ * While we have no need to have `ktext` for `<br>` tags.
240
+ *
241
+ * ## Tags where appending a text node has no effect
242
+ *
243
+ * There are some HTML elements that appending a text node as their child takes no effect.
244
+ * They are mostly void elements, but some non-void elements are also included.
245
+ *
246
+ * ## What means no effect
247
+ * 1. appending a text node to these tags takes no effect.
248
+ * 2. No effect means `innerText` does not include the text in the text node.
249
+ *
250
+ * After testing 15 browsers testing, I found that these elements are:
251
+ *
252
+ * - FireFox(as base):
253
+ * - script -- this is skipped due to some bugs in The World 7
254
+ * - area, audio, base, basefont, br, canvas, datalist, details, dialog, frameset, head, iframe, img, input, link, meta, meter, noembed, noframes, noscript, optgroup, param, progress, rp, select, style, template, textarea, title, video, wbr
255
+ * - 360: embed
256
+ * - 2345: embed
257
+ * - maxthon: embed
258
+ * - quark: embed
259
+ * - uc: embed
260
+ * - chrome: embed,frame
261
+ * - qq: embed
262
+ * - sogou: embed
263
+ * - cent: embed
264
+ * - world: embed,frame,keygen,option
265
+ * - opera: embed
266
+ * - edge: embed
267
+ * - liebao: embed
268
+ * - 360turbo: embed,frame
269
+ *
270
+ * Since `Set.prototype.has` is about 80 times faster than `Array.prototype.includes`,
271
+ * We put these tags into a `Set` object.
272
+ */
273
+ var INVALID_TAGS = {
274
+ area: true,
275
+ audio: true,
276
+ base: true,
277
+ basefont: true,
278
+ br: true,
279
+ canvas: true,
280
+ datalist: true,
281
+ details: true,
282
+ dialog: true,
283
+ frameset: true,
284
+ head: true,
285
+ iframe: true,
286
+ img: true,
287
+ input: true,
288
+ link: true,
289
+ meta: true,
290
+ meter: true,
291
+ noembed: true,
292
+ noframes: true,
293
+ noscript: true,
294
+ optgroup: true,
295
+ param: true,
296
+ progress: true,
297
+ rp: true,
298
+ select: true,
299
+ style: true,
300
+ template: true,
301
+ textarea: true,
302
+ title: true,
303
+ video: true,
304
+ wbr: true,
305
+ embed: true,
306
+ frame: true,
307
+ keygen: true,
308
+ option: true,
309
+ };
310
+ function notSupportTextNode(tag) {
311
+ return INVALID_TAGS[tag];
312
+ }
313
+
314
+ exports.h = h;
315
+ exports.ktnull = ktnull;
316
+ exports.notSupportTextNode = notSupportTextNode;
317
+
318
+ return exports;
319
+
320
+ })({});
package/dist/index.mjs CHANGED
@@ -1 +1,298 @@
1
- const e=e=>{throw new Error("kt.js: "+e)},t=Array.isArray,n=Object.keys,o=Object.defineProperties,r=(e,t)=>o(e,{t:{value:t,configurable:!0}}),i=()=>({});"undefined"==typeof Promise&&(window.Promise={resolve:i,reject:i}),(()=>{const t="__ktjs__";if(t in window)return;const n=Object.create(null);o(n,{throws:{value:e,enumerable:!0},defines:{value:o,enumerable:!0},mark:{value:r,enumerable:!0}}),o(window,{[t]:{value:n,enumerable:!0}})})();const s=Object.create(null),u=HTMLElement.prototype.appendChild,a=HTMLElement.prototype.append,c="function"==typeof a?function(...e){const t=e.filter(e=>e!==s);return a.apply(this,t)}:function(...e){if(e.length<50)for(let t=0;t<e.length;t++){const n=e[t];"string"==typeof n?u.call(this,document.createTextNode(n)):n!==s&&u.call(this,n)}else{const t=document.createDocumentFragment();for(let n=0;n<e.length;n++){const o=e[n];"string"==typeof o?u.call(t,document.createTextNode(o)):o!==s&&u.call(t,o)}u.call(this,t)}};function l(e,t,n){t in e?e[t]=!!n:e.setAttribute(t,n)}function f(e,t,n){t in e?e[t]=n:e.setAttribute(t,n)}const d={checked:l,selected:l,value:f,valueAsDate:f,valueAsNumber:f,defaultValue:f,defaultChecked:l,defaultSelected:l,disabled:l,readOnly:l,multiple:l,required:l,autofocus:l,open:l,controls:l,autoplay:l,loop:l,muted:l,defer:l,async:l,hidden:function(e,t,n){e.hidden=!!n}},m=function(e,t,n){return e.setAttribute(t,n)};function p(t,o){"string"==typeof o?t.className=o:"object"==typeof o&&null!==o?function(e,t){const o=t.class,r=t.style;if(void 0!==o&&(e.className=o,delete t.class),r){if("string"==typeof r)e.setAttribute("style",r);else if("object"==typeof r)for(const t in r)e.style[t]=r[t];delete t.style}const i=n(t);for(let n=i.length-1;n>=0;n--){const o=i[n],r=t[o];o.startsWith("on:")?e.addEventListener(o.slice(1),r):"function"!=typeof r?(d[o]||m)(e,o,r):e.addEventListener(o,r)}void 0!==o&&(t.class=o),void 0!==r&&(t.style=r)}(t,o):e("attr must be an object/string.")}const b=(n,o="",r="")=>{"string"!=typeof n&&e("__func__ tagName must be a string.");const i=document.createElement(n);return p(i,o),function(e,n){t(n)?c.apply(e,n):"number"==typeof n?c.call(e,n.toString()):c.call(e,n)}(i,r),i};r(b,"h");const y={area:!0,audio:!0,base:!0,basefont:!0,br:!0,canvas:!0,datalist:!0,details:!0,dialog:!0,frameset:!0,head:!0,iframe:!0,img:!0,input:!0,link:!0,meta:!0,meter:!0,noembed:!0,noframes:!0,noscript:!0,optgroup:!0,param:!0,progress:!0,rp:!0,select:!0,style:!0,template:!0,textarea:!0,title:!0,video:!0,wbr:!0,embed:!0,frame:!0,keygen:!0,option:!0};function g(e){return y[e]}export{b as h,s as ktnull,g as notSupportTextNode};
1
+ const $throw = (message) => {
2
+ throw new Error('kt.js: ' + message);
3
+ };
4
+
5
+ const $isArray = Array.isArray;
6
+ const $keys = Object.keys;
7
+ const $defines = Object.defineProperties;
8
+ const $mark = (func, tag) => $defines(func, { __ktjs_h__: { value: tag, configurable: true } });
9
+ const emptyPromiseHandler = () => ({});
10
+ if (typeof Promise === 'undefined') {
11
+ window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
12
+ }
13
+
14
+ (() => {
15
+ const runtimeKey = '__ktjs__';
16
+ if (runtimeKey in window) {
17
+ return;
18
+ }
19
+ const __ktjs__ = Object.create(null);
20
+ // & We can add new functions when we need more
21
+ const descriptor = {
22
+ throws: { value: $throw, enumerable: true },
23
+ defines: { value: $defines, enumerable: true },
24
+ mark: { value: $mark, enumerable: true },
25
+ };
26
+ $defines(__ktjs__, descriptor);
27
+ $defines(window, { [runtimeKey]: { value: __ktjs__, enumerable: true } });
28
+ return {};
29
+ })();
30
+
31
+ /**
32
+ * This is a `falsy` value used to indicate "no node" in `h` function.
33
+ * - It's an object, so it's guaranteed to be unique and no need for polyfill of `symbol`.
34
+ */
35
+ const ktnull = Object.create(null);
36
+
37
+ /**
38
+ * & Remove `bind` because it is shockingly slower than wrapper
39
+ * & `window.document` is safe because it is not configurable and its setter is undefined
40
+ */
41
+ const $appendChild = HTMLElement.prototype.appendChild;
42
+ const originAppend = HTMLElement.prototype.append;
43
+ const $append = // for ie 9/10/11
44
+ typeof originAppend === 'function'
45
+ ? function (...args) {
46
+ const nodes = args.filter((a) => a !== ktnull);
47
+ return originAppend.apply(this, nodes);
48
+ }
49
+ : function (...nodes) {
50
+ if (nodes.length < 50) {
51
+ for (let i = 0; i < nodes.length; i++) {
52
+ const node = nodes[i];
53
+ if (typeof node === 'string') {
54
+ $appendChild.call(this, document.createTextNode(node));
55
+ }
56
+ else if (node !== ktnull) {
57
+ $appendChild.call(this, node);
58
+ }
59
+ }
60
+ }
61
+ else {
62
+ const fragment = document.createDocumentFragment();
63
+ for (let i = 0; i < nodes.length; i++) {
64
+ const node = nodes[i];
65
+ if (typeof node === 'string') {
66
+ $appendChild.call(fragment, document.createTextNode(node));
67
+ }
68
+ else if (node !== ktnull) {
69
+ $appendChild.call(fragment, node);
70
+ }
71
+ }
72
+ $appendChild.call(this, fragment);
73
+ }
74
+ };
75
+
76
+ function booleanHandler(element, key, value) {
77
+ if (key in element) {
78
+ element[key] = !!value;
79
+ }
80
+ else {
81
+ element.setAttribute(key, value);
82
+ }
83
+ }
84
+ function valueHandler(element, key, value) {
85
+ if (key in element) {
86
+ element[key] = value;
87
+ }
88
+ else {
89
+ element.setAttribute(key, value);
90
+ }
91
+ }
92
+ // Attribute handlers map for optimized lookup
93
+ const handlers = {
94
+ checked: booleanHandler,
95
+ selected: booleanHandler,
96
+ value: valueHandler,
97
+ valueAsDate: valueHandler,
98
+ valueAsNumber: valueHandler,
99
+ defaultValue: valueHandler,
100
+ defaultChecked: booleanHandler,
101
+ defaultSelected: booleanHandler,
102
+ disabled: booleanHandler,
103
+ readOnly: booleanHandler,
104
+ multiple: booleanHandler,
105
+ required: booleanHandler,
106
+ autofocus: booleanHandler,
107
+ open: booleanHandler,
108
+ controls: booleanHandler,
109
+ autoplay: booleanHandler,
110
+ loop: booleanHandler,
111
+ muted: booleanHandler,
112
+ defer: booleanHandler,
113
+ async: booleanHandler,
114
+ hidden: function (element, _key, value) {
115
+ element.hidden = !!value;
116
+ },
117
+ };
118
+ const defaultHandler = function (element, key, value) {
119
+ return element.setAttribute(key, value);
120
+ };
121
+ function attrIsObject(element, attr) {
122
+ const classValue = attr.class;
123
+ const style = attr.style;
124
+ if (classValue !== undefined) {
125
+ element.className = classValue;
126
+ delete attr.class;
127
+ }
128
+ if (style) {
129
+ if (typeof style === 'string') {
130
+ element.setAttribute('style', style);
131
+ }
132
+ else if (typeof style === 'object') {
133
+ for (const key in style) {
134
+ element.style[key] = style[key];
135
+ }
136
+ }
137
+ delete attr.style;
138
+ }
139
+ const keys = $keys(attr);
140
+ for (let i = keys.length - 1; i >= 0; i--) {
141
+ const key = keys[i];
142
+ const o = attr[key];
143
+ // force register on:xxx as an event handler
144
+ // !if o is not valid, the throwing job will be done by `on`, not kt.js
145
+ if (key.startsWith('on:')) {
146
+ element.addEventListener(key.slice(3), o); // chop off the `@`
147
+ continue;
148
+ }
149
+ if (typeof o !== 'function') {
150
+ (handlers[key] || defaultHandler)(element, key, o);
151
+ }
152
+ else {
153
+ element.addEventListener(key, o);
154
+ }
155
+ }
156
+ if (classValue !== undefined) {
157
+ attr.class = classValue;
158
+ }
159
+ if (style !== undefined) {
160
+ attr.style = style;
161
+ }
162
+ }
163
+ function applyAttr(element, attr) {
164
+ if (typeof attr === 'string') {
165
+ element.className = attr;
166
+ }
167
+ else if (typeof attr === 'object' && attr !== null) {
168
+ attrIsObject(element, attr);
169
+ }
170
+ else {
171
+ $throw('attr must be an object/string.');
172
+ }
173
+ }
174
+
175
+ function applyContent(element, content) {
176
+ if ($isArray(content)) {
177
+ $append.apply(element, content);
178
+ }
179
+ else {
180
+ if (typeof content === 'number') {
181
+ $append.call(element, content.toString());
182
+ }
183
+ else {
184
+ $append.call(element, content);
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Create an enhanced HTMLElement.
191
+ * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
192
+ * @param tag tag of an `HTMLElement`
193
+ * @param attr attribute object or className
194
+ * @param content a string or an array of HTMLEnhancedElement as child nodes
195
+ *
196
+ * ## About
197
+ * @package @ktjs/core
198
+ * @author Kasukabe Tsumugi <futami16237@gmail.com>
199
+ * @version 0.6.16 (Last Update: 2025.12.24 22:15:40.697)
200
+ * @license MIT
201
+ * @link https://github.com/baendlorel/kt.js
202
+ * @link https://baendlorel.github.io/ Welcome to my site!
203
+ * @description Core functionality for kt.js - DOM manipulation utilities
204
+ * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
205
+ */
206
+ const h = (tag, attr = '', content = '') => {
207
+ if (typeof tag !== 'string') {
208
+ $throw('__func__ tagName must be a string.');
209
+ }
210
+ // * start creating the element
211
+ const element = document.createElement(tag);
212
+ // * Handle content
213
+ applyAttr(element, attr);
214
+ applyContent(element, content);
215
+ return element;
216
+ };
217
+ $mark(h, 'h');
218
+
219
+ /**
220
+ * # Specialized Ehancement
221
+ *
222
+ * Different elements should be enhanced in different ways. For example, we should have `kvalue` to handle `<input>` values.
223
+ * While we have no need to have `ktext` for `<br>` tags.
224
+ *
225
+ * ## Tags where appending a text node has no effect
226
+ *
227
+ * There are some HTML elements that appending a text node as their child takes no effect.
228
+ * They are mostly void elements, but some non-void elements are also included.
229
+ *
230
+ * ## What means no effect
231
+ * 1. appending a text node to these tags takes no effect.
232
+ * 2. No effect means `innerText` does not include the text in the text node.
233
+ *
234
+ * After testing 15 browsers testing, I found that these elements are:
235
+ *
236
+ * - FireFox(as base):
237
+ * - script -- this is skipped due to some bugs in The World 7
238
+ * - area, audio, base, basefont, br, canvas, datalist, details, dialog, frameset, head, iframe, img, input, link, meta, meter, noembed, noframes, noscript, optgroup, param, progress, rp, select, style, template, textarea, title, video, wbr
239
+ * - 360: embed
240
+ * - 2345: embed
241
+ * - maxthon: embed
242
+ * - quark: embed
243
+ * - uc: embed
244
+ * - chrome: embed,frame
245
+ * - qq: embed
246
+ * - sogou: embed
247
+ * - cent: embed
248
+ * - world: embed,frame,keygen,option
249
+ * - opera: embed
250
+ * - edge: embed
251
+ * - liebao: embed
252
+ * - 360turbo: embed,frame
253
+ *
254
+ * Since `Set.prototype.has` is about 80 times faster than `Array.prototype.includes`,
255
+ * We put these tags into a `Set` object.
256
+ */
257
+ const INVALID_TAGS = {
258
+ area: true,
259
+ audio: true,
260
+ base: true,
261
+ basefont: true,
262
+ br: true,
263
+ canvas: true,
264
+ datalist: true,
265
+ details: true,
266
+ dialog: true,
267
+ frameset: true,
268
+ head: true,
269
+ iframe: true,
270
+ img: true,
271
+ input: true,
272
+ link: true,
273
+ meta: true,
274
+ meter: true,
275
+ noembed: true,
276
+ noframes: true,
277
+ noscript: true,
278
+ optgroup: true,
279
+ param: true,
280
+ progress: true,
281
+ rp: true,
282
+ select: true,
283
+ style: true,
284
+ template: true,
285
+ textarea: true,
286
+ title: true,
287
+ video: true,
288
+ wbr: true,
289
+ embed: true,
290
+ frame: true,
291
+ keygen: true,
292
+ option: true,
293
+ };
294
+ function notSupportTextNode(tag) {
295
+ return INVALID_TAGS[tag];
296
+ }
297
+
298
+ export { h, ktnull, notSupportTextNode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/core",
3
- "version": "0.6.12",
3
+ "version": "0.6.16",
4
4
  "description": "Core functionality for kt.js - DOM manipulation utilities",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",