lightview 2.0.8 → 2.1.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/README.md +47 -1283
- package/build-bundles.mjs +109 -0
- package/cdom/helpers/array.js +70 -0
- package/cdom/helpers/compare.js +26 -0
- package/cdom/helpers/conditional.js +34 -0
- package/cdom/helpers/datetime.js +54 -0
- package/cdom/helpers/format.js +20 -0
- package/cdom/helpers/logic.js +24 -0
- package/cdom/helpers/lookup.js +25 -0
- package/cdom/helpers/math.js +34 -0
- package/cdom/helpers/network.js +41 -0
- package/cdom/helpers/state.js +77 -0
- package/cdom/helpers/stats.js +39 -0
- package/cdom/helpers/string.js +49 -0
- package/cdom/parser.js +602 -0
- package/components/actions/button.js +19 -6
- package/components/actions/dropdown.js +6 -6
- package/components/actions/modal.js +9 -9
- package/components/actions/swap.js +31 -8
- package/components/daisyui.js +1 -1
- package/components/data-display/accordion.js +6 -6
- package/components/data-display/alert.js +17 -7
- package/components/data-display/avatar.js +7 -7
- package/components/data-display/badge.js +14 -6
- package/components/data-display/card.js +7 -7
- package/components/data-display/carousel.js +4 -4
- package/components/data-display/chart.js +8 -8
- package/components/data-display/chat.js +7 -7
- package/components/data-display/collapse.js +5 -5
- package/components/data-display/countdown.js +3 -3
- package/components/data-display/diff.js +6 -6
- package/components/data-display/kbd.js +12 -6
- package/components/data-display/loading.js +14 -6
- package/components/data-display/progress.js +14 -6
- package/components/data-display/radial-progress.js +15 -6
- package/components/data-display/stats.js +9 -9
- package/components/data-display/table.js +9 -9
- package/components/data-display/timeline.js +8 -8
- package/components/data-display/toast.js +3 -3
- package/components/data-display/tooltip.js +20 -3
- package/components/data-input/checkbox.js +5 -5
- package/components/data-input/file-input.js +3 -3
- package/components/data-input/input.js +5 -5
- package/components/data-input/radio.js +9 -9
- package/components/data-input/range.js +3 -3
- package/components/data-input/rating.js +3 -3
- package/components/data-input/select.js +5 -5
- package/components/data-input/textarea.js +3 -3
- package/components/data-input/toggle.js +5 -5
- package/components/layout/divider.js +24 -4
- package/components/layout/drawer.js +7 -7
- package/components/layout/footer.js +5 -5
- package/components/layout/hero.js +5 -5
- package/components/layout/indicator.js +18 -4
- package/components/layout/join.js +4 -4
- package/components/layout/navbar.js +6 -6
- package/components/navigation/breadcrumbs.js +4 -4
- package/components/navigation/dock.js +5 -5
- package/components/navigation/menu.js +6 -6
- package/components/navigation/pagination.js +3 -3
- package/components/navigation/steps.js +4 -4
- package/components/navigation/tabs.js +296 -21
- package/components/theme/theme-switch.js +30 -30
- package/docs/about.html +141 -7
- package/docs/api/computed.html +1 -6
- package/docs/api/effects.html +1 -7
- package/docs/api/elements.html +130 -58
- package/docs/api/enhance.html +1 -6
- package/docs/api/hypermedia.html +182 -23
- package/docs/api/index.html +11 -12
- package/docs/api/nav.html +35 -4
- package/docs/api/signals.html +1 -6
- package/docs/api/state.html +1 -6
- package/docs/assets/js/examplify-sandbox.html +2 -2
- package/docs/assets/js/examplify.js +15 -15
- package/docs/cdom-nav.html +29 -0
- package/docs/cdom.html +362 -0
- package/docs/components/accordion.html +4 -4
- package/docs/components/alert.html +12 -12
- package/docs/components/avatar.html +4 -4
- package/docs/components/badge.html +59 -4
- package/docs/components/breadcrumbs.html +3 -3
- package/docs/components/button.html +83 -97
- package/docs/components/card.html +4 -4
- package/docs/components/carousel.html +3 -3
- package/docs/components/chart-area.html +6 -6
- package/docs/components/chart-bar.html +6 -6
- package/docs/components/chart-column.html +6 -6
- package/docs/components/chart-line.html +6 -6
- package/docs/components/chart-pie.html +6 -6
- package/docs/components/chart.html +2 -2
- package/docs/components/chat.html +4 -4
- package/docs/components/checkbox.html +4 -4
- package/docs/components/collapse.html +4 -4
- package/docs/components/component-nav.html +1 -1
- package/docs/components/countdown.html +4 -4
- package/docs/components/diff.html +3 -3
- package/docs/components/divider.html +68 -24
- package/docs/components/dock.html +3 -3
- package/docs/components/drawer.html +4 -4
- package/docs/components/dropdown.html +4 -4
- package/docs/components/file-input.html +4 -4
- package/docs/components/footer.html +3 -3
- package/docs/components/gallery.html +2 -2
- package/docs/components/hero.html +3 -3
- package/docs/components/index.css +5 -3
- package/docs/components/index.html +4 -4
- package/docs/components/indicator.html +88 -34
- package/docs/components/input.html +4 -4
- package/docs/components/join.html +3 -3
- package/docs/components/kbd.html +67 -28
- package/docs/components/loading.html +59 -43
- package/docs/components/menu.html +4 -4
- package/docs/components/modal.html +4 -4
- package/docs/components/navbar.html +3 -3
- package/docs/components/pagination.html +3 -3
- package/docs/components/progress.html +48 -7
- package/docs/components/radial-progress.html +35 -15
- package/docs/components/radio.html +4 -4
- package/docs/components/range.html +4 -4
- package/docs/components/rating.html +4 -4
- package/docs/components/select.html +4 -4
- package/docs/components/sidebar-setup.js +1 -1
- package/docs/components/spinner.html +4 -4
- package/docs/components/stats.html +4 -4
- package/docs/components/steps.html +3 -3
- package/docs/components/swap.html +187 -104
- package/docs/components/switch.html +4 -4
- package/docs/components/table.html +4 -4
- package/docs/components/tabs.html +147 -279
- package/docs/components/text-input.html +4 -4
- package/docs/components/textarea.html +4 -4
- package/docs/components/timeline.html +4 -4
- package/docs/components/toast.html +4 -4
- package/docs/components/toggle.html +4 -4
- package/docs/components/tooltip.html +75 -35
- package/docs/examples/getting-started-example.html +1 -1
- package/docs/examples/index.html +1 -2
- package/docs/getting-started/index.html +112 -19
- package/docs/index.html +1 -6
- package/docs/router-nav.html +13 -0
- package/docs/router.html +60 -17
- package/docs/styles/index.html +2 -7
- package/docs/syntax-nav.html +10 -0
- package/docs/syntax.html +146 -0
- package/functions/_middleware.js +17 -10
- package/functions/processServerScripts.js +127 -0
- package/index.html +8 -8
- package/lightview-all.js +1 -0
- package/lightview-cdom.js +1 -0
- package/lightview-router.js +71 -22
- package/lightview-x.js +1 -1247
- package/lightview.js +1 -760
- package/lightview.js.bak +1 -0
- package/package.json +37 -26
- package/scripts/analysis/README.md +2 -0
- package/scripts/analysis/analyze.js +266 -0
- package/scripts/analysis/latest_metrics.md +185 -0
- package/src/lightview-all.js +10 -0
- package/src/lightview-cdom.js +305 -0
- package/src/lightview-x.js +1581 -0
- package/src/lightview.js +694 -0
- package/src/reactivity/signal.js +133 -0
- package/src/reactivity/state.js +217 -0
- package/test-text-tag.js +6 -0
- package/tests/cdom/fixtures/helpers.cdomc +62 -0
- package/tests/cdom/fixtures/user.cdom +14 -0
- package/tests/cdom/fixtures/user.cdomc +12 -0
- package/tests/cdom/fixtures/user.odom +18 -0
- package/tests/cdom/fixtures/user.vdom +11 -0
- package/tests/cdom/helpers.test.js +121 -0
- package/tests/cdom/loader.test.js +125 -0
- package/tests/cdom/parser.test.js +108 -0
- package/tests/cdom/reactivity.test.js +186 -0
- package/tests/text-tag.test.js +77 -0
- package/vite.config.mjs +52 -0
- package/wrangler.toml +6 -0
- package/components/data-display/skeleton.js +0 -66
- package/docs/components/skeleton.html +0 -447
- package/docs/playground.html +0 -416
package/lightview.js.bak
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(){"use strict";const e=globalThis.__LIGHTVIEW_INTERNALS__||(globalThis.__LIGHTVIEW_INTERNALS__={currentEffect:null,registry:new Map,dependencyMap:new WeakMap}),t=(t,n)=>{let o="string"==typeof n?n:null==n?void 0:n.name;const r=null==n?void 0:n.storage;if(o&&r)try{const e=r.getItem(o);null!==e&&(t=JSON.parse(e))}catch(l){}let s=t;const i=new Set,a=(...e)=>{if(0===e.length)return a.value;a.value=e[0]};if(Object.defineProperty(a,"value",{get:()=>(e.currentEffect&&(i.add(e.currentEffect),e.currentEffect.dependencies.add(i)),s),set(e){if(s!==e){if(s=e,o&&r)try{r.setItem(o,JSON.stringify(s))}catch(l){}[...i].forEach(e=>e())}}}),o)if(e.registry.has(o)){if(e.registry.get(o)!==a)throw new Error(`Lightview: A signal or state with the name "${o}" is already registered.`)}else e.registry.set(o,a);return a};t.get=(n,o)=>e.registry.has(n)||void 0===o?e.registry.get(n):t(o,n);const n=t=>{const n=()=>{if(n.active&&!n.running){n.dependencies.forEach(e=>e.delete(n)),n.dependencies.clear(),n.running=!0,e.currentEffect=n;try{t()}finally{e.currentEffect=null,n.running=!1}}};return n.active=!0,n.running=!1,n.dependencies=new Set,n.stop=()=>{n.dependencies.forEach(e=>e.delete(n)),n.dependencies.clear(),n.active=!1},n(),n},o={get currentEffect(){return(globalThis.__LIGHTVIEW_INTERNALS__||(globalThis.__LIGHTVIEW_INTERNALS__={})).currentEffect}},r=(e,t,n)=>{let o=e.get(t);return o||(o=n(),e.set(t,o)),o},s=new WeakMap,i=()=>({effects:[],onmount:null,onunmount:null}),a=e.registry,l=(e,t)=>{const n=r(s,e,i);n.effects||(n.effects=[]),n.effects.push(t)},c=Symbol("lightview.shadowDOM"),d=e=>e&&"object"==typeof e&&!0===e[c],u=(e,t)=>{if(t.shadowRoot)return void console.warn("Lightview: Element already has a shadowRoot, skipping shadowDOM directive");const n=t.attachShadow({mode:e.mode}),o=[],r=[...e.styles||[]];if(e.adoptedStyleSheets&&e.adoptedStyleSheets.length>0&&e.adoptedStyleSheets.forEach(e=>{e instanceof CSSStyleSheet?o.push(e):"string"==typeof e&&r.push(e)}),o.length>0)try{n.adoptedStyleSheets=o}catch(s){console.warn("Lightview: adoptedStyleSheets not supported")}for(const i of r){const e=document.createElement("link");e.rel="stylesheet",e.href=i,n.appendChild(e)}e.children&&e.children.length>0&&S(e.children,n)};let f=!1;const h=new WeakMap,p=(e,t,n={},o=[])=>{const r=y({tag:t,attributes:n,children:o,get domEl(){return e}});return h.set(e,r),r},g=(e,t={},n=[])=>{if(C[e]&&(e=C[e]),"function"==typeof e){const o=e({...t},n);return m(o)}if("shadowDOM"===e)return((e,t)=>({[c]:!0,mode:e.mode||"open",styles:e.styles||[],adoptedStyleSheets:e.adoptedStyleSheets||[],children:t}))(t,n);const o="svg"===e.toLowerCase(),r=f;o&&(f=!0);const s=f?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e),i=p(s,e,t,n);return i.attributes=t,i.children=n,o&&(f=r),i},m=e=>{if(!e)return null;if(T.hooks.processChild&&(e=T.hooks.processChild(e)??e),e.domEl)return e;const t=typeof e;if("object"===t&&e instanceof HTMLElement)return p(e,e.tagName.toLowerCase(),{},[]);if("object"===t&&e instanceof String){const t=document.createElement("span");return t.textContent=e.toString(),p(t,"span",{},[])}if("string"===t){const t=document.createElement("template");t.innerHTML=e.trim();const n=t.content;if(1===n.childNodes.length&&n.firstChild instanceof HTMLElement){const e=n.firstChild;return p(e,e.tagName.toLowerCase(),{},[])}{const e=document.createElement("span");return e.style.display="contents",e.appendChild(n),p(e,"span",{},[])}}return"object"==typeof e&&e.tag?g(e.tag,e.attributes||{},e.children||[]):null},y=e=>{const t=e.domEl;return new Proxy(e,{set:(e,n,o)=>(e[n]="attributes"===n?v(o,t):"children"===n?L(o,t):o,!0)})},w=new Set(["value","checked","selected","selectedIndex","className","innerHTML","innerText"]),b=(e,t,n)=>{const o="boolean"==typeof e[t];"href"!==t&&"src"!==t||"string"!=typeof n||!/^(javascript|vbscript|data:text\/html|data:application\/javascript)/i.test(n)||(console.warn(`[Lightview] Blocked dangerous protocol in ${t}: ${n}`),n="javascript:void(0)"),w.has(t)||o?e[t]=o?null!=n&&!1!==n&&"false"!==n:n:null==n?e.removeAttribute(t):e.setAttribute(t,n)},v=(e,t)=>{const o={};for(let[a,c]of Object.entries(e))if("onmount"===a||"onunmount"===a){r(s,t,i)[a]=c,"onmount"===a&&t.isConnected&&c(t)}else if(a.startsWith("on")){if("function"==typeof c){const e=a.slice(2).toLowerCase();t.addEventListener(e,c)}else"string"==typeof c&&t.setAttribute(a,c);o[a]=c}else if("function"==typeof c){const e=n(()=>{const e=c();"style"===a&&"object"==typeof e?Object.assign(t.style,e):b(t,a,e)});l(t,e),o[a]=c}else"style"===a&&"object"==typeof c?(Object.entries(c).forEach(([e,o])=>{if("function"==typeof o){const r=n(()=>{t.style[e]=o()});l(t,r)}else t.style[e]=o}),o[a]=c):(b(t,a,c),o[a]=c);return o},E=(e,t,o=!0)=>{o&&void 0!==t.innerHTML&&(t.innerHTML="");const r=[],s=t.tagName&&("script"===t.tagName.toLowerCase()||"style"===t.tagName.toLowerCase()),i=e.flat(1/0);for(let a of i){if(T.hooks.processChild&&!s&&(a=T.hooks.processChild(a)??a),d(a)){if(t instanceof ShadowRoot){console.warn("Lightview: Cannot nest shadowDOM inside another shadowDOM");continue}u(a,t);continue}const e=typeof a;if("function"===e){const e=document.createComment("lv:s"),o=document.createComment("lv:e");let s;t.appendChild(e),t.appendChild(o);const i=()=>{for(;e.nextSibling&&e.nextSibling!==o;)e.nextSibling.remove();const t=a();if(null!=t)if(!s||e.isConnected)if("object"==typeof t&&t instanceof String){const e=document.createTextNode(t);o.parentNode.insertBefore(e,o)}else{const e=document.createDocumentFragment(),n=Array.isArray(t)?t:[t];E(n,e,!1),o.parentNode.insertBefore(e,o)}else s.stop()};s=n(i),l(e,s),r.push(a)}else if(["string","number","boolean","symbol"].includes(e)||a&&"object"===e&&a instanceof String)t.appendChild(document.createTextNode(a)),r.push(a);else if(a&&"object"===e&&a.tag){const e=a.domEl?a:g(a.tag,a.attributes||{},a.children||[]);t.appendChild(e.domEl),r.push(e)}}return r},S=(e,t)=>E(e,t,!1),L=(e,t)=>E(e,t,!0),C={},N=new Proxy({},{get(e,t){if("_customTags"===t)return{...C};const n=(...e)=>{let n={},o=e;const r=e[0];return e.length>0&&r&&"object"==typeof r&&!r.tag&&!r.domEl&&!Array.isArray(r)&&(n=r,o=e.slice(1)),g(C[t]||t,n,o)};return C[t]&&Object.assign(n,C[t]),n},set:(e,t,n)=>(C[t]=n,!0)}),T={signal:t,computed:e=>{const o=t(void 0);return n(()=>{o.value=e()}),o},effect:n,get:get,registry:a,element:g,enhance:(e,t={})=>{const o="string"==typeof e?document.querySelector(e):e,r=o.domEl||o;if(!(r instanceof HTMLElement))return null;const s=r.tagName.toLowerCase();let i=h.get(r);i||(i=p(r,s));const{innerText:a,innerHTML:l,...c}=t;return void 0!==a&&("function"==typeof a?n(()=>{r.innerText=a()}):r.innerText=a),void 0!==l&&("function"==typeof l?n(()=>{r.innerHTML=l()}):r.innerHTML=l),Object.keys(c).length>0&&(i.attributes=c),i},tags:N,$:(e,t=document.body)=>{const n="string"==typeof e?t.querySelector(e):e;return n?(Object.defineProperty(n,"content",{value(e,t="inner"){t=t.toLowerCase(),T.tags;const o=n.tagName&&("script"===n.tagName.toLowerCase()||"style"===n.tagName.toLowerCase()),r=(Array.isArray(e)?e:[e]).map(e=>(T.hooks.processChild&&!o&&(e=T.hooks.processChild(e)??e),e.tag&&!e.domEl?g(e.tag,e.attributes||{},e.children||[]).domEl:e.domEl||e)),s="shadow"===t?n.shadowRoot||n.attachShadow({mode:"open"}):n;return"inner"===t||"shadow"===t?s.replaceChildren(...r):"outer"===t?s.replaceWith(...r):"afterbegin"===t?s.prepend(...r):"beforeend"===t?s.append(...r):r.forEach(e=>n.insertAdjacentElement(t,e)),n},configurable:!0,writable:!0}),n):null},hooks:{onNonStandardHref:null,processChild:null,validateUrl:null},internals:{core:o,domToElement:h,wrapDomElement:p,setupChildren:L}};if("undefined"!=typeof module&&module.exports&&(module.exports=T),"undefined"!=typeof window&&(globalThis.Lightview=T,globalThis.addEventListener("click",e=>{const t=e.composedPath().find(e=>{var t,n;return"A"===e.tagName&&(null==(n=null==(t=e.getAttribute)?void 0:t.call(e,"href"))?void 0:n.startsWith("#"))});if(t&&!e.defaultPrevented){const n=t.getAttribute("href");if(n.length>1){const o=n.slice(1),r=t.getRootNode(),s=(r.getElementById?r.getElementById(o):null)||(r.querySelector?r.querySelector(`#${o}`):null);s&&(e.preventDefault(),requestAnimationFrame(()=>{requestAnimationFrame(()=>{s.style.scrollMarginTop="calc(var(--site-nav-height, 0px) + 2rem)",s.scrollIntoView({behavior:"smooth",block:"start",inline:"start"})})}))}}T.hooks.onNonStandardHref&&T.hooks.onNonStandardHref(e)}),"undefined"!=typeof MutationObserver)){const e=(t,n)=>{var o;n(t),null==(o=t.childNodes)||o.forEach(t=>e(t,n)),t.shadowRoot&&e(t.shadowRoot,n)},t=t=>e(t,e=>{var t,n;const o=s.get(e);o&&(null==(t=o.effects)||t.forEach(e=>e.stop()),null==(n=o.onunmount)||n.call(o,e),s.delete(e))}),n=t=>e(t,e=>{var t,n;null==(n=null==(t=s.get(e))?void 0:t.onmount)||n.call(t,e)}),o=new MutationObserver(e=>{e.forEach(e=>{e.removedNodes.forEach(t),e.addedNodes.forEach(n)})}),r=()=>{document.body&&o.observe(document.body,{childList:!0,subtree:!0})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",r):r()}}();
|
package/package.json
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "lightview",
|
|
3
|
-
"version": "2.0
|
|
4
|
-
"description": "A lightweight reactive UI library with features of Bau, Juris, and HTMX",
|
|
5
|
-
"main": "lightview.js",
|
|
6
|
-
"directories": {
|
|
7
|
-
"doc": "docs"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"dev": "wrangler pages dev . --port 3000",
|
|
11
|
-
"preview": "npm run build && wrangler pages dev ./dist --port 8788",
|
|
12
|
-
"build": "node build.js",
|
|
13
|
-
"watch": "node watch.js",
|
|
14
|
-
"deploy": "npm run build && wrangler pages deploy dist",
|
|
15
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [],
|
|
18
|
-
"author": "Simon Y. Blackwell, AnyWhichWay LLC",
|
|
19
|
-
"license": "MIT",
|
|
20
|
-
"type": "commonjs",
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "lightview",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "A lightweight reactive UI library with features of Bau, Juris, and HTMX",
|
|
5
|
+
"main": "lightview.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"doc": "docs"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "wrangler pages dev . --port 3000",
|
|
11
|
+
"preview": "npm run build && wrangler pages dev ./dist --port 8788",
|
|
12
|
+
"build": "node build-bundles.mjs && node build.js",
|
|
13
|
+
"watch": "node watch.js",
|
|
14
|
+
"deploy": "npm run build && wrangler pages deploy dist",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [],
|
|
18
|
+
"author": "Simon Y. Blackwell, AnyWhichWay LLC",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"type": "commonjs",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@grucloud/bau": "^0.106.0",
|
|
23
|
+
"acorn": "^8.15.0",
|
|
24
|
+
"acorn-walk": "^8.3.4",
|
|
25
|
+
"htmx.org": "^2.0.8",
|
|
26
|
+
"jsdom": "^27.4.0",
|
|
27
|
+
"juris": "^0.9.0",
|
|
28
|
+
"react": "^19.2.3",
|
|
29
|
+
"terser": "^5.24.0",
|
|
30
|
+
"vite": "^5.0.0",
|
|
31
|
+
"vitest": "^4.0.16",
|
|
32
|
+
"wrangler": "^4.54.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"linkedom": "^0.18.12",
|
|
36
|
+
"marked": "^17.0.1"
|
|
37
|
+
}
|
|
27
38
|
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const acorn = require('acorn');
|
|
3
|
+
const walk = require('acorn-walk');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 2025 LIGHTVIEW CODEBASE METRICS ENGINE
|
|
8
|
+
* Calculates:
|
|
9
|
+
* - Cyclomatic Complexity (Control Flow Paths)
|
|
10
|
+
* - Cognitive Complexity (2025 SonarSource Spec)
|
|
11
|
+
* - Halstead Volume (Operator/Operand Density)
|
|
12
|
+
* - SLOC (Source Lines of Code)
|
|
13
|
+
* - Maintainability Index (MI)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const TARGET_FILES = [
|
|
17
|
+
'../../lightview.js',
|
|
18
|
+
'../../lightview-x.js',
|
|
19
|
+
'../../lightview-router.js',
|
|
20
|
+
'../../node_modules/react/cjs/react.development.js',
|
|
21
|
+
'../../node_modules/@grucloud/bau/bau.js',
|
|
22
|
+
'../../node_modules/htmx.org/dist/htmx.js',
|
|
23
|
+
'../../node_modules/juris/juris.js'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
// --- METRIC CALCULATORS ---
|
|
27
|
+
|
|
28
|
+
const getCyclomaticComplexity = (fnNode) => {
|
|
29
|
+
let complexity = 1;
|
|
30
|
+
walk.recursive(fnNode.body, null, {
|
|
31
|
+
IfStatement(node, state, c) { complexity++; c(node.test, state); c(node.consequent, state); if (node.alternate) c(node.alternate, state); },
|
|
32
|
+
ConditionalExpression(node, state, c) { complexity++; c(node.test, state); c(node.consequent, state); c(node.alternate, state); },
|
|
33
|
+
WhileStatement(node, state, c) { complexity++; c(node.test, state); c(node.body, state); },
|
|
34
|
+
DoWhileStatement(node, state, c) { complexity++; c(node.test, state); c(node.body, state); },
|
|
35
|
+
ForStatement(node, state, c) { complexity++; if (node.init) c(node.init, state); if (node.test) c(node.test, state); if (node.update) c(node.update, state); c(node.body, state); },
|
|
36
|
+
ForInStatement(node, state, c) { complexity++; c(node.left, state); c(node.right, state); c(node.body, state); },
|
|
37
|
+
ForOfStatement(node, state, c) { complexity++; c(node.left, state); c(node.right, state); c(node.body, state); },
|
|
38
|
+
LogicalExpression(node, state, c) {
|
|
39
|
+
if (node.operator === '&&' || node.operator === '||' || node.operator === '??') complexity++;
|
|
40
|
+
c(node.left, state); c(node.right, state);
|
|
41
|
+
},
|
|
42
|
+
SwitchCase(node, state, c) { if (node.test) complexity++; if (node.test) c(node.test, state); node.consequent.forEach(n => c(n, state)); },
|
|
43
|
+
CatchClause(node, state, c) { complexity++; if (node.param) c(node.param, state); c(node.body, state); },
|
|
44
|
+
FunctionDeclaration() { }, FunctionExpression() { }, ArrowFunctionExpression() { }
|
|
45
|
+
});
|
|
46
|
+
return complexity;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const getCognitiveComplexity = (fnNode, fnName) => {
|
|
50
|
+
let score = 0;
|
|
51
|
+
const findRecursion = (node) => {
|
|
52
|
+
let count = 0;
|
|
53
|
+
walk.simple(node, {
|
|
54
|
+
CallExpression(call) { if (call.callee.type === 'Identifier' && call.callee.name === fnName) count++; }
|
|
55
|
+
});
|
|
56
|
+
return count;
|
|
57
|
+
};
|
|
58
|
+
const traverse = (n, d) => {
|
|
59
|
+
if (!n) return 0;
|
|
60
|
+
let s = 0;
|
|
61
|
+
switch (n.type) {
|
|
62
|
+
case 'IfStatement':
|
|
63
|
+
s += (1 + d);
|
|
64
|
+
s += traverse(n.test, d);
|
|
65
|
+
s += traverse(n.consequent, d + 1);
|
|
66
|
+
if (n.alternate) {
|
|
67
|
+
s += 1;
|
|
68
|
+
if (n.alternate.type === 'IfStatement') s += traverseBranch(n.alternate, d);
|
|
69
|
+
else s += traverse(n.alternate, d + 1);
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'SwitchStatement': s += (1 + d); n.cases.forEach(c => s += traverse(c, d + 1)); break;
|
|
73
|
+
case 'ForStatement': case 'ForInStatement': case 'ForOfStatement': case 'WhileStatement': case 'DoWhileStatement':
|
|
74
|
+
s += (1 + d); s += traverse(n.body, d + 1); break;
|
|
75
|
+
case 'CatchClause': s += (1 + d); s += traverse(n.body, d + 1); break;
|
|
76
|
+
case 'LogicalExpression': s += 1; break; // Naive: count each operator sequence as 1
|
|
77
|
+
case 'ConditionalExpression': s += 1; s += traverse(n.consequent, d + 1); s += traverse(n.alternate, d + 1); break;
|
|
78
|
+
case 'BreakStatement': case 'ContinueStatement': s += 1; break;
|
|
79
|
+
case 'FunctionDeclaration': case 'FunctionExpression': case 'ArrowFunctionExpression': break;
|
|
80
|
+
default:
|
|
81
|
+
for (const key in n) {
|
|
82
|
+
const c = n[key];
|
|
83
|
+
if (Array.isArray(c)) c.forEach(i => { if (i?.type) s += traverse(i, d); });
|
|
84
|
+
else if (c?.type) s += traverse(c, d);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return s;
|
|
88
|
+
};
|
|
89
|
+
const traverseBranch = (n, d) => {
|
|
90
|
+
let s = 1; s += traverse(n.test, d); s += traverse(n.consequent, d + 1);
|
|
91
|
+
if (n.alternate) {
|
|
92
|
+
if (n.alternate.type === 'IfStatement') s += traverseBranch(n.alternate, d);
|
|
93
|
+
else { s += 1; s += traverse(n.alternate, d + 1); }
|
|
94
|
+
}
|
|
95
|
+
return s;
|
|
96
|
+
};
|
|
97
|
+
if (fnNode.body) {
|
|
98
|
+
score += traverse(fnNode.body, 0);
|
|
99
|
+
score += findRecursion(fnNode.body);
|
|
100
|
+
}
|
|
101
|
+
return score;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const calculateHalstead = (code) => {
|
|
105
|
+
let tokens = [];
|
|
106
|
+
try {
|
|
107
|
+
tokens = [...acorn.tokenizer(code, { ecmaVersion: 'latest' })];
|
|
108
|
+
} catch (e) {
|
|
109
|
+
// Fallback or skip if tokenization fails for complex files
|
|
110
|
+
}
|
|
111
|
+
const operators = new Set(['(', ')', '[', ']', '{', '}', '.', ',', ';', ':', '?', '...', '=', '+=', '-=', '*=', '/=', '==', '===', '!=', '!==', '<', '>', '<=', '>=', '+', '-', '*', '/', '%', '++', '--', '&&', '||', '??', '!', 'typeof', 'let', 'const', 'var', 'if', 'else', 'for', 'while', 'return']);
|
|
112
|
+
let N1 = 0, N2 = 0; const n1set = new Set(), n2set = new Set();
|
|
113
|
+
tokens.forEach(t => {
|
|
114
|
+
const txt = t.value !== undefined ? String(t.value) : t.type.label;
|
|
115
|
+
if (operators.has(txt)) { N1++; n1set.add(txt); } else { N2++; n2set.add(txt); }
|
|
116
|
+
});
|
|
117
|
+
const N = N1 + N2;
|
|
118
|
+
const n = n1set.size + n2set.size;
|
|
119
|
+
const volume = N * Math.log2(n || 1);
|
|
120
|
+
return { volume, n1: n1set.size, n2: n2set.size, N1, N2 };
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const getSLOC = (code) => code.split('\n').filter(l => l.trim().length > 0 && !l.trim().startsWith('//')).length;
|
|
124
|
+
|
|
125
|
+
const calculateMI = (volume, cc, sloc) => {
|
|
126
|
+
// Standard MI formula: 171 - 5.2 * ln(V) - 0.23 * CC - 16.2 * ln(SLOC)
|
|
127
|
+
const mi = 171 - 5.2 * Math.log(volume || 1) - 0.23 * cc - 16.2 * Math.log(sloc || 1);
|
|
128
|
+
return Math.max(0, Math.min(100, (mi * 100) / 171));
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// --- ANALYSIS CORE ---
|
|
132
|
+
|
|
133
|
+
const analyzeFile = (filePath) => {
|
|
134
|
+
const fullPath = path.resolve(__dirname, filePath);
|
|
135
|
+
if (!fs.existsSync(fullPath)) return { error: `File not found: ${filePath}` };
|
|
136
|
+
|
|
137
|
+
const code = fs.readFileSync(fullPath, 'utf8');
|
|
138
|
+
let ast;
|
|
139
|
+
try {
|
|
140
|
+
ast = acorn.parse(code, { ecmaVersion: 'latest', sourceType: 'script' });
|
|
141
|
+
} catch (e) {
|
|
142
|
+
try {
|
|
143
|
+
ast = acorn.parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
|
|
144
|
+
} catch (e2) {
|
|
145
|
+
return { error: `AST Parse Error: ${e2.message}` };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const sloc = getSLOC(code);
|
|
149
|
+
const fileHalstead = calculateHalstead(code);
|
|
150
|
+
|
|
151
|
+
const fns = [];
|
|
152
|
+
walk.ancestor(ast, {
|
|
153
|
+
FunctionDeclaration(node) { fns.push({ node, name: node.id?.name || '<anonymous>' }); },
|
|
154
|
+
FunctionExpression(node, state, anc) {
|
|
155
|
+
let name = '<anonymous>';
|
|
156
|
+
const p = anc[anc.length - 2];
|
|
157
|
+
if (p?.type === 'VariableDeclarator' && p.id?.name) name = p.id.name;
|
|
158
|
+
else if (p?.type === 'Property' && p.key?.name) name = p.key.name;
|
|
159
|
+
else if (p?.type === 'AssignmentExpression' && p.left?.name) name = p.left.name;
|
|
160
|
+
fns.push({ node, name });
|
|
161
|
+
},
|
|
162
|
+
ArrowFunctionExpression(node, state, anc) {
|
|
163
|
+
let name = '<anonymous>';
|
|
164
|
+
const p = anc[anc.length - 2];
|
|
165
|
+
if (p?.type === 'VariableDeclarator' && p.id?.name) name = p.id.name;
|
|
166
|
+
fns.push({ node, name });
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const results = fns.map(f => {
|
|
171
|
+
const cc = getCyclomaticComplexity(f.node);
|
|
172
|
+
const cog = getCognitiveComplexity(f.node, f.name);
|
|
173
|
+
const fCode = code.slice(f.node.start, f.node.end);
|
|
174
|
+
const h = calculateHalstead(fCode);
|
|
175
|
+
const fSloc = getSLOC(fCode);
|
|
176
|
+
const mi = calculateMI(h.volume, cc, fSloc);
|
|
177
|
+
return { name: f.name, cc, cog, mi, volume: h.volume, sloc: fSloc };
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
fileName: path.basename(filePath),
|
|
182
|
+
sloc,
|
|
183
|
+
fnCount: fns.length,
|
|
184
|
+
totalVolume: fileHalstead.volume,
|
|
185
|
+
results
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// --- REPORT GENERATION ---
|
|
190
|
+
|
|
191
|
+
const generateReport = () => {
|
|
192
|
+
let md = "# Codebase Ethics & Complexity Report\n\n";
|
|
193
|
+
md += `Generated on: ${new Date().toLocaleString()}\n\n`;
|
|
194
|
+
|
|
195
|
+
const summaries = [];
|
|
196
|
+
|
|
197
|
+
TARGET_FILES.forEach(file => {
|
|
198
|
+
console.log(`Analyzing ${file}...`);
|
|
199
|
+
const data = analyzeFile(file);
|
|
200
|
+
if (data.error) {
|
|
201
|
+
md += `### !! Error analyzing ${file}: ${data.error}\n\n`;
|
|
202
|
+
summaries.push({
|
|
203
|
+
name: path.basename(file),
|
|
204
|
+
sloc: '-',
|
|
205
|
+
fns: '-',
|
|
206
|
+
mi: 'Error',
|
|
207
|
+
cog: 'Error',
|
|
208
|
+
status: "❌ Error"
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const miScores = data.results.map(r => r.mi);
|
|
214
|
+
const cogScores = data.results.map(r => r.cog);
|
|
215
|
+
|
|
216
|
+
const minMI = miScores.length ? Math.min(...miScores) : 0;
|
|
217
|
+
const avgMI = miScores.length ? miScores.reduce((a, b) => a + b, 0) / miScores.length : 0;
|
|
218
|
+
const maxMI = miScores.length ? Math.max(...miScores) : 0;
|
|
219
|
+
|
|
220
|
+
const minCog = cogScores.length ? Math.min(...cogScores) : 0;
|
|
221
|
+
const avgCog = cogScores.length ? cogScores.reduce((a, b) => a + b, 0) / cogScores.length : 0;
|
|
222
|
+
const maxCog = cogScores.length ? Math.max(...cogScores) : 0;
|
|
223
|
+
|
|
224
|
+
summaries.push({
|
|
225
|
+
name: data.fileName,
|
|
226
|
+
sloc: data.sloc,
|
|
227
|
+
fns: data.fnCount,
|
|
228
|
+
mi: `${minMI.toFixed(1)} / ${avgMI.toFixed(1)} / ${maxMI.toFixed(1)}`,
|
|
229
|
+
cog: `${minCog.toFixed(0)} / ${avgCog.toFixed(1)} / ${maxCog.toFixed(0)}`,
|
|
230
|
+
avgMI,
|
|
231
|
+
status: avgMI > 80 ? "✅ Excellent" : (avgMI > 65 ? "⚖️ Good" : "⚠️ Attention")
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
md += `## Detail: ${data.fileName}\n\n`;
|
|
235
|
+
md += `| Metric | Overall Value |\n| :--- | :--- |\n`;
|
|
236
|
+
md += `| **SLOC** | ${data.sloc} |\n`;
|
|
237
|
+
md += `| **Function Count** | ${data.fnCount} |\n`;
|
|
238
|
+
md += `| **Avg Maintainability** | **${avgMI.toFixed(2)}/100** |\n\n`;
|
|
239
|
+
|
|
240
|
+
md += `### Top 10 High Friction Functions\n`;
|
|
241
|
+
md += `| Function | Cognitive | Cyclomatic | MI | Status |\n| :--- | :--- | :--- | :--- | :--- |\n`;
|
|
242
|
+
|
|
243
|
+
data.results
|
|
244
|
+
.sort((a, b) => b.cog - a.cog)
|
|
245
|
+
.slice(0, 10)
|
|
246
|
+
.forEach(r => {
|
|
247
|
+
const status = r.cog > 25 ? "🛑 Critical" : (r.cog > 15 ? "⚠️ High" : "✅ Clean");
|
|
248
|
+
md += `| \`${r.name}\` | ${r.cog} | ${r.cc} | ${r.mi.toFixed(1)} | ${status} |\n`;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
md += "\n---\n\n";
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
let summaryHeader = "## Executive Summary\n\n| File | Functions | Maintainability (min/avg/max) | Cognitive (min/avg/max) | Status |\n| :--- | :--- | :--- | :--- | :--- |\n";
|
|
255
|
+
summaries.sort((a, b) => {
|
|
256
|
+
// Optional: sort by status or name. Let's keep TARGET_FILES order if possible, or sort by name.
|
|
257
|
+
return 0; // Keep order of TARGET_FILES
|
|
258
|
+
}).forEach(s => {
|
|
259
|
+
summaryHeader += `| \`${s.name}\` | ${s.fns} | ${s.mi} | ${s.cog} | ${s.status} |\n`;
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
fs.writeFileSync(path.resolve(__dirname, 'latest_metrics.md'), md.replace("# Codebase Ethics & Complexity Report", "# Metrics Report\n\n" + summaryHeader));
|
|
263
|
+
console.log("Analysis complete. Report saved to latest_metrics.md");
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
generateReport();
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Metrics Report
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
| File | Functions | Maintainability (min/avg/max) | Cognitive (min/avg/max) | Status |
|
|
6
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
7
|
+
| `lightview.js` | 58 | 7.2 / 65.5 / 92.9 | 0 / 3.4 / 25 | ⚖️ Good |
|
|
8
|
+
| `lightview-x.js` | 104 | 0.0 / 66.7 / 93.5 | 0 / 3.2 / 23 | ⚖️ Good |
|
|
9
|
+
| `lightview-router.js` | 27 | 24.8 / 68.6 / 93.5 | 0 / 2.1 / 19 | ⚖️ Good |
|
|
10
|
+
| `react.development.js` | 109 | 0.0 / 65.2 / 91.5 | 0 / 2.2 / 33 | ⚖️ Good |
|
|
11
|
+
| `bau.js` | 79 | 11.2 / 71.3 / 92.9 | 0 / 1.5 / 20 | ⚖️ Good |
|
|
12
|
+
| `htmx.js` | 335 | 0.0 / 65.3 / 92.9 | 0 / 3.4 / 116 | ⚖️ Good |
|
|
13
|
+
| `juris.js` | 360 | 21.2 / 70.1 / 96.5 | 0 / 2.6 / 51 | ⚖️ Good |
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Generated on: 12/30/2025, 7:44:35 AM
|
|
17
|
+
|
|
18
|
+
## Detail: lightview.js
|
|
19
|
+
|
|
20
|
+
| Metric | Overall Value |
|
|
21
|
+
| :--- | :--- |
|
|
22
|
+
| **SLOC** | 599 |
|
|
23
|
+
| **Function Count** | 58 |
|
|
24
|
+
| **Avg Maintainability** | **65.52/100** |
|
|
25
|
+
|
|
26
|
+
### Top 10 High Friction Functions
|
|
27
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
28
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
29
|
+
| `processChildren` | 25 | 19 | 35.1 | ⚠️ High |
|
|
30
|
+
| `makeReactiveAttributes` | 19 | 12 | 38.8 | ⚠️ High |
|
|
31
|
+
| `processComponentResult` | 17 | 15 | 42.0 | ⚠️ High |
|
|
32
|
+
| `enhance` | 13 | 10 | 44.6 | ✅ Clean |
|
|
33
|
+
| `value` | 11 | 11 | 44.2 | ✅ Clean |
|
|
34
|
+
| `processShadowDOM` | 10 | 10 | 43.5 | ✅ Clean |
|
|
35
|
+
| `signal` | 9 | 7 | 40.9 | ✅ Clean |
|
|
36
|
+
| `<anonymous>` | 9 | 9 | 59.0 | ✅ Clean |
|
|
37
|
+
| `<anonymous>` | 9 | 9 | 49.2 | ✅ Clean |
|
|
38
|
+
| `<anonymous>` | 9 | 6 | 7.2 | ✅ Clean |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Detail: lightview-x.js
|
|
43
|
+
|
|
44
|
+
| Metric | Overall Value |
|
|
45
|
+
| :--- | :--- |
|
|
46
|
+
| **SLOC** | 1012 |
|
|
47
|
+
| **Function Count** | 104 |
|
|
48
|
+
| **Avg Maintainability** | **66.70/100** |
|
|
49
|
+
|
|
50
|
+
### Top 10 High Friction Functions
|
|
51
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
52
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
53
|
+
| `<anonymous>` | 23 | 20 | 0.0 | ⚠️ High |
|
|
54
|
+
| `state` | 22 | 25 | 39.6 | ⚠️ High |
|
|
55
|
+
| `handleNonStandardHref` | 16 | 12 | 36.5 | ⚠️ High |
|
|
56
|
+
| `registerStyleSheet` | 14 | 8 | 46.5 | ✅ Clean |
|
|
57
|
+
| `removeInsertedContent` | 14 | 7 | 45.5 | ✅ Clean |
|
|
58
|
+
| `convertObjectDOM` | 13 | 12 | 54.0 | ✅ Clean |
|
|
59
|
+
| `<anonymous>` | 13 | 9 | 55.7 | ✅ Clean |
|
|
60
|
+
| `activateReactiveSyntax` | 13 | 10 | 36.9 | ✅ Clean |
|
|
61
|
+
| `<anonymous>` | 12 | 12 | 44.9 | ✅ Clean |
|
|
62
|
+
| `handleSrcAttribute` | 10 | 9 | 47.1 | ✅ Clean |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Detail: lightview-router.js
|
|
67
|
+
|
|
68
|
+
| Metric | Overall Value |
|
|
69
|
+
| :--- | :--- |
|
|
70
|
+
| **SLOC** | 141 |
|
|
71
|
+
| **Function Count** | 27 |
|
|
72
|
+
| **Avg Maintainability** | **68.59/100** |
|
|
73
|
+
|
|
74
|
+
### Top 10 High Friction Functions
|
|
75
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
76
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
77
|
+
| `route` | 19 | 10 | 51.6 | ⚠️ High |
|
|
78
|
+
| `normalizePath` | 7 | 8 | 63.1 | ✅ Clean |
|
|
79
|
+
| `<anonymous>` | 5 | 6 | 50.2 | ✅ Clean |
|
|
80
|
+
| `handleRequest` | 5 | 6 | 52.6 | ✅ Clean |
|
|
81
|
+
| `fetchHandler` | 4 | 4 | 64.3 | ✅ Clean |
|
|
82
|
+
| `<anonymous>` | 4 | 4 | 24.8 | ✅ Clean |
|
|
83
|
+
| `base` | 2 | 3 | 65.1 | ✅ Clean |
|
|
84
|
+
| `<anonymous>` | 2 | 4 | 84.4 | ✅ Clean |
|
|
85
|
+
| `use` | 2 | 3 | 63.6 | ✅ Clean |
|
|
86
|
+
| `<anonymous>` | 2 | 4 | 64.7 | ✅ Clean |
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Detail: react.development.js
|
|
91
|
+
|
|
92
|
+
| Metric | Overall Value |
|
|
93
|
+
| :--- | :--- |
|
|
94
|
+
| **SLOC** | 1282 |
|
|
95
|
+
| **Function Count** | 109 |
|
|
96
|
+
| **Avg Maintainability** | **65.19/100** |
|
|
97
|
+
|
|
98
|
+
### Top 10 High Friction Functions
|
|
99
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
100
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
101
|
+
| `mapIntoArray` | 33 | 39 | 23.6 | 🛑 Critical |
|
|
102
|
+
| `getComponentNameFromType` | 20 | 31 | 34.7 | ⚠️ High |
|
|
103
|
+
| `flushActQueue` | 19 | 7 | 47.0 | ⚠️ High |
|
|
104
|
+
| `<anonymous>` | 19 | 26 | 35.6 | ⚠️ High |
|
|
105
|
+
| `<anonymous>` | 18 | 20 | 35.9 | ⚠️ High |
|
|
106
|
+
| `lazyInitializer` | 9 | 9 | 37.7 | ✅ Clean |
|
|
107
|
+
| `recursivelyFlushAsyncActWork` | 9 | 5 | 51.3 | ✅ Clean |
|
|
108
|
+
| `<anonymous>` | 8 | 9 | 48.2 | ✅ Clean |
|
|
109
|
+
| `<anonymous>` | 7 | 10 | 29.6 | ✅ Clean |
|
|
110
|
+
| `<anonymous>` | 7 | 10 | 0.0 | ✅ Clean |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Detail: bau.js
|
|
115
|
+
|
|
116
|
+
| Metric | Overall Value |
|
|
117
|
+
| :--- | :--- |
|
|
118
|
+
| **SLOC** | 458 |
|
|
119
|
+
| **Function Count** | 79 |
|
|
120
|
+
| **Avg Maintainability** | **71.26/100** |
|
|
121
|
+
|
|
122
|
+
### Top 10 High Friction Functions
|
|
123
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
124
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
125
|
+
| `<anonymous>` | 20 | 17 | 34.0 | ⚠️ High |
|
|
126
|
+
| `updateBinding` | 17 | 11 | 40.0 | ⚠️ High |
|
|
127
|
+
| `replaceChildren` | 14 | 8 | 48.2 | ✅ Clean |
|
|
128
|
+
| `add` | 9 | 7 | 53.3 | ✅ Clean |
|
|
129
|
+
| `toDom` | 6 | 5 | 56.8 | ✅ Clean |
|
|
130
|
+
| `get` | 5 | 6 | 49.4 | ✅ Clean |
|
|
131
|
+
| `processDom` | 4 | 4 | 51.1 | ✅ Clean |
|
|
132
|
+
| `val` | 4 | 5 | 58.1 | ✅ Clean |
|
|
133
|
+
| `val` | 4 | 4 | 55.4 | ✅ Clean |
|
|
134
|
+
| `<anonymous>` | 3 | 6 | 49.7 | ✅ Clean |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Detail: htmx.js
|
|
139
|
+
|
|
140
|
+
| Metric | Overall Value |
|
|
141
|
+
| :--- | :--- |
|
|
142
|
+
| **SLOC** | 4803 |
|
|
143
|
+
| **Function Count** | 335 |
|
|
144
|
+
| **Avg Maintainability** | **65.27/100** |
|
|
145
|
+
|
|
146
|
+
### Top 10 High Friction Functions
|
|
147
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
148
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
149
|
+
| `issueAjaxRequest` | 116 | 73 | 5.5 | 🛑 Critical |
|
|
150
|
+
| `parseAndCacheTrigger` | 68 | 34 | 28.0 | 🛑 Critical |
|
|
151
|
+
| `doSwap` | 41 | 24 | 26.8 | 🛑 Critical |
|
|
152
|
+
| `eventListener` | 39 | 22 | 33.2 | 🛑 Critical |
|
|
153
|
+
| `handleAjaxResponse` | 34 | 29 | 22.9 | 🛑 Critical |
|
|
154
|
+
| `querySelectorAllExt` | 33 | 26 | 31.9 | 🛑 Critical |
|
|
155
|
+
| `swapWithStyle` | 29 | 16 | 38.3 | 🛑 Critical |
|
|
156
|
+
| `updateScrollState` | 27 | 23 | 39.3 | 🛑 Critical |
|
|
157
|
+
| `maybeGenerateConditional` | 26 | 9 | 42.0 | 🛑 Critical |
|
|
158
|
+
| `getSwapSpecification` | 25 | 19 | 36.1 | ⚠️ High |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Detail: juris.js
|
|
163
|
+
|
|
164
|
+
| Metric | Overall Value |
|
|
165
|
+
| :--- | :--- |
|
|
166
|
+
| **SLOC** | 2736 |
|
|
167
|
+
| **Function Count** | 360 |
|
|
168
|
+
| **Avg Maintainability** | **70.11/100** |
|
|
169
|
+
|
|
170
|
+
### Top 10 High Friction Functions
|
|
171
|
+
| Function | Cognitive | Cyclomatic | MI | Status |
|
|
172
|
+
| :--- | :--- | :--- | :--- | :--- |
|
|
173
|
+
| `<anonymous>` | 51 | 28 | 21.2 | 🛑 Critical |
|
|
174
|
+
| `<anonymous>` | 37 | 33 | 26.4 | 🛑 Critical |
|
|
175
|
+
| `<anonymous>` | 36 | 28 | 31.2 | 🛑 Critical |
|
|
176
|
+
| `<anonymous>` | 24 | 14 | 43.2 | ⚠️ High |
|
|
177
|
+
| `<anonymous>` | 24 | 26 | 28.7 | ⚠️ High |
|
|
178
|
+
| `<anonymous>` | 22 | 12 | 44.1 | ⚠️ High |
|
|
179
|
+
| `<anonymous>` | 20 | 8 | 49.5 | ⚠️ High |
|
|
180
|
+
| `updateChildren` | 19 | 11 | 37.4 | ⚠️ High |
|
|
181
|
+
| `<anonymous>` | 18 | 23 | 38.6 | ⚠️ High |
|
|
182
|
+
| `<anonymous>` | 17 | 9 | 46.3 | ⚠️ High |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|