kt.js 0.0.7 → 0.0.8

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/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # KT.js
2
2
 
3
- [中文](./README.zh.md) | [English](./README.md)
3
+ [![license](https://img.shields.io/github/license/baendlorel/kt.js.svg)](https://github.com/baendlorel/kt.js/blob/main/LICENSE)
4
4
 
5
- For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
5
+ [中文](README.zh.md) | [English](README.md) | [CHANGLOG](CHANGELOG.md)
6
6
 
7
7
  > Note: This framework is still under development. APIs, type declarations, and other parts may change. If you use it, please watch for updates in the near future.
8
8
 
9
9
  KT.js is a tiny, high-performance DOM utility focused on minimal re-rendering and direct DOM manipulation. It favors not forcing re-renders and aims to keep DOM updates to the absolute minimum for maximum performance.
10
10
 
11
+ For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
12
+
11
13
  ## Philosophy
12
14
 
13
15
  As a web framework, repeatedly creating a large number of variables and objects is unacceptable. This is a provocation against browsers and the V8 engine(or SpiderMonkey, or JSC). So I created KT.js.
package/README.zh.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # KT.js
2
2
 
3
- [中文](./README.zh.md) | [English](./README.md)
3
+ [![license](https://img.shields.io/github/license/baendlorel/kt.js.svg)](https://github.com/baendlorel/kt.js/blob/main/LICENSE)
4
4
 
5
- For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
5
+ [中文](README.zh.md) | [English](README.md) | [更新日志](CHANGELOG.md)
6
6
 
7
7
  > Note: 本框架还在开发中,api、类型声明等可能会有变化,如果使用,近期请关注更新
8
8
 
9
9
  KT.js 是一个微小的高性能 DOM 工具,专注于最小化重绘和直接操作 DOM。它的设计目标是尽量不强制重绘,只在必要时更新 DOM,从而获得极致性能。
10
10
 
11
+ For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
12
+
11
13
  ## 核心理念
12
14
 
13
15
  作为一个web框架,反复创建大量对象、反复重绘是不可接受的,这是对浏览器和V8引擎(或者SpiderMonkey, 或者说JSC)的挑衅。所以我创建了 KT.js。
package/dist/index.d.ts CHANGED
@@ -4,15 +4,16 @@
4
4
  * @param attr attribute object or className
5
5
  * @param content a string or an array of HTMLEnhancedElement as child nodes
6
6
  */
7
- declare function h<Tag extends HTMLElementTag>(tag: Tag, attr?: KAttribute | string, content?: (HTMLKEnhancedElement | string)[] | HTMLKEnhancedElement | string): HTMLKEnhancedElement<Tag>;
7
+ declare function h<T extends HTMLTag>(tag: T, attr?: KAttribute | string, content?: (HTMLKEnhancedElement | string)[] | HTMLKEnhancedElement | string): HTMLKEnhancedElement<T>;
8
8
 
9
9
  /**
10
10
  * ## About
11
11
  * @package Kt.js
12
12
  * @author Kasukabe Tsumugi <futami16237@gmail.com>
13
- * @version 0.0.7 (Last Update: 2025.09.19 21:53:16.950)
13
+ * @version 0.0.8 (Last Update: 2025.09.20 15:12:59.928)
14
14
  * @license MIT
15
15
  * @link https://github.com/baendlorel/kt.js
16
+ * @link https://baendlorel.github.io/ Welcome to my site!
16
17
  * @description A simple and easy-to-use web framework, never re-render. Abbreviation of Kasukabe Tsumugi.
17
18
  * @copyright Copyright (c) 2025 Kasukabe Tsumugi. All rights reserved.
18
19
  *
@@ -27,10 +28,23 @@ export { createApp, h };
27
28
 
28
29
  // # from: src/global.d.ts
29
30
 
31
+ // # from: src/types/core.d.ts
32
+ type HFunction = <T extends HTMLTag>(
33
+ tag: T,
34
+ attr?: KAttribute | string,
35
+ content?: (HTMLKEnhancedElement | string)[] | HTMLKEnhancedElement | string
36
+ ) => HTMLKEnhancedElement<T>;
37
+
38
+ type HAlias<T extends HTMLTag> = (
39
+ attr?: KAttribute | string,
40
+ content?: (HTMLKEnhancedElement | string)[] | HTMLKEnhancedElement | string
41
+ ) => HTMLKEnhancedElement<T>;
42
+
30
43
  /**
31
44
  * Used to create enhanced HTML elements
32
45
  */
33
46
  export interface KAttribute {
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
48
  [k: string]: any;
35
49
 
36
50
  id?: string;
@@ -61,6 +75,11 @@ export interface KAttribute {
61
75
  | (string & {});
62
76
  }
63
77
 
78
+ // # from: src/types/enhance.d.ts
79
+ export type HTMLTag = keyof HTMLElementTagNameMap;
80
+
81
+ export type KChildren = HTMLKEnhancedElement | Text;
82
+
64
83
  interface KOnOptions extends AddEventListenerOptions {
65
84
  /**
66
85
  * This option's priority is higher than `once`.
@@ -74,23 +93,17 @@ type KListener<E extends HTMLElement, K extends keyof HTMLElementEventMap> = (
74
93
  ev: HTMLElementEventMap[K]
75
94
  ) => unknown;
76
95
 
77
- // # from: src/types/enhance.d.ts
78
- export type HTMLElementTag = keyof HTMLElementTagNameMap;
79
-
80
- export type KChildren = HTMLKEnhancedElement | Text;
81
-
82
- interface KEnhanced {
96
+ interface KEnhancedPrivates {
83
97
  /**
84
98
  * Unique numeric identifier for a KT.js enhanced element instance.
85
99
  * Used internally to track and distinguish enhanced elements.
86
100
  */
87
- kid: number;
101
+ id: number;
88
102
 
89
- /**
90
- * Marker property that is always true for enhanced elements.
91
- */
92
- isKT: true;
103
+ text: Text;
104
+ }
93
105
 
106
+ interface KEnhanced {
94
107
  /**
95
108
  * The element's text content as maintained by KT.js.
96
109
  * - it is not recommended to use `textContent` any more
@@ -168,6 +181,24 @@ type NonSpecialTags = {
168
181
  * It combines the standard HTMLElement properties and methods
169
182
  * with KT.js enhancements defined in KEnhanced.
170
183
  */
171
- export type HTMLKEnhancedElement<T extends HTMLElementTag = NonSpecialTags> =
184
+ export type HTMLKEnhancedElement<T extends HTMLTag = NonSpecialTags> =
172
185
  (HTMLElement extends HTMLElementTagNameMap[T] ? HTMLElement : HTMLElementTagNameMap[T]) &
173
186
  KEnhanced;
187
+
188
+ // # from: src/types/type-utils.d.ts
189
+ type IsSameType<A, B> =
190
+ (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2
191
+ ? (<T>() => T extends B ? 1 : 2) extends <T>() => T extends A ? 1 : 2
192
+ ? true
193
+ : false
194
+ : false;
195
+
196
+ type PickProperty<T> = {
197
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
+ [K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];
199
+ };
200
+
201
+ type PickMethod<T> = {
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ [K in keyof T as T[K] extends (...args: any[]) => any ? K : never]: T[K];
204
+ };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- const e=Symbol("KText"),t=Symbol("NotProvided"),n=Reflect.set,o=Reflect.get,i=Reflect.defineProperty,r=Array.isArray,s=Array.from,a=Object.keys,l=Object.assign,c=document.getElementById.bind(document),f=document.createElement.bind(document),u=document.createTextNode.bind(document),m=HTMLElement.prototype.addEventListener,T=HTMLElement.prototype.removeEventListener,d=HTMLElement.prototype.appendChild,h=HTMLElement.prototype.setAttribute;class E extends(null){static kid=0;static index=0;static genIndex(){return"data-k-"+(++E.index).toString(36).padStart(6,"0")}static nextKid(){return++E.kid}}const p=Object.is,M=Number.isSafeInteger,L=e=>"object"==typeof e&&null!==e,H={get:function(){return o(this,e).textContent},set:function(t){o(this,e).textContent=t}},y={value:!0},w={get(){return s(this.children)},set(e){this.innerHTML="";const t=e.length;for(let n=0;n<t;n++){const t=e[n];if("string"!=typeof t){if(!(t instanceof Text||t.isKT))throw new TypeError(`[Kt.js:kchildren] Invalid child element at index ${n}. Only string, Text nodes or KT.js enhanced elements are allowed.`);d.call(this,t)}else d.call(this,u(t))}}};function g(e,n,o=t){if(p(o,t))return m.call(this,e,n),n;if(!L(o)||!("triggerLimit"in o))return m.call(this,e,n,o),n;const i=o.triggerLimit;if(delete o.triggerLimit,!M(i)||i<=0)throw new TypeError("[Kt.js:kon] options.triggerLimit must be a positive safe integer.");if(1===i)return o.once=!0,m.call(this,e,n,o),n;let r=i;const s=function(t){const i=n.call(this,t);return r--,r<=0&&T.call(this,e,s,o),i};return m.call(this,e,s,o),s}function B(e,n,o=t){p(t,o)?T.call(this,e,n):T.call(this,e,n,o)}function b(e){if(!e.isKT)throw new TypeError("[Kt.js:kmount] target must be a KText element.");return d.call(e,this)}function x(e){i(e,"kid",{value:E.nextKid(),enumerable:!0}),i(e,"isKT",y),i(e,"ktext",H),i(e,"kchildren",w),e.kon=g,e.koff=B,e.kmount=b}class S{t=null;o=null;add(e,t){if("function"!=typeof t)throw new TypeError("Branch must be a function");return e&&(this.t=t),this}nomatch(e){if("function"!=typeof e)throw new TypeError("Branch must be a function");return this.t||e(),this}deferedNomatch(e){if("function"!=typeof e)throw new TypeError("Branch must be a function");return this.o=e,this}run(...e){return this.t?this.t(...e):this.o?this.o(...e):void 0}}const j=()=>new S,K=(e,t)=>e.className=t,k=(e,t)=>{t.class&&(r(t.class)?e.classList.add(...t.class):e.className=t.class,delete t.class),t.style&&("string"==typeof t.style?e.setAttribute("style",t.style):l(e.style,t.style),delete t.style);const n=a(t),o=n.length;for(let i=0;i<o;i++){const o=n[i],r=t[o];"function"!=typeof r&&("checked"!==o?"value"!==o?"selected"!==o?"defaultValue"!==o?"defaultChecked"!==o?"defaultSelected"!==o?"disabled"!==o?"readOnly"!==o?"multiple"!==o?"autofocus"!==o?"required"!==o?"hidden"!==o?"open"===o&&e instanceof HTMLDetailsElement?e.open=Boolean(r):"controls"===o&&e instanceof HTMLMediaElement?e.controls=Boolean(r):"autoplay"===o&&e instanceof HTMLMediaElement?e.autoplay=Boolean(r):"loop"===o&&e instanceof HTMLMediaElement?e.loop=Boolean(r):"muted"===o&&e instanceof HTMLMediaElement?e.muted=Boolean(r):"defer"===o&&e instanceof HTMLScriptElement?e.defer=Boolean(r):"async"===o&&e instanceof HTMLScriptElement?e.async=Boolean(r):h.call(e,String(o),r):e.hidden=Boolean(r):e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.required=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.autofocus=Boolean(r):h.call(e,o,r):e instanceof HTMLSelectElement?e.multiple=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.readOnly=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLOptGroupElement||e instanceof HTMLOptionElement||e instanceof HTMLFieldSetElement||e instanceof HTMLTextAreaElement?e.disabled=Boolean(r):h.call(e,o,r):e instanceof HTMLOptionElement?e.defaultSelected=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement?e.defaultChecked=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.defaultValue=String(r):h.call(e,o,r):e instanceof HTMLOptionElement?e.selected=Boolean(r):h.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value=String(r):h.call(e,o,r):e instanceof HTMLInputElement?e.checked=Boolean(r):h.call(e,o,r))}},I=()=>{throw new TypeError("[Kt.js:h] attr must be an object.")},O=(e,t)=>{e.ktext=t},A=(e,t)=>{const n=t.length;for(let o=0;o<n;o++){const n=t[o];"string"!=typeof n?n.isKT?d.call(e,n):N():d.call(e,u(n))}},v=(e,t)=>{t.isKT||N(),d.call(e,t)},N=()=>{throw new TypeError("[Kt.js:h] content must be a string, HTMLEnhancedElement or an array of HTMLEnhancedElement.")};function R(t,o="",i=""){if("string"!=typeof t)throw new TypeError("[Kt.js:h] tagName must be a string.");const s=(e=>j().add("string"==typeof e,K).add(L(e),k).nomatch(I))(o),a=(e=>j().add("string"==typeof e,O).add(L(e),v).add(r(e),A).nomatch(N))(i),l=f(t),c=u("");return d.call(l,c),n(l,e,c),x(l),a.run(l,i),s.run(l,o),l}function q(e,n=t){if(!e.isKT)throw new TypeError("Root element must be a KText element.");const o=c("app")??document.body;if(p(n,t))d.call(o,e);else if(!L(n))throw new TypeError("mountTo must be an HTMLElement or omitted.")}export{q as createApp,R as h};
1
+ const e=Symbol("NotProvided");class t extends(null){static kid=0;static index=0;static genIndex(){return"data-k-"+(++t.index).toString(36).padStart(6,"0")}static nextKid(){return++t.kid}}const n=e=>document.createTextNode(e),o=HTMLElement.prototype.addEventListener,i=HTMLElement.prototype.removeEventListener,r=HTMLElement.prototype.appendChild,s=HTMLElement.prototype.setAttribute,a=Array.isArray,l=Array.from,c=Object.keys,f=Object.assign,m=Object.defineProperties,u=Object.is,T=Number.isSafeInteger,h=e=>"object"==typeof e&&null!==e,E=new WeakMap,d=e=>E.get(e),p=e=>E.has(e),M={kon(t,n,r=e){if(u(r,e))return o.call(this,t,n),n;if(!h(r)||!("triggerLimit"in r))return o.call(this,t,n,r),n;const s=r.triggerLimit;if(delete r.triggerLimit,!T(s)||s<=0)throw new TypeError("[Kt.js:kon] options.triggerLimit must be a positive safe integer.");if(1===s)return r.once=!0,o.call(this,t,n,r),n;let a=s;const l=function(e){const o=n.call(this,e);return a--,a<=0&&i.call(this,t,l,r),o};return o.call(this,t,l,r),l},koff(t,n,o=e){u(e,o)?i.call(this,t,n):i.call(this,t,n,o)},kmount(e){if(!p(e))throw new TypeError("[Kt.js:kmount] target must be a KText element.");return r.call(e,this)}},L={ktext:{get(){return d(this).text.textContent},set(e){d(this).text.textContent=e}},kchildren:{get(){return l(this.children)},set(e){this.textContent="",r.call(this,d(this).text);const t=e.length;for(let o=0;o<t;o++){const t=e[o];if("string"!=typeof t){if(!(t instanceof Text||p(t)))throw new TypeError(`[Kt.js:kchildren] Invalid child element at index ${o}. Only string, Text nodes or KT.js enhanced elements are allowed.`);r.call(this,t)}else r.call(this,n(t))}}}};class H{t=null;o=null;add(e,t){if("function"!=typeof t)throw new TypeError("Branch must be a function");return e&&(this.t=t),this}nomatch(e){if("function"!=typeof e)throw new TypeError("Branch must be a function");return this.t||e(),this}deferedNomatch(e){if("function"!=typeof e)throw new TypeError("Branch must be a function");return this.o=e,this}run(...e){return this.t?this.t(...e):this.o?this.o(...e):void 0}}const y=()=>new H,w=(e,t)=>e.className=t,g=(e,t)=>{t.class&&(a(t.class)?e.classList.add(...t.class):e.className=t.class,delete t.class),t.style&&("string"==typeof t.style?e.setAttribute("style",t.style):f(e.style,t.style),delete t.style);const n=c(t),o=n.length;for(let i=0;i<o;i++){const o=n[i],r=t[o];"function"!=typeof r&&("checked"!==o?"value"!==o?"selected"!==o?"defaultValue"!==o?"defaultChecked"!==o?"defaultSelected"!==o?"disabled"!==o?"readOnly"!==o?"multiple"!==o?"autofocus"!==o?"required"!==o?"hidden"!==o?"open"===o&&e instanceof HTMLDetailsElement?e.open=Boolean(r):"controls"===o&&e instanceof HTMLMediaElement?e.controls=Boolean(r):"autoplay"===o&&e instanceof HTMLMediaElement?e.autoplay=Boolean(r):"loop"===o&&e instanceof HTMLMediaElement?e.loop=Boolean(r):"muted"===o&&e instanceof HTMLMediaElement?e.muted=Boolean(r):"defer"===o&&e instanceof HTMLScriptElement?e.defer=Boolean(r):"async"===o&&e instanceof HTMLScriptElement?e.async=Boolean(r):s.call(e,String(o),r):e.hidden=Boolean(r):e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.required=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement?e.autofocus=Boolean(r):s.call(e,o,r):e instanceof HTMLSelectElement?e.multiple=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.readOnly=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLOptGroupElement||e instanceof HTMLOptionElement||e instanceof HTMLFieldSetElement||e instanceof HTMLTextAreaElement?e.disabled=Boolean(r):s.call(e,o,r):e instanceof HTMLOptionElement?e.defaultSelected=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement?e.defaultChecked=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?e.defaultValue=String(r):s.call(e,o,r):e instanceof HTMLOptionElement?e.selected=Boolean(r):s.call(e,o,r):e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value=String(r):s.call(e,o,r):e instanceof HTMLInputElement?e.checked=Boolean(r):s.call(e,o,r))}},B=()=>{throw new TypeError("[Kt.js:h] attr must be an object.")},b=(e,t)=>{e.ktext=t},x=(e,t)=>{const o=t.length;for(let i=0;i<o;i++){const o=t[i];"string"!=typeof o?p(o)?r.call(e,o):k():r.call(e,n(o))}},j=(e,t)=>{p(t)||k(),r.call(e,t)},k=()=>{throw new TypeError("[Kt.js:h] content must be a string, HTMLEnhancedElement or an array of HTMLEnhancedElement.")};function S(e,o="",i=""){if("string"!=typeof e)throw new TypeError("[Kt.js:h] tagName must be a string.");const s=(e=>y().add("string"==typeof e,w).add(h(e),g).nomatch(B))(o),l=(e=>y().add("string"==typeof e,b).add(h(e),j).add(a(e),x).nomatch(k))(i),c=(f=e,document.createElement(f));var f;const u=n("");return r.call(c,u),((e,t)=>{E.set(e,t)})(c,{id:t.nextKid(),text:u}),function(e){m(e,L),e.kon=M.kon,e.koff=M.koff,e.kmount=M.kmount}(c),l.run(c,i),s.run(c,o),c}function I(t,n=e){if(!p(t))throw new TypeError("Root element must be a KText element.");const o=(i="app",document.getElementById(i)??document.body);var i;if(u(n,e))r.call(o,t);else if(!h(n))throw new TypeError("mountTo must be an HTMLElement or omitted.")}export{I as createApp,S as h};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kt.js",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "author": {
5
5
  "name": "Kasukabe Tsumugi",
6
6
  "email": "futami16237@gmail.com"
@@ -65,6 +65,7 @@
65
65
  "vitest": "^3.2.4"
66
66
  },
67
67
  "dependencies": {
68
+ "bind-params": "^1.0.2",
68
69
  "defered-branch": "^1.2.2"
69
70
  }
70
71
  }