jqx-es 1.0.0
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/Bundle/jqx.browser.min.js +15 -0
- package/Bundle/jqx.min.js +15 -0
- package/LICENSE +674 -0
- package/README.md +59 -0
- package/build.js +17 -0
- package/index.js +99 -0
- package/lib/JQLBundle.js +15 -0
- package/package.json +27 -0
- package/src/DOM.js +77 -0
- package/src/DOMCleanup.js +89 -0
- package/src/EmbedResources.js +47 -0
- package/src/HTMLTags.js +18 -0
- package/src/HandlerFactory.js +31 -0
- package/src/JQxExtensionHelpers.js +276 -0
- package/src/JQxLog.js +144 -0
- package/src/JQxMethods.js +541 -0
- package/src/Popup.js +89 -0
- package/src/SyncedExternals.js +464 -0
- package/src/Utilities.js +126 -0
- package/src/tinyDOM.js +104 -0
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://bundlephobia.com/package/jqlmodule" rel="nofollow">
|
|
3
|
+
<a href="https://bundlephobia.com/package/jqlmodule@latest" rel="nofollow">
|
|
4
|
+
<img src="https://badgen.net/bundlephobia/min/jqlmodule"></a>
|
|
5
|
+
<a target="_blank" href="https://www.npmjs.com/package/jqlmodule">
|
|
6
|
+
<img src="https://img.shields.io/npm/v/jqlmodule.svg?labelColor=cb3837&logo=npm&color=dcfdd9"></a>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
## *Work in progress*: migrating (and renaming) from GitHUB JQL to Codeberg JQx
|
|
10
|
+
|
|
11
|
+
# JQx
|
|
12
|
+
|
|
13
|
+
<h3>JQuery - the good parts redone</h3>
|
|
14
|
+
|
|
15
|
+
This module was inspired by the idea that some JQuery was too good <a target="_blank" href="http://youmightnotneedjquery.com/" rel="nofollow">to ditch</a>.
|
|
16
|
+
|
|
17
|
+
It is developed in a modular fashion and uses plain ES20xx, so not really (or really not, take your pick) suitable for older browsers.
|
|
18
|
+
|
|
19
|
+
The module was rewritten in 2023 in a <i>classfree object oriented</i> fashion, inspired by a <a target="_blank" href="https://youtu.be/XFTOG895C7c?t=2562">Douglas Crockford presentation</a>.
|
|
20
|
+
|
|
21
|
+
The objective is to ***not*** use `prototype` and `this` in the code.
|
|
22
|
+
|
|
23
|
+
## Install/Import/Initialize
|
|
24
|
+
|
|
25
|
+
### NPM
|
|
26
|
+
You can install this module using npm. To create a HTML tree (DOM Object) server side you need a library like [jsdom](https://github.com/jsdom/jsdom).
|
|
27
|
+
```
|
|
28
|
+
npm i jqlmodule
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
There are *two flavors* of this library. One for scripts with type `module` (or projects with `"type": "module"` in package.json) and one for the browser.
|
|
32
|
+
|
|
33
|
+
For each flavor, the script is (bundled and) minified. The location of the minified scripts is `https://kooiinc.codeberg.page/JQx/Bundle`
|
|
34
|
+
|
|
35
|
+
### ESM import
|
|
36
|
+
``` javascript
|
|
37
|
+
import $ from "https://kooiinc.codeberg.page/JQx/Bundle/jqx.min.js";
|
|
38
|
+
// or
|
|
39
|
+
const $ = ( await
|
|
40
|
+
import("https://kooiinc.codeberg.page/JQx/Bundle/jqx.min.js")
|
|
41
|
+
).default;
|
|
42
|
+
$.div(`Hello JQx!`).appendTo(document.body);
|
|
43
|
+
// ...
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Browser script
|
|
47
|
+
``` html
|
|
48
|
+
<script src="https://kooiinc.codeberg.page/JQx/Bundle/jqx.browser.min.js"></script>
|
|
49
|
+
<script>
|
|
50
|
+
const $ = JQx.default;
|
|
51
|
+
$.div(`Hello JQx!`).appendTo(document.body);
|
|
52
|
+
// ...
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
## Documentation
|
|
56
|
+
Documentation can be found @[https://kooiinc.codeberg.page/JQx/@main/Resource/Docs/](https://kooiinc.codeberg.page/JQx/@main/Resource/Docs/).
|
|
57
|
+
|
|
58
|
+
## Demo and test
|
|
59
|
+
A test and demo of this module can be found @[kooiinc.codeberg.page/@main/JQx/Resource/Demo](https://kooiinc.codeberg.page/JQx/@main/Resource/Demo/).
|
package/build.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import builder from 'esbuild';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
const log = console.log.bind(console);
|
|
4
|
+
const esContext = {
|
|
5
|
+
entryPoints: ['./index.js'],
|
|
6
|
+
bundle: true,
|
|
7
|
+
outfile: './Bundle/jql.min.js',
|
|
8
|
+
treeShaking: true,
|
|
9
|
+
sourcemap: false, // don't need it
|
|
10
|
+
minify: true,
|
|
11
|
+
format: 'esm',
|
|
12
|
+
target: ['esnext'],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const ctx = await builder.context(esContext);
|
|
16
|
+
await ctx.rebuild().then(r => ctx.dispose());
|
|
17
|
+
process.exit();
|
package/index.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
This code is classfree object oriented. No this. No prototype. No class.
|
|
3
|
+
Inspired by Douglas Crockford (see https://youtu.be/XFTOG895C7c?t=2562)
|
|
4
|
+
2025/05/31 overhaul ...
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
isHtmlString,
|
|
9
|
+
isArrayOfHtmlStrings,
|
|
10
|
+
isArrayOfHtmlElements,
|
|
11
|
+
inject2DOMTree,
|
|
12
|
+
ElemArray2HtmlString,
|
|
13
|
+
input2Collection,
|
|
14
|
+
setCollectionFromCssSelector,
|
|
15
|
+
truncateHtmlStr,
|
|
16
|
+
proxify,
|
|
17
|
+
addJQxStaticMethods,
|
|
18
|
+
createElementFromHtmlString,
|
|
19
|
+
insertPositions,
|
|
20
|
+
systemLog,
|
|
21
|
+
IS,
|
|
22
|
+
} from "./src/JQxExtensionHelpers.js";
|
|
23
|
+
|
|
24
|
+
export default addJQxStaticMethods(JQxFactory());
|
|
25
|
+
|
|
26
|
+
function JQxFactory() {
|
|
27
|
+
const logLineLength = 70;
|
|
28
|
+
|
|
29
|
+
return function JQx(input, root, position = insertPositions.BeforeEnd) {
|
|
30
|
+
if (input?.isJQx) { return input; }
|
|
31
|
+
const isVirtual = IS(root, HTMLBRElement);
|
|
32
|
+
root = (!isVirtual && root && root.isJQx ? root[0] : root) || document.body;
|
|
33
|
+
position = position && Object.values(insertPositions).find(pos => position === pos) ? position : undefined;
|
|
34
|
+
const isRawHtml = isHtmlString(input);
|
|
35
|
+
const isRawHtmlArray = !isRawHtml && isArrayOfHtmlStrings(input);
|
|
36
|
+
const shouldCreateElements = isRawHtmlArray || isRawHtml;
|
|
37
|
+
|
|
38
|
+
let instance = {
|
|
39
|
+
collection: input2Collection(input) ?? [],
|
|
40
|
+
isVirtual,
|
|
41
|
+
isJQx: true,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const isRawElemCollection = isArrayOfHtmlElements(instance.collection);
|
|
45
|
+
|
|
46
|
+
const logStr = `input => ${
|
|
47
|
+
isRawHtmlArray
|
|
48
|
+
? `"${truncateHtmlStr(input.join(`, `), logLineLength)}"`
|
|
49
|
+
: !shouldCreateElements && isRawElemCollection ? `element collection [${
|
|
50
|
+
truncateHtmlStr( instance.collection.map(el => `${
|
|
51
|
+
IS(el, Comment, Text) ? `Comment|Text @` : ``} ${
|
|
52
|
+
el?.outerHTML || el?.textContent}`).join(`, `), logLineLength)}]`
|
|
53
|
+
: `"${truncateHtmlStr(input, logLineLength)}"`}`;
|
|
54
|
+
|
|
55
|
+
if (instance.collection.length && isRawElemCollection) {
|
|
56
|
+
systemLog(logStr);
|
|
57
|
+
|
|
58
|
+
if (!isVirtual) {
|
|
59
|
+
instance.collection.forEach(el => {
|
|
60
|
+
if (!root.contains(el)) {
|
|
61
|
+
inject2DOMTree([el], root, position);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return proxify(instance);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (shouldCreateElements) {
|
|
70
|
+
[input].flat().forEach(htmlStringOrComment =>
|
|
71
|
+
instance.collection.push(createElementFromHtmlString(htmlStringOrComment)));
|
|
72
|
+
|
|
73
|
+
if (instance.collection.length > 0) {
|
|
74
|
+
const errors = instance.collection.filter( el => el?.dataset?.jqxcreationerror );
|
|
75
|
+
instance.collection = instance.collection.filter(el => !el?.dataset?.jqxcreationerror);
|
|
76
|
+
|
|
77
|
+
systemLog(`${logStr}`);
|
|
78
|
+
systemLog(`*Created ${instance.isVirtual ? `VIRTUAL ` : ``}[${
|
|
79
|
+
truncateHtmlStr(ElemArray2HtmlString(instance.collection) ||
|
|
80
|
+
"sanitized: no elements remaining", logLineLength)}]`);
|
|
81
|
+
|
|
82
|
+
if (errors.length) {
|
|
83
|
+
console.error(`JQx: illegal html, not rendered: "${
|
|
84
|
+
errors.reduce( (acc, el) => acc.concat(`${el.textContent}\n`), ``).trim()}"` );
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!instance.isVirtual) {
|
|
88
|
+
inject2DOMTree(instance.collection, root, position);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return proxify(instance);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const forLog = setCollectionFromCssSelector(input, root, instance);
|
|
96
|
+
systemLog(`input => ${forLog}`);
|
|
97
|
+
return proxify(instance);
|
|
98
|
+
}
|
|
99
|
+
}
|
package/lib/JQLBundle.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var Xt="url('data:image/svg+xml\\3butf8,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%20id%3D%22Layer_1%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%20128%20128%22%20style%3D%22enable-background%3Anew%200%200%20128%20128%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20x%3D%22-368%22%20y%3D%226%22%20style%3D%22display%3Anone%3Bfill%3A%23E0E0E0%3B%22%20width%3D%22866%22%20height%3D%221018%22%2F%3E%3Ccircle%20style%3D%22fill%3A%23FFFFFF%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2248%22%2F%3E%3Ccircle%20style%3D%22fill%3A%238CCFB9%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2239%22%2F%3E%3Ccircle%20style%3D%22fill%3Anone%3Bstroke%3A%23444B54%3Bstroke-width%3A6%3Bstroke-miterlimit%3A10%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2248%22%2F%3E%3Cpolyline%20style%3D%22fill%3Anone%3Bstroke%3A%23FFFFFF%3Bstroke-width%3A6%3Bstroke-linecap%3Around%3Bstroke-miterlimit%3A10%3B%22%20points%3D%2242%2C69%2055.55%2C81%20%20%2086%2C46%20%22%2F%3E%3C%2Fsvg%3E')",st=ee(),vt=re(),P=Kt(),q=te();function Kt(){return{html:Object.freeze("accept,action,align,alt,autocapitalize,autocomplete,autopictureinpicture,autoplay,background,bgcolor,border,capture,cellpadding,cellspacing,checked,cite,class,clear,contenteditable,color,cols,colspan,controls,controlslist,coords,crossorigin,datetime,decoding,default,dir,disabled,disablepictureinpicture,disableremoteplayback,download,draggable,enctype,enterkeyhint,face,for,headers,height,hidden,high,href,hreflang,id,inputmode,integrity,is,ismap,kind,label,lang,list,loading,loop,low,max,maxlength,media,method,min,minlength,multiple,muted,name,nonce,noshade,novalidate,nowrap,open,optimum,pattern,placeholder,playsinline,poster,preload,pubdate,radiogroup,readonly,rel,required,rev,reversed,role,rows,rowspan,spellcheck,scope,selected,shape,size,sizes,span,srclang,start,src,srcset,step,style,summary,tabindex,target,title,translate,type,usemap,valign,value,width,xmlns,slot".split(",")),svg:Object.freeze("accent-height,accumulate,additive,alignment-baseline,ascent,attributename,attributetype,azimuth,basefrequency,baseline-shift,begin,bias,by,class,clip,clippathunits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,cx,cy,d,dx,dy,diffuseconstant,direction,display,divisor,dur,edgemode,elevation,end,fill,fill-opacity,fill-rule,filter,filterunits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,fx,fy,g1,g2,glyph-name,glyphref,gradientunits,gradienttransform,height,href,id,image-rendering,in,in2,k,k1,k2,k3,k4,kerning,keypoints,keysplines,keytimes,lang,lengthadjust,letter-spacing,kernelmatrix,kernelunitlength,lighting-color,local,marker-end,marker-mid,marker-start,markerheight,markerunits,markerwidth,maskcontentunits,maskunits,max,mask,media,method,mode,min,name,numoctaves,offset,operator,opacity,order,orient,orientation,origin,overflow,paint-order,path,pathlength,patterncontentunits,patterntransform,patternunits,points,preservealpha,preserveaspectratio,primitiveunits,r,rx,ry,radius,refx,refy,repeatcount,repeatdur,restart,result,rotate,scale,seed,shape-rendering,specularconstant,specularexponent,spreadmethod,startoffset,stddeviation,stitchtiles,stop-color,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke,stroke-width,style,surfacescale,systemlanguage,tabindex,targetx,targety,transform,text-anchor,text-decoration,text-rendering,textlength,type,u1,u2,unicode,values,viewbox,visibility,version,vert-adv-y,vert-origin-x,vert-origin-y,width,word-spacing,wrap,writing-mode,xchannelselector,ychannelselector,x,x1,x2,xmlns,y,y1,y2,z,zoomandpan".split(","))}}function te(){return{a:!0,area:!0,audio:!1,br:!0,base:!0,body:!0,button:!0,canvas:!0,comment:!0,dl:!0,data:!0,datalist:!0,div:!0,em:!0,embed:!1,fieldset:!0,font:!0,footer:!0,form:!1,hr:!0,head:!0,header:!0,output:!0,iframe:!1,frameset:!1,img:!0,input:!0,li:!0,label:!0,legend:!0,link:!0,map:!0,mark:!0,menu:!0,media:!0,meta:!0,nav:!0,meter:!0,ol:!0,object:!1,optgroup:!0,option:!0,p:!0,param:!0,picture:!0,pre:!0,progress:!1,quote:!0,script:!1,select:!0,source:!0,span:!0,style:!0,caption:!0,td:!0,col:!0,table:!0,tr:!0,template:!1,textarea:!0,time:!0,title:!0,track:!0,details:!0,ul:!0,video:!0,del:!0,ins:!0,slot:!0,blockquote:!0,svg:!0,dialog:!0,summary:!0,main:!0,address:!0,colgroup:!0,tbody:!0,tfoot:!0,thead:!0,th:!0,dd:!0,dt:!0,figcaption:!0,figure:!0,i:!0,b:!0,code:!0,h1:!0,h2:!0,h3:!0,h4:!0,abbr:!0,bdo:!0,dfn:!0,kbd:!0,q:!0,rb:!0,rp:!0,rt:!0,ruby:!0,s:!0,strike:!0,samp:!0,small:!0,strong:!0,sup:!0,sub:!0,u:!0,var:!0,wbr:!0,nobr:!0,tt:!0,noscript:!0}}function ee(){return["#logBox{min-width:0px;max-width:0px;min-height:0px;max-height:0px;width:0;height:0;z-index:-1;border:none;padding:0px;overflow:hidden;transition:all 0.3s ease;margin-top:-100px;}","#logBox.visible{background-color:rgb(255, 255, 224);z-index:1;position:static;border:1px dotted rgb(153, 153, 153);max-width:50vw;min-width:30vw;min-height:10vh;max-height:90vh;overflow:auto;width:50vw;height:20vh;margin:1rem 0px;padding:0px 8px 19px;resize:both;}","#logBox.visible .legend{position:absolute;}","#logBox .legend{text-align:center;margin-top:-1em;width:inherit;max-width:inherit;}","#logBox .legend div{text-align:center;display:inline-block;max-width:inherit;height:1.2rem;background-color:rgb(119, 119, 119);padding:2px 10px;color:rgb(255, 255, 255);box-shadow:rgb(119 119 119) 2px 1px 10px;border-radius:4px;}","#logBox .legend div:before{content:'JQx Logging (chronological)';}","#logBox .legend.reversed div:before{content:'JQL Logging (reversed)';}","#logBox #jqx_logger{marginTop:0.7rem;lineHeight:1.4em;font-family:consolas,monospace;whiteSpace:pre-wrap;maxWidth:inherit;padding-left:100px;}","#logBox #jqx_logger div.entry{text-indent:-100px;whiteSpace:normal;}"]}function re(){return[".popupContainer{position:fixed;inset:-5000px;opacity:0;height:0;width:0;background:rgba(0,0,0,0.1);transition:opacity 0.6s ease-in-out 0s;}",".popupContainer.popup-active{opacity:1;inset:0;height:auto;width:auto;z-index:2147483646;}",".popupContainer .content{box-shadow:rgba(0,0,0,0.5) 2px 2px 8px;border-radius:3px;min-width:125px;max-width:40vw;max-height:40vh;padding:8px;overflow:auto;background:#FFF;z-index:inherit;opacity:1;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}",".popupContainer .content .popup-warn{position:relative;padding:3px 8px 0 8px;color:red;margin:6px -8px -4px -8px;text-align:center;display:none;}",".popupContainer .content.popup-warn-active .popup-warn{display:block;border-top:1px dashed rgb(0,0,0);}",`.closeHandleIcon{z-index:1;position:absolute;opacity:0;cursor:pointer;width:24px;height:24px;background:${Xt} no-repeat;}`,".closeHandleIcon.popup-active{opacity:1;z-index:2147483647;}","@media screen and (width < 1200px){.popupContainer .content{max-width:75vw;}}","@media screen and (width < 640px){.popupContainer .content{max-width:90vw;max-height:60vw;}}"]}var at=!1,ne={on:()=>at=!0,off:()=>at=!1},j={tagsRaw:q,allowUnknownHtmlTags:ne,isAllowed(t){if(at)return!0;let e=c(t,String)?t.toLowerCase():t?.nodeName.toLowerCase()||"none";return e==="#text"||!!q[e]},allowTag:t=>q[t.toLowerCase()]=!0,prohibitTag:t=>q[t.toLowerCase()]=!1};var ut=!1,U=!1,J=!0,dt=!1,oe=!0,Et,k=()=>b("#logBox"),wt="#jqx_logger",ie=t=>{st?.forEach(e=>t(e))},se=()=>{st&&ie(Et);let t=oe?"div":"pre",e=`<div id="logBox"><div class="legend"><div></div></div><${t} id="jqx_logger"></${t}></div>`;return mt(A(e),void 0,F.AfterBegin),b.node(wt)},Lt=t=>c(t,String)&&Object.assign(document.createElement("textarea"),{innerHTML:t}).textContent||t,H=(...t)=>{let e=t[0]==="fromStatic";if(t=e?t.slice(1):t,e&&!U)return t.forEach(n=>console.info(`${Q()} \u2714 ${Lt(n)}`));if(!U)return;!J&&!b.node("#logBox")&&(Et=b.createStyle("JQxLogCSS"),se());let r=n=>`${c(n,Object)?JSON.stringify(n,null,2):n}
|
|
2
|
+
`;t.forEach(n=>J?console.info(`${Q()} \u2714 ${Lt(n)}`):b.node("#jqx_logger").insertAdjacentHTML(dt?"afterbegin":"beforeend",`<div class="entry">${Q()} ${r(n.replace(/\n/g,"<br>"))}</div>`))},ct={on(){U=!0,H("Logging activated")},off(){U=!1,console.log("Logging deactivated")}},lt={on(){ut=!0},off(){ut=!1}},O=(...t)=>ut&&H(...t),C={get isConsole(){return J===!0},get isOn(){return U},isVisible:function(){return b("#jqx_logger").is("visible")},on(){return ct.on(),lt.on(),J||k()?.addClass("visible"),H("Debug logging started. Every call to [jqx instance] is logged"),C},off(){return k().isEmpty||(lt.off(),H("Debug logging stopped"),k()?.removeClass("visible")),ct.off(),C},toConsole:{on(){return J=!0,H("Started logging to console"),C},off(){return H("Stopped logging to console (except error messages)"),J=!1,C}},remove(){return ct.off(),lt.off(),k()?.remove(),console.clear(),console.log(`${Q()} logging completely disabled and all entries removed`),C},log:function(...t){return H(...t),C},hide(){return k()?.removeClass("visible"),C},show:()=>(k()?.addClass("visible"),C),get reversed(){return{on:()=>(dt=!0,H("Reverse logging set: now logging bottom to top (latest first)"),b("#logBox .legend").addClass("reversed"),C),off:()=>(dt=!1,b("#logBox .legend").removeClass("reversed"),H("Reverse logging reset: now logging chronological (latest last)"),C)}},clear(){return b(wt).text(""),console.clear(),H("Logging cleared"),C}};var ae=ce(),Ct={html:"innerHTML",text:"textContent",class:"className"},ft=ae;function ce(){let t={get(e,r){let n=String(r)?.toLowerCase();switch(!0){case n in e:return e[n];case ye(n):return $t(e,n,r);default:return $t(e,n,r,!0)}},enumerable:!1,configurable:!1};return new Proxy({},t)}function $t(t,e,r,n=!1){return Object.defineProperty(t,e,{get(){return n?o=>pe(r):he(e)}}),t[e]}function le(t,e,r){return e=e?.isJQL&&e.first()||e,pt({trial:n=>Ft(e)?t.insertAdjacentHTML("beforeend",e):t.append(e),whenError:n=>console.info(`${r} (for root ${t}) not created, reason
|
|
3
|
+
`,n)})}function ue(t,e,...r){let n=de(e,t);return r?.forEach(o=>le(n,o,t)),n}function de(t,e){switch(t=gt(e)?ge(t):t?.isJQL?t.first():t,!0){case c(t,String):return G(e,Ft(t,e)?{html:t}:{text:t});case c(t,Node):return fe(e,t);default:return G(e,t)}}function me(t){return delete t.data,Object.keys(t).length<1||Object.keys(t).forEach(e=>{let r=e.toLowerCase();r in Ct&&(t[Ct[r]]=t[e],delete t[e])}),t}function fe(t,e){let r=G(t);return r.append(e),r}function G(t,e={}){e=Tt(e,{});let r=Object.entries(e.data??{}),n=Object.assign(gt(t)?new Comment:document.createElement(t),me(e));return r.length&&r.forEach(([o,i])=>n.dataset[o]=String(i)),n}function Tt(t,e){return e?c(t,{isTypes:Object,notTypes:[Array,null,NaN,Proxy],defaultValue:e}):c(t,{isTypes:Object,notTypes:[Array,null,NaN,Proxy]})}function ge(t){return Tt(t)?t?.text??t?.textContent??"":String(t)}function pe(t){return G("b",{style:"color:red",text:`'${t}' is not a valid HTML-tag`})}function Ft(t,e){return!gt(e)&&c(t,String)&&/<.*>|&[#|0-9a-z]+[^;];/i.test(t)}function gt(t){return/comment/i.test(t)}function ye(t){return!c(G(t),HTMLUnknownElement)}function he(t){return(e,...r)=>ue(t,e,...r)}var{IS:c,maybe:pt,$Wrap:pr,xProxy:yr,isNothing:hr}=be();function be(){Symbol.proxy=Symbol.for("toa.proxy"),Symbol.is=Symbol.for("toa.is"),Symbol.type=Symbol.for("toa.type"),Symbol.isSymbol=Symbol.for("toa.isASymbol"),p();let t=T(),[e,r]=[g(),v()];return r.custom(),{IS:n,maybe:t,$Wrap:e,isNothing:w,xProxy:r};function n(a,...l){if(t({trial:h=>"isTypes"in(l?.[0]??{})})){let h=l[0];return"defaultValue"in h?x(a,h):"notTypes"in h?d(a,h):n(a,...[h.isTypes].flat())}let f=typeof a=="symbol"?Symbol.isSymbol:a;return l.length>1?y(f,...l):i(a,...l)}function o(a){return a?.[Symbol.proxy]??n(a)}function i(a,...l){let{noInput:f,noShouldbe:h,compareTo:$,inputCTOR:N,isNaN:rt,isInfinity:nt,shouldBeFirstElementIsNothing:ot}=S(a,...l);switch(l=l.length&&l[0],!0){case ot:return String(a)===String($);case(a?.[Symbol.proxy]&&h):return a[Symbol.proxy];case rt:return h?"NaN":t({trial:it=>String($)})===String(a);case nt:return h?"Infinity":t({trial:it=>String($)})===String(a);case f:return h?String(a):String($)===String(a);case N===Boolean:return l?N===l:"Boolean";default:return L(a,l,h,u(a,N))}}function u(a,l){return a===0?Number:a===""?String:a?l:{name:String(a)}}function S(a,...l){let f=l.length<1,h=!f&&l[0],$=!f&&w(l[0]),N=a==null,rt=!N&&Object.getPrototypeOf(a)?.constructor,nt=Number.isNaN(a)||t({trial:it=>String(a)==="NaN"}),ot=t({trial:it=>String(a)})==="Infinity";return{noInput:N,noShouldbe:f,compareTo:h,inputCTOR:rt,isNaN:nt,isInfinity:ot,shouldBeFirstElementIsNothing:$}}function L(a,l,f,h){switch(!0){case(!f&&l===a||a?.[Symbol.proxy]&&l===Proxy):return!0;case t({trial:$=>String(l)})==="NaN":return String(a)==="NaN";case(a?.[Symbol.toStringTag]&&n(l,String)):return String(l)===a[Symbol.toStringTag];default:return l?t({trial:$=>a instanceof l})||l===h||l===Object.getPrototypeOf(h)||`${l?.name}`===h?.name:a?.[Symbol.toStringTag]&&`[object ${a?.[Symbol.toStringTag]}]`||h?.name||String(h)}}function y(a,...l){return l.some(f=>n(a,f))}function w(a,l=!1){let f=a==null;return f=l?f||n(a,1/0)||n(a,NaN):f,f}function T(){let a=(l,f)=>l?.constructor===Function?l(f):void 0;return function({trial:l,whenError:f=()=>{}}={}){try{return a(l)}catch(h){return a(f,h)}}}function g(){return function(a){return Object.freeze({get value(){return a},get[Symbol.type](){return o(a)},get type(){return o(a)},[Symbol.is](...l){return n(a,...l)},is(...l){return n(a,...l)}})}}function x(a,{defaultValue:l,isTypes:f=[void 0],notTypes:h}={}){return f=f?.constructor!==Array?[f]:f,h=h&&h?.constructor!==Array?[h]:[],h.length<1?n(a,...f)?a:l:d(a,{isTypes:f,notTypes:h})?a:l}function d(a,{isTypes:l=[void 0],notTypes:f=[void 0]}={}){return l=l?.constructor!==Array?[l]:l,f=f?.constructor!==Array?[f]:f,n(a,...l)&&!n(a,...f)}function p(){Object.getOwnPropertyDescriptors(Object.prototype)[Symbol.is]||(Object.defineProperties(Object.prototype,{[Symbol.type]:{get(){return o(this)},enumerable:!1,configurable:!1},[Symbol.is]:{value:function(...a){return n(this,...a)},enumerable:!1,configurable:!1}}),Object.defineProperties(Object,{[Symbol.type]:{value(a){return o(a)},enumerable:!1,configurable:!1},[Symbol.is]:{value:function(a,...l){return n(a,...l)},enumerable:!1,configurable:!1}}))}function s(a){let l=String(Object.getPrototypeOf(a)?.constructor);return l.slice(l.indexOf("ion")+3,l.indexOf("(")).trim()}function m(a){let l=a.set;return a.set=(f,h,$)=>h===Symbol.proxy?f[h]=$:l(f,h,$),a}function v(){let a=Proxy;return{native(){Proxy=a},custom(){Proxy=new a(a,{construct(l,f){for(let $ of f)$.set&&($=m($));let h=new l(...f);return h[Symbol.proxy]=`Proxy (${s(f[0])})`,h}})}}}}function V({styleSheet:t,createWithId:e}={}){let{tryParseAtOrNestedRules:r,ruleExists:n,checkParams:o,sheet:i,removeRules:u,consider:S,currentSheetID:L}=xe({styleSheet:t,createWithId:e});function y(d,p){if(d&&p.removeProperties){Object.keys(p.removeProperties).forEach(s=>d.style.removeProperty(Ht(s)));return}Object.entries(p).forEach(([s,m])=>{s=Ht(s.trim()),m=m.trim();let v;if(/!important/.test(m)&&(m=m.slice(0,m.indexOf("!important")).trim(),v="important"),!CSS.supports(s,m))return console.error(`StylingFactory ${L} error: '${s}' with value '${m}' not supported (yet)`);At(()=>d.style.setProperty(s,m,v),`StylingFactory ${L} (setRule4Selector) failed`)})}function w(d,p,s=i){if(d=d?.trim?.(),!c(d,String)||!d.length||/[;,]$/g.test(d))return console.error(`StylingFactory ${L} (setRules): [${d||"[no selector given]"}] is not a valid selector`);if(p.removeRule)return u(d);let m=n(d,!0),v=m||s.cssRules[s.insertRule(`${d} {}`,s.cssRules.length||0)];return S(()=>y(v,p),d,m)}function T(d){let p=d.trim().split(/{/,2),s=p.shift().trim();if(!c(s,String)||!s?.trim()?.length)return console.error(`StylingFactory ${L} (doParse): no (valid) selector could be extracted from rule ${yt(d)}`);let m=$e(p.shift());return At(()=>w(s,m),`StylingFactory ${L} (setRules) failed`)}function g(d){let p=r(d);return p.done?p.existing:T(d)}function x(d,p){return d.trim().startsWith("@media")?g(Se(d,p)):w(d,p)}return function(d,p={}){return o(d,p)&&(Object.keys(p).length?x(d,p):g(d))}}function xe({styleSheet:t,createWithId:e}){let r="Note: The rule or some of its properties may not be supported by your browser (yet)",n=`for style#${e}`;t=e?o(e):t;function o(g){let x=document.querySelector(`#${g}`)?.sheet;if(x)return x;let d=Object.assign(document.createElement("style"),{id:g});return document.head.insertAdjacentElement("beforeend",d),d.sheet}function i(g){return console.error(`StylingFactory ${n} [rule: ${g}]
|
|
4
|
+
=> @charset, @namespace and @import are not supported here`),{done:!0}}function u(g,x){return[...t.rules].find(d=>x?Mt(d.selectorText||"",g):Ee`${Le(g)}${[..."gim"]}`.test(d.cssText))}function S(g){return/^@charset|@import|namespace/i.test(g.trim())?i(g):g.match(/}/g)?.length>1?{existing:w(g,1),done:!0}:{done:!1}}function L(g){let x=[...t.cssRules].reduce((p,s,m)=>Mt(s.selectorText||"",g)&&p.concat(m)||p,[]),d=x.length;return x.forEach(p=>t.deleteRule(p)),d>0?console.info(`\u2714 Removed ${d} instance${d>1?"s":""} of selector ${g} from ${n.slice(4)}`):console.info(`\u2714 Remove rule: selector ${g} does not exist in ${n.slice(4)}`)}function y(g,x){return g&&c(g,String)&&g.trim().length>0&&c(x,Object)||(console.error(`StylingFactory ${n} called with invalid parameters`),!1)}function w(g){g=g.trim();let x=g.slice(0,g.indexOf("{")).trim(),d=!!u(x);try{return t.insertRule(`${g}`,t.cssRules.length),d}catch(p){return console.error(`StylingFactory ${n} (tryParse) ${p.name} Error:
|
|
5
|
+
${p.message}
|
|
6
|
+
Rule: ${yt(g)}
|
|
7
|
+
${r}`),d}}function T(g,x,d){try{return g(),d}catch(p){return console.error(`StylingFactory ${n} (tryAddOrModify) ${p.name} Error:
|
|
8
|
+
${p.message}
|
|
9
|
+
Rule: ${yt(x)}
|
|
10
|
+
${r}`),d}}return{sheet:t,removeRules:L,tryParseAtOrNestedRules:S,ruleExists:u,checkParams:y,tryParse:w,consider:T,currentSheetID:n}}function Se(t,e){return`${t.trim()} ${Object.entries(e).map(([r,n])=>`${r}: { ${ve(n)}`)}`}function yt(t){let e=(t||"NO RULE").trim().slice(0,50).replace(/\n/g,"\\n").replace(/\s{2,}/g," ");return t.length>e.length?`${e.trim()}...truncated`:e}function ve(t){return Object.entries(t).map(([e,r])=>`${e}: ${r.trim()}`).join(`;
|
|
11
|
+
`)}function Le(t){return t.replace(/([*\[\]()-+{}.$?\\])/g,e=>`\\${e}`)}function Ee(t,...e){let r=e.length&&Array.isArray(e.slice(-1))?e.pop().join(""):"";return new RegExp((e.length&&t.raw.reduce((n,o,i)=>n.concat(e[i-1]||"").concat(o),"")||t.raw.join("")).split(`
|
|
12
|
+
`).map(n=>n.replace(/\s|\/\/.*$/g,"").trim().replace(/(@s!)/g," ")).join(""),r)}function Ht(t){return t.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`).replace(/[^--]^-|-$/,"")}function At(t,e){try{return t()}catch(r){console.error(`${e||"an error occured"}: ${r.message}`)}}function we(t){return t.replace(/\/\*.+?\*\//gm,"").replace(/[}{\r\n]/g,"").replace(/(data:.+?);/g,(e,r)=>`${r}\\3b`).split(";").map(e=>e.trim()).join(`;
|
|
13
|
+
`).replaceAll("\\3b",";").split(`
|
|
14
|
+
`)}function Ce(t){return t.reduce((e,r)=>{let[n,o]=[r.slice(0,r.indexOf(":")).trim(),r.slice(r.indexOf(":")+1).trim().replace(/;$|;.+(?=\/*).+\/$/,"")];return n&&o?{...e,[n]:o}:e},{})}function $e(t){return Ce(we(t))}function Mt(t,e){return t?.replace("::",":")===e?.replace("::",":")}var Te=[...Array(26)].map((t,e)=>String.fromCharCode(e+65)).concat([...Array(26)].map((t,e)=>String.fromCharCode(e+97))).concat([...Array(10)].map((t,e)=>`${e}`)),K=(t,e=2)=>`${t}`.padStart(e,"0"),Fe=(t,e=0)=>([t,e]=[Math.floor(t),Math.ceil(e)],Math.floor([...crypto.getRandomValues(new Uint32Array(1))].shift()/2**32*(t-e+1)+e)),He=t=>{let e=t.length;for(;e--;){let r=Fe(e);[t[e],t[r]]=[t[r],t[e]]}return t};var M=(t,e=120)=>`${t}`.trim().slice(0,e).replace(/>\s+</g,"><").replace(/</g,"<").replace(/\s{2,}/g," ").replace(/\n/g,"\\n")+(t.length>e?" …":"").trim(),I=t=>t.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`).replace(/^-|-$/,""),Ae=([t,...e])=>`${t.toUpperCase()}${e.join("")}`,Z=t=>c(t,String)?t.toLowerCase().split("-").map((e,r)=>r&&`${Ae(e)}`||e).join(""):t,R=()=>`_${He(Te).slice(0,8).join("")}`,tt=(t,e=120)=>M(t,e).replace(/</g,"<"),Q=()=>(t=>`[${K(t.getHours())}:${K(t.getMinutes())}:${K(t.getSeconds())}.${K(t.getMilliseconds(),3)}]`)(new Date);var B=t=>t.replace(/</g,"<");function jt(){let t=function(i){if(!i)return;let u=i.style,S=getComputedStyle(i),L=[u.visibility,S.visibility].includes("hidden"),y=[u.display,S.display].includes("none"),w=i.offsetTop<0||i.offsetLeft+i.offsetWidth<0||i.offsetLeft>document.body.offsetWidth,T=+S.opacity==0||+(u.opacity||1)==0;return!(w||T||y||L)},e="n/a",r=function(i){return i.parentNode?!!b.nodes(":is(:read-write)",i?.parentNode)?.find(u=>u===i):!1},n=function(i){return i.parentNode?!!b.nodes(":is(:modal)",i?.parentNode)?.find(u=>u===i):!1},o={notInDOM:!0,writable:e,modal:e,empty:!0,open:e,visible:e};return i=>{let u=i[0];return u?{get writable(){return r(u)},get modal(){return n(u)},get inDOM(){return!!u.parentNode},get open(){return u.open??!1},get visible(){return t(u)},get disabled(){return u.hasAttribute("readonly")||u.hasAttribute("disabled")},get empty(){return i.collection.length<1},get virtual(){return i.isVirtual}}:o}}var Me=!0,et={data:/data-[\-\w.\p{L}]/ui,validURL:/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,whiteSpace:/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g,notAllowedValues:/javascript|injected|noreferrer|alert|DataURL/gi},je=t=>{if(Me&&Object.keys(t.removed).length){let e=Object.entries(t.removed).reduce((r,[n,o])=>[...r,`${B(n)} => ${o}`],[]).join("\\000A");C.log(`JQL HTML creation errors: ${C.isConsole?e:B(e)}`)}},Oe=function(t){let e=t.nodeName.toLowerCase(),r=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"];return/-/.test(e)&&!r.find(n=>n===e)||j.isAllowed(e)},Y=t=>{let e={rawHTML:t?.parentElement?.getHTML()??"no html",removed:{}};return c(t,HTMLElement)&&[...t.childNodes].forEach(r=>{if(r?.children?.length&&Y(r),r?.attributes){let o=c(r,SVGElement)?P.svg:P.html;[...(r??{attributes:[]}).attributes].forEach(i=>{let u=i.name.trim().toLowerCase(),S=i.value.trim().toLowerCase().replace(et.whiteSpace,""),L=u==="href"?!et.validURL.test(S):et.notAllowedValues.test(S),y=u.startsWith("data")?!et.data.test(u):!!o[u];if(L||y){let w=tt(i.value||"none",60);w+=w.length===60?"...":"",e.removed[`${i.name}`]=`attribute/property (-value) not allowed, removed. Value: ${w}`,r.removeAttribute(i.name)}})}if(!Oe(r)){let o=(r?.outerHTML||r?.textContent).trim(),i=tt(o,60)??"EMPTY";i+=i.length===60?"...":"",e.removed[`<${r.nodeName?.toLowerCase()}>`]=`not allowed, not rendered. Value: ${i}`,r.remove()}}),je(e),t};var F=new Proxy({start:"afterbegin",afterbegin:"afterbegin",end:"beforeend",beforeend:"beforeend",before:"beforebegin",beforebegin:"beforebegin",after:"afterend",afterend:"afterend"},{get(t,e){return t[String(e).toLowerCase()]??t[e]}}),Re=t=>{let e=document.createElement("div");return e.insertAdjacentHTML(F.end,t),e.childNodes.length?Y(e):void 0},Ie=(t,e,r)=>c(t,Comment)?e.insertAdjacentHTML(r,`<!--${t.data}-->`):e.insertAdjacentText(r,t.data),z=(t=[],e=document.body,r=F.BeforeEnd)=>t.reduce((n,o)=>{let i=X(o)&&mt(o,e,r);return i?[...n,i]:n},[]),mt=(t,e=document.body,r=F.BeforeEnd)=>(e=e?.isJQL?e?.[0]:e,c(t,Comment,Text)?Ie(t,e,r):e.insertAdjacentElement(r,t)),A=t=>{if(c(t,Text,Comment))return t;let e=t?.trim(),r=e?.split(/<text>|<\/text>/i)??[];if(r?.length&&(r=r.length>1?r.filter(o=>o.length).shift():void 0),e.startsWith("<!--")&&e.endsWith("-->"))return document.createComment(t.replace(/<!--|-->$/g,""));if(r||!/^<(.+)[^>]+>/m.test(e))return document.createTextNode(r);let n=Re(t);return n.childNodes.length<1?A(`<span data-jqlcreationerror="1">${M(t,60)}</span>`):n.children[0]};var E=(t,e)=>{let r=t.collection.filter(n=>!Pt(n));for(let n=0;n<r.length;n+=1)e(r[n],n);return t},De=jt(),Ot=t=>t&&(t.textContent="");var _=t=>{let e=t.cloneNode(!0);return e.removeAttribute&&e.removeAttribute("id"),t.isConnected?t.remove():t=null,e},Dt=(t,e)=>{t&&c(e,Object)&&Object.entries(e).forEach(([r,n])=>t.setAttribute(`data-${I(r)}`,n))},Rt=(t,e)=>t.andThen(e,!0),It=(t,e)=>t.andThen(e),Nt=t=>t.startsWith("data")||P.html.find(e=>t.toLowerCase()===e),Ne=(t,e,r)=>{r&&c(e,String)&&(e={[e]:r==="-"?"":r});let n;e.className&&(n=e.className,delete e.className),n=[...t.classList].find(i=>i.startsWith("JQLClass-")||n&&i===n)||n||`JQLClass-${R().slice(1)}`,b.editCssRule(`.${n}`,e),t.classList.add(n)},Pe=(t,e)=>{t&&Object.entries(e).forEach(([r,n])=>{if(r.toLowerCase().startsWith("data"))return Dt(t,n);c(n,String)&&Nt(r)&&t.setAttribute(r,n.split(/[, ]/)?.join(" "))})},ht=(t,e)=>{c(e,Object)&&Object.entries(e).forEach(([r,n])=>{let o;/!important/i.test(n)&&(n=n.slice(0,n.indexOf("!")).trim(),o="important"),t.style.setProperty(I(r),n,o)})},ke={get(t,e){return t[Z(e)]||t[e]}},Je=(...t)=>{C.log("\u2757"+t.map(e=>String(e)).join(", "))},Qe={factoryExtensions:{is:t=>De(t),length:t=>t.collection.length,dimensions:t=>t.first()?.getBoundingClientRect(),parent:t=>{let e=b(t[0]?.parentNode);return e.is.empty?t:e},outerHtml:t=>(t.first()||{outerHTML:void 0}).outerHTML,data:t=>({get all(){return new Proxy(t[0]?.dataset??{},ke)},set:(e={})=>(!t.is.empty&&c(e,Object)&&Object.entries(e).forEach(([r,n])=>t.setData({[r]:n})),t),get:(e,r)=>t.data.all[e]??r,add:(e={})=>(!t.is.empty&&c(e,Object)&&Object.entries(e).forEach(([r,n])=>t.setData({[r]:n})),t),remove:e=>(t[0]?.removeAttribute(`data-${I(e)}`),t)}),Style:t=>({get computed(){return t.is.empty?{}:getComputedStyle(t[0])},inline:e=>t.style(e),inSheet:e=>t.css(e),valueOf:e=>t.is.empty?void 0:getComputedStyle(t[0])[I(e)],nwRule:e=>t.Style.byRule({rules:e}),byRule:({classes2Apply:e=[],rules:r=[]}={})=>{let o=c(r,String)&&!e.length?r.split("{")[0].trim():"";return r=r&&c(r,String)?[r]:r,e=e&&c(e,String)?[e]:e,(r?.length||e?.length)&&(r?.length&&b.editCssRules(...r),e?.forEach(i=>t.addClass(i))),o?.startsWith(".")&&t.addClass(o.slice(1)),o?.startsWith("#")&&!t.attr("id")&&t.prop({id:o.slice(1)}),t}}),HTML:t=>({get:(e,r)=>{if(t.is.empty)return"NO ELEMENTS IN COLLECTION";let n=e?t.outerHtml:t.html();return r?B(n):n},set:(e,r=!1,n=!1)=>{e=e.isJQL?e.HTML.get(1):e;let o=c(e,String);return e=o&&n?B(e):e,o&&(e||"").trim().length&&t.html(e,r),t},replace:(e,r=!1)=>t.HTML.set(e,!1,r),append:(e,r=!1)=>(e=c(e,HTMLElement)?e[Symbol.jqlvirtual].HTML.get(1):e.isJQL?e.HTML.get(1):e,t.HTML.set(e,!0,r)),insert:(e,r=!1)=>(e=c(e,HTMLElement)?e[Symbol.jqlvirtual].HTML.get(1):e.isJQL?e.HTML.get(1):e,t.HTML.set(e+t.HTML.get(),!1,r))}),render:t=>!t.is.empty&&t.toDOM()||(b.log("[JQL.render]: empty collection"),void 0)},instanceExtensions:{isEmpty:t=>t.collection.length<1,renderTo:(t,e=document.body,r=b.insertPositions.end)=>(t.toDOM(e,r),t),replaceClass:(t,e,...r)=>E(t,n=>{n.classList.remove(e),r.forEach(o=>n.classList.add(o))}),removeClass:(t,...e)=>E(t,r=>r&&e.forEach(n=>r.classList.remove(n))),addClass:(t,...e)=>E(t,r=>r&&e.forEach(n=>r.classList.add(n))),setData:(t,e)=>E(t,r=>Dt(r,e)),show:t=>E(t,e=>ht(e,{display:"revert-layer !important"})),hide:t=>E(t,e=>ht(e,{display:"none !important"})),empty:t=>E(t,Ot),clear:t=>E(t,Ot),closest:(t,e)=>{let r=c(e,String)?t[0].closest(e):null;return r?b(r):t},style:(t,e,r)=>E(t,o=>{r&&c(e,String)&&(e={[e]:r||"none"}),ht(o,e)}),toggleClass:(t,e)=>E(t,r=>r.classList.toggle(e)),css:(t,e,r)=>E(t,n=>Ne(n,e,r)),text:(t,e,r=!1)=>t.isEmpty()?t:c(e,String)?E(t,o=>o.textContent=r?o.textContent+e:e):t.first().textContent,removeAttribute:(t,e)=>E(t,r=>r.removeAttribute(e)),each:(t,e)=>E(t,e),remove:(t,e)=>{O(`remove ${M(t.HTML.get(1),40)}${e?` /w selector ${e}`:""}`);let r=o=>o.remove(),n=()=>t.collection=t.collection.filter(o=>document.documentElement.contains(o));if(e){let o=t.find$(e);return o.is.empty||(E(o,r),n()),t}return E(t,r),n(),t},computedStyle:(t,e)=>t.first()&&getComputedStyle(t.first())[e],getData:(t,e,r)=>t.first()&&t.first().dataset?.[e]||r,hasClass:(t,...e)=>{let r=t[0];return!r||!r.classList.length?!1:e.find(n=>r.classList.contains(n))&&!0||!1},replace:(t,e,r)=>{let n=t[0];return!e||!r||!c(r,HTMLElement)&&!r.isJQL?(console.error("JQL replace: invalid replacement value"),t):(r.isJQL&&(r=r[0]),c(r,NodeList)&&(r=r[0]),n&&e&&(e=c(e,String)?n.querySelectorAll(e):e.isJQL?e.collection:e,c(e,HTMLElement,NodeList,Array)&&c(r,HTMLElement)&&(c(e,HTMLElement)?[e]:[...e]).forEach(o=>o.replaceWith(r.cloneNode(!0)))),t)},replaceWith:(t,e)=>(e=c(e,Element)?e:e.isJQL?e[0]:void 0,e&&(t[0].replaceWith(e),t=b.virtual(e)),t),replaceMe:(t,e)=>t.replaceWith(e),val:(t,e)=>{let r=t[0];return!r||!c(r,HTMLInputElement,HTMLSelectElement,HTMLTextAreaElement)?t:e===void 0?r.value:(r.value=c(e,String)?e:"",t)},attr:(t,e,r)=>{let n=t[0];return n?!r&&c(e,String)?e==="class"?[...n?.classList].join(" "):n?.getAttribute(e):(c(e,String)&&r&&(e={[e]:r}),c(e,Object)&&!t.is.empty&&Pe(n,e),t):t},andThen:(t,e,r=!1)=>{if(!e||!c(e,String,Node,Proxy))return Je(`[JQL instance].[beforeMe | afterMe | andThen]: insufficient input [${e}]`),t;e=e?.isJQL?e.collection:c(e,Node)?b.virtual(e).collection:b.virtual(A(e)).collection;let[n,o,i]=r?[0,"before",e.concat(t.collection)]:[t.collection.length-1,"after",t.collection.concat(e)];return t[n][o](...e),t.collection=i,t},after:It,afterMe:It,before:Rt,beforeMe:Rt,append:(t,...e)=>{if(!t.is.empty&&e.length){let r=t.length===1;for(let n of e){if(!n.isJQL&&c(n,String)){let o=n.trim(),u=!/^<(.+)[^>]+>$/m.test(o)?b.text(n):A(n);E(t,S=>S.append(r?u:_(u)))}X(n)&&E(t,o=>o.append(r?n:_(n))),n.isJQL&&!n.is.empty&&E(t,o=>n.collection.forEach(i=>o.append(r?i:_(i))))}}return t},prepend:(t,...e)=>{if(!t.is.empty&&e){let r=t.length===1;for(let n of e){if(c(n,String)){n=n.trim();let i=!/^<(.+)[^>]+>$/m.test(n)?b.text(n):A(n);i=r?i:_(i),E(t,u=>u.prepend(i.cloneNode(!0)))}X(n)&&E(t,o=>o.prepend(r?n:_(n))),n.isJQL&&!n.is.empty&&(n.collection.length>1&&n.collection.reverse(),E(t,o=>E(n,i=>o.prepend(r?i:_(i)))),n.collection.reverse())}}return t},appendTo:(t,e)=>(e.isJQL||(e=b(e)),e.append(t),t),prependTo:(t,e)=>(e.isJQL||(e=b.virtual(e)),e.prepend(t),t),single:(t,e)=>t.collection.length>0?c(e,String)?t.find$(e):c(e,Number)?b(t.collection[e]):b(t.collection[0]):t,toNodeList:t=>[...t.collection].map(e=>document.importNode(e,!0)),duplicate:(t,e=!1,r=document.body)=>{let n=t.toNodeList().map(i=>i.removeAttribute&&i.removeAttribute("id")||i),o=b.virtual(n);return e?o.toDOM(r):o},toDOM:(t,e=document.body,r=F.BeforeEnd)=>(t.isVirtual&&(t.isVirtual=!1),t.collection=z(t.collection,e,r),t),first:(t,e=!1)=>{if(t.collection.length>0)return e?t.single():t.collection[0]},first$:(t,e)=>t.single(e),nth$:(t,e)=>t.single(e),find:(t,e)=>t.collection.length>0?[...t.first()?.querySelectorAll(e)]:[],find$:(t,e)=>t.collection.length>0?b(e,t):t,prop:(t,e,r)=>{if(c(e,String)&&!r)return e.startsWith("data")?t[0]?.dataset[e.slice(e.indexOf("-")+1)]:t[0]?.[e];let n=c(e,Object)?e:{[e]:r};return Object.entries(n).forEach(([o,i])=>{if(o=o.trim(),i&&!Nt(o)||!i)return!1;if(o.toLowerCase()==="id")return t[0].id=i;E(t,S=>{if(o.startsWith("data"))return S.dataset[o.slice(o.indexOf("-")+1)]=i;S[o]=i})}),t},on:(t,e,...r)=>(t.collection.length&&r?.forEach(n=>{let o=kt(t);b.delegate(e,o,n)}),t),html:(t,e,r)=>{if(e===void 0)return t[0]?.getHTML();if(!t.isEmpty()){let n=A(`<div>${e.isJQL?e.HTML.get(!0):e}</div>`);if(!c(n,Comment))return E(t,i=>(r||(i.textContent=""),i.insertAdjacentHTML(b.at.end,n.getHTML())))}return t},htmlFor:(t,e,r="",n=!1)=>{if(e&&t.collection.length){if(!e||!c(r,String))return t;let o=t.find$(e);if(o.length<1)return t;let i=A(`<span>${r}</span>`);o.each(u=>{n||(u.textContent=""),u.insertAdjacentHTML(b.at.end,i.getHTML())})}return t},trigger:(t,e,r=Event,n={})=>{if(t.collection.length){let o=new r(e,{...n,bubbles:n.bubbles??!0});for(let i of t.collection)i.dispatchEvent(o)}return t}}},bt=Qe;var Jt=Be;function Be(t){let e=t.createStyle("JQLPopupCSS");vt.forEach(s=>e(s));let r={},n,o,i,u=t.virtual('<div class="popup-warn">'),S=t('<div class="popupContainer">').append(t('<span class="closeHandleIcon">')).append(t('<div class="content">')),[L,y]=[t(".popupContainer > .closeHandleIcon"),t(".popupContainer > .content")],w=()=>{if(L.hasClass("popup-active")){let{x:s,y:m,width:v}=y.dimensions;L.style({top:`${m-12}px`,left:`${s+v-12}px`})}},T=()=>{o&&t(".popup-warn").clear().append(t(`<div>${o}</div>`)),y.addClass("popup-warn-active")},g=()=>{n=!1,p(L.first())},x=(s,m)=>i=setTimeout(()=>p(L[0]),+s*1e3);return t.delegate("click",".popupContainer, .closeHandleIcon",s=>p(s.target)),t.delegate("click",".popupContainer .content",(s,m)=>n&&m.removeClass("popup-warn-active")),t.delegate("resize",w),{show:d,create:(s,m,v,a)=>{let l=t.IS(m,Boolean)?m:!1;d({content:s,modal:l,callback:l?v:m,warnMessage:a})},createTimed:(s,m,v)=>d({content:s,closeAfter:m,callback:v}),removeModal:g};function d({content:s,modal:m,closeAfter:v,callback:a,warnMessage:l}){if(s){if(s=t.IS(s,Node)?s[Symbol.jqlvirtual]:s,clearTimeout(i),n=m??!1,o=t.IS(l,String)&&`${l?.trim()}`.length||l?.isJQL?l:void 0,y.clear().append(s.isJQL?s:t(`<div>${s}</div>`)),n&&l&&y.append(u.duplicate()),S.addClass("popup-active"),t.IS(a,Function)){let f=R();S.data.set({callbackId:f}),r[f]=a}if(!n){if(t.IS(+v,Number)){let f=S.data.get("callbackId"),h=f&&r[f];x(v,h)}L.addClass("popup-active"),w()}return!0}return console.error("Popup creation needs at least some text to show")}function p(s){if(!n&&!s.closest(".content")){clearTimeout(i),y.clear();let m=S.data.get("callbackId");S.data.remove("callbackId"),t(".popup-active").removeClass("popup-active");let v=m&&r[m];t.IS(v,Function)&&v(),m&&delete r[m],o="";return}return n&&T()}}var D={},ze=["load","unload","scroll","focus","blur","DOMNodeRemovedFromDocument","DOMNodeInsertedIntoDocument","loadstart","progress","error","abort","load","loadend","pointerenter","pointerleave","readystatechange"],_e=t=>!!ze.find(e=>e===t),Qt=()=>{let t=n=>D[n.type].forEach(o=>o(n)),e=(n,o)=>i=>{let u=i.target?.closest?.(n);return u&&o(i,b(u))},r=(n,o)=>{D[n]||addEventListener(n,t,_e(n))};return(n,o,i,u=!1)=>{r(n,u);let S=o?e(o,i):i;D=D[n]?{...D,[n]:D[n].concat(S)}:{...D,[n]:[S]}}};var We={},{instanceMethods:Bt,instanceGetters:zt,isCommentOrTextNode:Pt,isNode:X,isHtmlString:Wt,isArrayOfHtmlElements:qt,isArrayOfHtmlStrings:Ut,ElemArray2HtmlString:Gt,input2Collection:Vt,setCollectionFromCssSelector:Zt,addHandlerId:kt,cssRuleEdit:xt,addFn:qe,elems4Docs:tn}=Ue();function Ue(){let t=V({createWithId:"JQxStylesheet"}),e=(s,m)=>r[s]=(v,...a)=>m(v,...a),r=bt.instanceExtensions,n=bt.factoryExtensions,o=s=>c(s,Comment,Text),i=s=>c(s,Text,HTMLElement,Comment),u=s=>c(s,Comment),S=s=>c(s,Text),L=s=>c(s,String)&&/^<|>$/.test(`${s}`.trim()),y=s=>c(s,Array)&&!s?.find(m=>!L(m)),w=s=>c(s,Array)&&!s?.find(m=>!i(m)),T=s=>s?.filter(m=>m).reduce((m,v)=>m.concat(u(v)?`<!--${v.data}-->`:o(v)?v.textContent:v.outerHTML),""),g=s=>s?c(s,Proxy)?[s.EL]:c(s,NodeList)?[...s]:i(s)?[s]:w(s)?s:s.isJQx?s.collection:void 0:[],x=(s,m,v)=>{let a=m!==document.body&&c(s,String)&&s.toLowerCase()!=="body"?m:document,l;try{v.collection=[...a.querySelectorAll(s)]}catch{l=`Invalid CSS querySelector. [${c(s,String)?s:"Nothing valid given!"}]`}return l??`CSS querySelector "${s}", output ${v.collection.length} element(s)`},d=s=>{let m=s.data.get("hid")||`HID${R()}`;return s.data.add({hid:m}),`[data-hid="${m}"]`},p=Object.entries(j.tagsRaw).filter(([,s])=>s).map(([s])=>s).sort((s,m)=>s.localeCompare(m));return{instanceMethods:r,instanceGetters:n,isCommentOrTextNode:o,isNode:i,isComment:u,isText:S,isHtmlString:L,isArrayOfHtmlElements:w,isArrayOfHtmlStrings:y,ElemArray2HtmlString:T,input2Collection:g,setCollectionFromCssSelector:x,addHandlerId:d,cssRuleEdit:t,addFn:e,elems4Docs:p}}function W(t){let e=i=>(...u)=>c(i,Function)&&i(W(t),...u),r=i=>(...u)=>c(i,Function)?{tmpKey:i(W(t),...u)}:{tmpKey:void 0},n=(i,u)=>c(u,Symbol)?()=>i:c(+u,Number)?i.collection?.[u]:u in zt?r(zt[u])().tmpKey:u in Bt?e(Bt[u]):i[u],o={get:(i,u)=>n(i,u)};return new Proxy(t,o)}function Yt(t){Object.defineProperties(Node.prototype,{[Symbol.$]:{get(){return t(this)},enumerable:!1,configurable:!1}});let e=tr(t);return Object.entries(Object.getOwnPropertyDescriptors(e)).forEach(([r,n])=>{Object.defineProperty(t,r,n),Object.defineProperty(We,r,n)}),t}function Ge(t){return{allow:e=>{let r=/-/.test(e),n=r&&e;e=r?Z(e):e.toLowerCase(),j.allowTag(e),c(t[e],Function)||Object.defineProperties(t,St(e,!0,t,n))},prohibit:e=>{e=e.toLowerCase(),j.prohibitTag(e),c(t[e],Function)&&Object.defineProperties(t,St(e,!1,t))}}}function _t(...t){if(t.length===1){let e=String(t.shift().trim());t=e.startsWith("!")?[e.slice(1,-1)]:e.split(",").map(r=>r.trim())}t.map(e=>e.startsWith("!")?e.slice(1,-1):e).forEach(e=>xt(e,{removeRule:1}))}function Ve(t){return function(e,r,...n){return c(r,Function)&&(n.push(r),r=void 0),n.forEach(o=>t(e,r,o))}}function Ze(t){return function(e,r,n){r=r?.isJQx?r?.[0]:r,n=n&&Object.values(F).find(i=>n===i)?n:void 0;let o=t(e,document.createElement("br"));return r&&!c(r,HTMLBRElement)&&o.collection.forEach(i=>n?r.insertAdjacentElement(n,i):r.append(i)),o}}function Ye(...t){let e={};for(let r of t){let n=Object.getOwnPropertyDescriptors(r);Object.entries(n).forEach(([o,i])=>!(o in e)&&Object.defineProperty(e,o,i))}return e}function Xe(t){console.error(`JQx: "${t}" not allowed, not rendered`)}function Ke(t,e,r,n){return t=I(n||t.toLowerCase()),{get(){return(...o)=>e?r.virtual(Y(ft[t](...o))):Xe(t)},enumerable:!1,configurable:!0}}function St(t,e,r,n){t=t.toLowerCase();let o=Ke(t,e,r,n);return n?{[n]:o,[Z(n)]:o}:{[t]:o,[t.toUpperCase()]:o}}function tr(t){return Ye(Object.entries(j.tagsRaw).reduce(er(t),{}),rr(t))}function er(t){return function(e,[r,n]){return n&&Object.defineProperties(e,St(r,n,t)),e}}function rr(t){let e=(n,o)=>xt(n,o),r=Ge(t);return{debugLog:C,log:(...n)=>H("fromStatic",...n),insertPositions:F,get at(){return F},editCssRules:(...n)=>n.forEach(o=>xt(o)),editCssRule:e,get setStyle(){return e},delegate:Ve(Qt()),virtual:Ze(t),get fn(){return qe},allowTag:r.allow,prohibitTag:r.prohibit,get lenient(){return j.allowUnknownHtmlTags},get IS(){return c},get Popup(){return t.activePopup||Object.defineProperty(t,"activePopup",{value:Jt(t),enumerable:!1}),t.activePopup},popup:()=>t.Popup,createStyle:n=>V({createWithId:n||`jqx${R()}`}),editStylesheet:n=>V({createWithId:n||`jqx${R()}`}),removeCssRule:_t,removeCssRules:_t,text:(n,o=!1)=>o?t.comment(n):document.createTextNode(n),node:(n,o=document)=>o.querySelector(n,o),nodes:(n,o=document)=>[...o.querySelectorAll(n,o)]}}var b=Yt(nr());function nr(){return function(r,n,o=F.BeforeEnd){let i=c(n,HTMLBRElement);n=(!i&&n&&n.isJQL?n[0]:n)||document.body,o=o&&Object.values(F).find(x=>o===x)?o:void 0;let u=Wt(r),S=!u&&Ut(r),L=S||u,y={collection:Vt(r)??[],isVirtual:i,isJQL:!0,isJQx:!0},w=qt(y.collection);location.host.startsWith("dev")&&(y.params={virtual:y.isVirtual,jql:y.isJQL,isRawHtml:u,isRawHtmlArray:S,isRawElemCollection:w});let T=`input => ${S?`"${M(r.join(", "),70)}"`:!L&&w?`element collection [${M(y.collection.map(x=>`${c(x,Comment,Text)?"Comment|Text @":""} ${x?.outerHTML||x?.textContent}`).join(", "),70)}]`:`"${M(r,70)}"`}`;if(y.collection.length&&w)return O(T),i||y.collection.forEach(x=>{n.contains(x)||z([x],n,o)}),W(y);if(L){if([r].flat().forEach(x=>y.collection.push(A(x))),y.collection.length>0){let x=y.collection.filter(d=>d?.dataset?.jqlcreationerror);y.collection=y.collection.filter(d=>!d?.dataset?.jqlcreationerror),O(`${T}`),O(`*Created ${y.isVirtual?"VIRTUAL ":""}[${M(Gt(y.collection)||"sanitized: no elements remaining",70)}]`),x.length&&console.error(`JQL: illegal html, not rendered: "${x.reduce((d,p)=>d.concat(`${p.textContent}
|
|
15
|
+
`),"").trim()}"`),y.isVirtual||z(y.collection,n,o)}return W(y)}let g=Zt(r,n,y);return O(`input => ${g}`),W(y)}}export{b as default};
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jqx-es",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "A JQuery alike es20xx module",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"jquery-subset",
|
|
9
|
+
"es20xx",
|
|
10
|
+
"classfree",
|
|
11
|
+
"js"
|
|
12
|
+
],
|
|
13
|
+
"author": "KooiInc",
|
|
14
|
+
"license": "GNU General Public License v3.0",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://codeberg.org/KooiInc/JQx"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://codeberg.org/KooiInc/JQx/issues"
|
|
21
|
+
},
|
|
22
|
+
"sideEffects": false,
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "node build"
|
|
25
|
+
},
|
|
26
|
+
"main": "./index.js"
|
|
27
|
+
}
|
package/src/DOM.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cleanupHtml,
|
|
3
|
+
getRestricted,
|
|
4
|
+
ATTRS, } from "./DOMCleanup.js";
|
|
5
|
+
import {truncateHtmlStr, IS, isNode} from "./JQxExtensionHelpers.js";
|
|
6
|
+
const insertPositions = new Proxy({
|
|
7
|
+
start: "afterbegin", afterbegin: "afterbegin",
|
|
8
|
+
end: "beforeend", beforeend: "beforeend",
|
|
9
|
+
before: "beforebegin", beforebegin: "beforebegin",
|
|
10
|
+
after: "afterend", afterend: "afterend" }, {
|
|
11
|
+
get(obj, key) { return obj[String(key).toLowerCase()] ?? obj[key]; }
|
|
12
|
+
});
|
|
13
|
+
const htmlToVirtualElement = htmlString => {
|
|
14
|
+
const placeholderNode = document.createElement("div");
|
|
15
|
+
placeholderNode.insertAdjacentHTML(insertPositions.end, htmlString);
|
|
16
|
+
return placeholderNode.childNodes.length
|
|
17
|
+
? cleanupHtml(placeholderNode)
|
|
18
|
+
: undefined;
|
|
19
|
+
};
|
|
20
|
+
const characterDataElement2DOM = (elem, root, position) => {
|
|
21
|
+
if (IS(elem, Comment)) {
|
|
22
|
+
return root.insertAdjacentHTML(position, `<!--${elem.data}-->`);
|
|
23
|
+
}
|
|
24
|
+
return root.insertAdjacentText(position, elem.data);
|
|
25
|
+
};
|
|
26
|
+
const inject2DOMTree = (
|
|
27
|
+
collection = [],
|
|
28
|
+
root = document.body,
|
|
29
|
+
position = insertPositions.BeforeEnd ) =>
|
|
30
|
+
collection.reduce( (acc, elem) => {
|
|
31
|
+
const created = isNode(elem) && element2DOM(elem, root, position);
|
|
32
|
+
return created ? [...acc, created] : acc;
|
|
33
|
+
}, []);
|
|
34
|
+
const element2DOM = (elem, root = document.body, position = insertPositions.BeforeEnd) => {
|
|
35
|
+
root = root?.isJQx ? root?.[0] : root;
|
|
36
|
+
|
|
37
|
+
return IS(elem, Comment, Text) ?
|
|
38
|
+
characterDataElement2DOM(elem, root, position) : root.insertAdjacentElement(position, elem);
|
|
39
|
+
};
|
|
40
|
+
const createElementFromHtmlString = htmlStr => {
|
|
41
|
+
if (IS(htmlStr, Text, Comment)) {
|
|
42
|
+
return htmlStr;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const testStr = htmlStr?.trim();
|
|
46
|
+
let text = testStr?.split(/<text>|<\/text>/i) ?? [];
|
|
47
|
+
|
|
48
|
+
if (text?.length) {
|
|
49
|
+
text = text.length > 1 ? text.filter(v => v.length).shift() : undefined;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (testStr.startsWith(`<!--`) && testStr.endsWith(`-->`)) {
|
|
53
|
+
return document.createComment(htmlStr.replace(/<!--|-->$/g, ''));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (text || !/^<(.+)[^>]+>/m.test(testStr)) {
|
|
57
|
+
return document.createTextNode(text);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const nwElem = htmlToVirtualElement(htmlStr);
|
|
61
|
+
|
|
62
|
+
if (nwElem.childNodes.length < 1) {
|
|
63
|
+
return createElementFromHtmlString(`<span data-jqxcreationerror="1">${truncateHtmlStr(htmlStr, 60)}</span>`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return nwElem.children[0];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
getRestricted,
|
|
71
|
+
createElementFromHtmlString,
|
|
72
|
+
element2DOM,
|
|
73
|
+
cleanupHtml,
|
|
74
|
+
inject2DOMTree,
|
|
75
|
+
insertPositions,
|
|
76
|
+
ATTRS,
|
|
77
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { truncate2SingleStr, IS } from "./JQxExtensionHelpers.js";
|
|
2
|
+
import cleanupTagInfo from "./HTMLTags.js";
|
|
3
|
+
import {ATTRS} from "./EmbedResources.js";
|
|
4
|
+
import {debugLog} from "./JQxLog.js";
|
|
5
|
+
import {escHtml} from "./Utilities.js";
|
|
6
|
+
|
|
7
|
+
let logElementCreationErrors2Console = true;
|
|
8
|
+
const attrRegExpStore = {
|
|
9
|
+
data: /data-[\-\w.\p{L}]/ui, // data-* minimal 1 character after dash
|
|
10
|
+
validURL: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
|
|
11
|
+
whiteSpace: /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g,
|
|
12
|
+
notAllowedValues: /javascript|injected|noreferrer|alert|DataURL/gi
|
|
13
|
+
};
|
|
14
|
+
const logContingentErrors = elCreationInfo => {
|
|
15
|
+
if (logElementCreationErrors2Console && Object.keys(elCreationInfo.removed).length) {
|
|
16
|
+
const msgs = Object.entries(elCreationInfo.removed)
|
|
17
|
+
.reduce( (acc, [k, v]) => [...acc, `${escHtml(k)} => ${v}`], [])
|
|
18
|
+
.join(`\\000A`);
|
|
19
|
+
debugLog.log(`JQx HTML creation errors: ${debugLog.isConsole ? msgs : escHtml(msgs)}`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const elementCheck = function(child) {
|
|
23
|
+
const name = child.nodeName.toLowerCase();
|
|
24
|
+
const notAllowedCustomElementNames = [
|
|
25
|
+
`annotation-xml`, `color-profile`, `font-face`, `font-face-src`,
|
|
26
|
+
`font-face-uri`, `font-face-format`, `font-face-name`, `missing-glyph` ];
|
|
27
|
+
return /-/.test(name) && !notAllowedCustomElementNames.find(v => v === name) || cleanupTagInfo.isAllowed(name);
|
|
28
|
+
};
|
|
29
|
+
const cleanupHtml = el2Clean => {
|
|
30
|
+
const elCreationInfo = {
|
|
31
|
+
rawHTML: el2Clean?.parentElement?.getHTML() ?? `no html`,
|
|
32
|
+
removed: { },
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (IS(el2Clean, HTMLElement)) {
|
|
36
|
+
[...el2Clean.childNodes].forEach(child => {
|
|
37
|
+
if (child?.children?.length) {
|
|
38
|
+
cleanupHtml(child);
|
|
39
|
+
}
|
|
40
|
+
if (child?.attributes) {
|
|
41
|
+
const attrStore = IS(child, SVGElement) ? ATTRS.svg : ATTRS.html;
|
|
42
|
+
|
|
43
|
+
[...(child ?? {attributes: []}).attributes]
|
|
44
|
+
.forEach(attr => {
|
|
45
|
+
const name = attr.name.trim().toLowerCase();
|
|
46
|
+
const value = attr.value.trim().toLowerCase().replace(attrRegExpStore.whiteSpace, ``);
|
|
47
|
+
const evilValue = name === "href"
|
|
48
|
+
? !attrRegExpStore.validURL.test(value)
|
|
49
|
+
: attrRegExpStore.notAllowedValues.test(value);
|
|
50
|
+
const evilAttrib = name.startsWith(`data`) ? !attrRegExpStore.data.test(name) : !!attrStore[name];
|
|
51
|
+
|
|
52
|
+
if (evilValue || evilAttrib) {
|
|
53
|
+
let val = truncate2SingleStr(attr.value || `none`, 60);
|
|
54
|
+
val += val.length === 60 ? `...` : ``;
|
|
55
|
+
elCreationInfo.removed[`${attr.name}`] = `attribute/property (-value) not allowed, removed. Value: ${
|
|
56
|
+
val}`;
|
|
57
|
+
child.removeAttribute(attr.name);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const allowed = elementCheck(child) ||
|
|
63
|
+
child.constructor === CharacterData ||
|
|
64
|
+
child.constructor === Comment;
|
|
65
|
+
|
|
66
|
+
if (!allowed) {
|
|
67
|
+
const tag = (child?.outerHTML || child?.textContent).trim();
|
|
68
|
+
let tagValue = truncate2SingleStr(tag, 60) ?? `EMPTY`;
|
|
69
|
+
tagValue += tagValue.length === 60 ? `...` : ``;
|
|
70
|
+
elCreationInfo.removed[`<${child.nodeName?.toLowerCase()}>`] = `not allowed, not rendered. Value: ${
|
|
71
|
+
tagValue}`;
|
|
72
|
+
child.remove();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
logContingentErrors(elCreationInfo);
|
|
77
|
+
|
|
78
|
+
return el2Clean;
|
|
79
|
+
};
|
|
80
|
+
const emphasize = str => `***${str}***`;
|
|
81
|
+
const getRestricted = emphasizeTag =>
|
|
82
|
+
Object.entries(cleanupTagInfo)
|
|
83
|
+
.reduce((acc, [key, value]) =>
|
|
84
|
+
!value.allowed &&
|
|
85
|
+
[...acc, (emphasizeTag && key === emphasizeTag ? emphasize(key) : key)] ||
|
|
86
|
+
acc, []);
|
|
87
|
+
const logElementCreationErrors = onOff => logElementCreationErrors2Console = onOff;
|
|
88
|
+
|
|
89
|
+
export { cleanupHtml, getRestricted, logElementCreationErrors, ATTRS};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const svgImg = `url('data:image/svg+xml\\3butf8,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%20id%3D%22Layer_1%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%20128%20128%22%20style%3D%22enable-background%3Anew%200%200%20128%20128%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20x%3D%22-368%22%20y%3D%226%22%20style%3D%22display%3Anone%3Bfill%3A%23E0E0E0%3B%22%20width%3D%22866%22%20height%3D%221018%22%2F%3E%3Ccircle%20style%3D%22fill%3A%23FFFFFF%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2248%22%2F%3E%3Ccircle%20style%3D%22fill%3A%238CCFB9%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2239%22%2F%3E%3Ccircle%20style%3D%22fill%3Anone%3Bstroke%3A%23444B54%3Bstroke-width%3A6%3Bstroke-miterlimit%3A10%3B%22%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2248%22%2F%3E%3Cpolyline%20style%3D%22fill%3Anone%3Bstroke%3A%23FFFFFF%3Bstroke-width%3A6%3Bstroke-linecap%3Around%3Bstroke-miterlimit%3A10%3B%22%20points%3D%2242%2C69%2055.55%2C81%20%20%2086%2C46%20%22%2F%3E%3C%2Fsvg%3E')`;
|
|
2
|
+
let logStyling = getLogStyling();
|
|
3
|
+
let popupStyling = getPopupStyling();
|
|
4
|
+
const ATTRS = getAttrs();
|
|
5
|
+
const allTags = getPermissions();
|
|
6
|
+
export {logStyling, popupStyling, ATTRS, allTags};
|
|
7
|
+
|
|
8
|
+
function getAttrs() {
|
|
9
|
+
return {
|
|
10
|
+
html: Object.freeze(`accept,action,align,alt,autocapitalize,autocomplete,autopictureinpicture,autoplay,background,bgcolor,border,capture,cellpadding,cellspacing,checked,cite,class,clear,contenteditable,color,cols,colspan,controls,controlslist,coords,crossorigin,datetime,decoding,default,dir,disabled,disablepictureinpicture,disableremoteplayback,download,draggable,enctype,enterkeyhint,face,for,headers,height,hidden,high,href,hreflang,id,inputmode,integrity,is,ismap,kind,label,lang,list,loading,loop,low,max,maxlength,media,method,min,minlength,multiple,muted,name,nonce,noshade,novalidate,nowrap,open,optimum,pattern,placeholder,playsinline,poster,preload,pubdate,radiogroup,readonly,rel,required,rev,reversed,role,rows,rowspan,spellcheck,scope,selected,shape,size,sizes,span,srclang,start,src,srcset,step,style,summary,tabindex,target,title,translate,type,usemap,valign,value,width,xmlns,slot`
|
|
11
|
+
.split(`,`)),
|
|
12
|
+
svg: Object.freeze(`accent-height,accumulate,additive,alignment-baseline,ascent,attributename,attributetype,azimuth,basefrequency,baseline-shift,begin,bias,by,class,clip,clippathunits,clip-path,clip-rule,color,color-interpolation,color-interpolation-filters,color-profile,color-rendering,cx,cy,d,dx,dy,diffuseconstant,direction,display,divisor,dur,edgemode,elevation,end,fill,fill-opacity,fill-rule,filter,filterunits,flood-color,flood-opacity,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,fx,fy,g1,g2,glyph-name,glyphref,gradientunits,gradienttransform,height,href,id,image-rendering,in,in2,k,k1,k2,k3,k4,kerning,keypoints,keysplines,keytimes,lang,lengthadjust,letter-spacing,kernelmatrix,kernelunitlength,lighting-color,local,marker-end,marker-mid,marker-start,markerheight,markerunits,markerwidth,maskcontentunits,maskunits,max,mask,media,method,mode,min,name,numoctaves,offset,operator,opacity,order,orient,orientation,origin,overflow,paint-order,path,pathlength,patterncontentunits,patterntransform,patternunits,points,preservealpha,preserveaspectratio,primitiveunits,r,rx,ry,radius,refx,refy,repeatcount,repeatdur,restart,result,rotate,scale,seed,shape-rendering,specularconstant,specularexponent,spreadmethod,startoffset,stddeviation,stitchtiles,stop-color,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke,stroke-width,style,surfacescale,systemlanguage,tabindex,targetx,targety,transform,text-anchor,text-decoration,text-rendering,textlength,type,u1,u2,unicode,values,viewbox,visibility,version,vert-adv-y,vert-origin-x,vert-origin-y,width,word-spacing,wrap,writing-mode,xchannelselector,ychannelselector,x,x1,x2,xmlns,y,y1,y2,z,zoomandpan`
|
|
13
|
+
.split(`,`)),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getPermissions() {
|
|
18
|
+
return {a:true,area:true,audio:false,br:true,base:true,body:true,button:true,canvas:true,comment:true,dl:true,data:true,datalist:true,div:true,em:true, embed:false,fieldset:true,font:true,footer:true,form:false,hr:true,head:true,header:true,output:true,iframe:false,frameset:false,img:true,input:true,li:true,label:true,legend:true,link:true,map:true,mark:true,menu:true,media:true,meta:true,nav:true,meter:true,ol:true,object:false,optgroup:true,option:true,p:true,param:true,picture:true,pre:true,progress:false,quote:true,script:false,select:true,source:true,span:true,style:true,caption:true,td:true,col:true,table:true,tr:true,template:false,textarea:true,time:true,title:true,track:true,details:true,ul:true,video:true,del:true,ins:true,slot:true,blockquote:true,svg:true,dialog:true,summary:true,main:true,address:true,colgroup:true,tbody:true,tfoot:true,thead:true,th:true,dd:true,dt:true,figcaption:true,figure:true,i:true,b:true,code:true,h1:true,h2:true,h3:true,h4:true,abbr:true,bdo:true,dfn:true,kbd:true,q:true,rb:true,rp:true,rt:true,ruby:true,s:true,strike:true,samp:true,small:true,strong:true,sup:true,sub:true,u:true,var:true,wbr:true,nobr:true,tt:true,noscript:true};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getLogStyling() {
|
|
22
|
+
return [
|
|
23
|
+
"#logBox{min-width:0px;max-width:0px;min-height:0px;max-height:0px;width:0;height:0;z-index:-1;border:none;padding:0px;overflow:hidden;transition:all 0.3s ease;margin-top:-100px;}",
|
|
24
|
+
"#logBox.visible{background-color:rgb(255, 255, 224);z-index:1;position:static;border:1px dotted rgb(153, 153, 153);max-width:50vw;min-width:30vw;min-height:10vh;max-height:90vh;overflow:auto;width:50vw;height:20vh;margin:1rem 0px;padding:0px 8px 19px;resize:both;}",
|
|
25
|
+
"#logBox.visible .legend{position:absolute;}",
|
|
26
|
+
"#logBox .legend{text-align:center;margin-top:-1em;width:inherit;max-width:inherit;}",
|
|
27
|
+
"#logBox .legend div{text-align:center;display:inline-block;max-width:inherit;height:1.2rem;background-color:rgb(119, 119, 119);padding:2px 10px;color:rgb(255, 255, 255);box-shadow:rgb(119 119 119) 2px 1px 10px;border-radius:4px;}",
|
|
28
|
+
"#logBox .legend div:before{content:'JQx Logging (chronological)';}",
|
|
29
|
+
"#logBox .legend.reversed div:before{content:'JQx Logging (reversed)';}",
|
|
30
|
+
"#logBox #jqx_logger{marginTop:0.7rem;lineHeight:1.4em;font-family:consolas,monospace;whiteSpace:pre-wrap;maxWidth:inherit;padding-left:100px;}",
|
|
31
|
+
"#logBox #jqx_logger div.entry{text-indent:-100px;whiteSpace:normal;}",
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getPopupStyling() {
|
|
36
|
+
return [
|
|
37
|
+
".popupContainer{position:fixed;inset:-5000px;opacity:0;height:0;width:0;background:rgba(0,0,0,0.1);transition:opacity 0.6s ease-in-out 0s;}",
|
|
38
|
+
".popupContainer.popup-active{opacity:1;inset:0;height:auto;width:auto;z-index:2147483646;}",
|
|
39
|
+
".popupContainer .content{box-shadow:rgba(0,0,0,0.5) 2px 2px 8px;border-radius:3px;min-width:125px;max-width:40vw;max-height:40vh;padding:8px;overflow:auto;background:#FFF;z-index:inherit;opacity:1;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}",
|
|
40
|
+
".popupContainer .content .popup-warn{position:relative;padding:3px 8px 0 8px;color:red;margin:6px -8px -4px -8px;text-align:center;display:none;}",
|
|
41
|
+
".popupContainer .content.popup-warn-active .popup-warn{display:block;border-top:1px dashed rgb(0,0,0);}",
|
|
42
|
+
`.closeHandleIcon{z-index:1;position:absolute;opacity:0;cursor:pointer;width:24px;height:24px;background:${svgImg} no-repeat;}`,
|
|
43
|
+
".closeHandleIcon.popup-active{opacity:1;z-index:2147483647;}",
|
|
44
|
+
"@media screen and (width < 1200px){.popupContainer .content{max-width:75vw;}}",
|
|
45
|
+
"@media screen and (width < 640px){.popupContainer .content{max-width:90vw;max-height:60vw;}}",
|
|
46
|
+
];
|
|
47
|
+
}
|
package/src/HTMLTags.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { allTags } from "./EmbedResources.js";
|
|
2
|
+
import { IS } from "./JQxExtensionHelpers.js";
|
|
3
|
+
let lenient = false;
|
|
4
|
+
const allowUnknownHtmlTags = {
|
|
5
|
+
on: () => lenient = true,
|
|
6
|
+
off: () => lenient = false,
|
|
7
|
+
};
|
|
8
|
+
export default {
|
|
9
|
+
tagsRaw: allTags,
|
|
10
|
+
allowUnknownHtmlTags,
|
|
11
|
+
isAllowed(elem) {
|
|
12
|
+
if (lenient) { return true; }
|
|
13
|
+
const nodeName = IS(elem, String) ? elem.toLowerCase() : elem?.nodeName.toLowerCase() || `none`;
|
|
14
|
+
return nodeName === `#text` || !!allTags[nodeName];
|
|
15
|
+
},
|
|
16
|
+
allowTag: tag2Allow => allTags[tag2Allow.toLowerCase()] = true,
|
|
17
|
+
prohibitTag: tag2Prohibit => allTags[tag2Prohibit.toLowerCase()] = false,
|
|
18
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import jqx from "../index.js";
|
|
2
|
+
let handlers = {};
|
|
3
|
+
const shouldCaptureEventTypes = [
|
|
4
|
+
`load`, `unload`, `scroll`, `focus`, `blur`, `DOMNodeRemovedFromDocument`,
|
|
5
|
+
`DOMNodeInsertedIntoDocument`, `loadstart`, `progress`, `error`, `abort`,
|
|
6
|
+
`load`, `loadend`, `pointerenter`, `pointerleave`, `readystatechange`];
|
|
7
|
+
const getCapture = eventType => !!(shouldCaptureEventTypes.find(t => t === eventType));
|
|
8
|
+
export default () => {
|
|
9
|
+
const metaHandler = evt => handlers[evt.type].forEach(handler => handler(evt));
|
|
10
|
+
|
|
11
|
+
const createHandlerForHID = (HID, callback) => {
|
|
12
|
+
return evt => {
|
|
13
|
+
const target = evt.target?.closest?.(HID);
|
|
14
|
+
return target && callback(evt, jqx(target));
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const addListenerIfNotExisting = (eventType, capture) => {
|
|
19
|
+
if (!handlers[eventType]) {
|
|
20
|
+
addEventListener(eventType, metaHandler, getCapture(eventType));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (eventType, HIDselector, callback, capture = false) => { /*NODOC*/
|
|
25
|
+
addListenerIfNotExisting(eventType, capture);
|
|
26
|
+
const fn = !HIDselector ? callback : createHandlerForHID(HIDselector, callback);
|
|
27
|
+
handlers = handlers[eventType]
|
|
28
|
+
? {...handlers, [eventType]: handlers[eventType].concat(fn)}
|
|
29
|
+
: {...handlers, [eventType]: [fn]};
|
|
30
|
+
};
|
|
31
|
+
};
|