aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2023-08-12 20:13:29 +0530
committerAkshay Nair <phenax5@gmail.com>2023-08-12 20:13:29 +0530
commita61f5ec92a9382b0c25fae9a344da0d7eb21b702 (patch)
tree42d0b265b9f4b9c3c4b2ab3ac5e2a6ffa54bcccd
parent53420ee477e9cad629bd8e6804d477d6ded8c110 (diff)
downloadcss-everything-a61f5ec92a9382b0c25fae9a344da0d7eb21b702.tar.gz
css-everything-a61f5ec92a9382b0c25fae9a344da0d7eb21b702.zip
refactor: moves stuff around
-rw-r--r--esbuild.js4
-rw-r--r--examples/counter/index.html2
-rw-r--r--examples/form/index.html2
-rw-r--r--package.json4
-rw-r--r--src/index.ts164
-rw-r--r--src/renderer.ts164
-rw-r--r--tests/signup.spec.ts2
-rw-r--r--tsconfig.json3
8 files changed, 173 insertions, 172 deletions
diff --git a/esbuild.js b/esbuild.js
index 91c6c44..62b2510 100644
--- a/esbuild.js
+++ b/esbuild.js
@@ -2,8 +2,8 @@ const esbuild = require('esbuild')
esbuild
.build({
- entryPoints: ['src/index.ts'],
- outdir: 'dist',
+ entryPoints: ['src/renderer.ts'],
+ outfile: 'dist/renderer/index.js',
bundle: true,
sourcemap: true,
minify: true,
diff --git a/examples/counter/index.html b/examples/counter/index.html
index 9aa89d2..367aa63 100644
--- a/examples/counter/index.html
+++ b/examples/counter/index.html
@@ -6,6 +6,6 @@
<link href="./style.css" rel="stylesheet" />
</head>
<body>
- <script async defer src="../../dist/index.js"></script>
+ <script async defer src="../../dist/renderer/index.js"></script>
</body>
</html>
diff --git a/examples/form/index.html b/examples/form/index.html
index 618b21b..c7aa321 100644
--- a/examples/form/index.html
+++ b/examples/form/index.html
@@ -6,6 +6,6 @@
<link href="./style.css" rel="stylesheet" />
</head>
<body>
- <script async defer src="../../dist/index.js"></script>
+ <script async defer src="../../dist/renderer/index.js"></script>
</body>
</html>
diff --git a/package.json b/package.json
index 346ce22..f213ad1 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
- "name": "cssx",
+ "name": "@cssx/render",
"version": "0.0.0",
"main": "src/index.ts",
"repository": "__",
"author": "Akshay Nair <phenax5@gmail.com>",
"license": "MIT",
"scripts": {
- "build": "node esbuild.js",
+ "build": "tsc && node esbuild.js",
"serve": "serve -p 3000 .",
"format": "prettier --write './{src,tests}/**/*.{ts,html,css}' './examples/**/*.{html,css}'",
"lint": "eslint ./src",
diff --git a/src/index.ts b/src/index.ts
index 9ca6c4e..1c8184a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,163 @@
-import { render } from './renderer'
+import { EvalActions, evalExpr } from './eval'
+import { parse } from './parser'
-render({ root: document.body })
+const UNSET_PROPERTY_VALUE = '<unset>'
+const EVENT_HANDLERS = {
+ click: '--cssx-on-click',
+ load: '--cssx-on-load',
+ mount: '--cssx-on-mount',
+ submit: '--cssx-on-submit',
+}
+
+const PROPERTIES = [
+ '--cssx-children',
+ '--cssx-text',
+ '--cssx-disgustingly-set-innerhtml',
+]
+
+export const injectStyles = () => {
+ const STYLE_TAG_CLASS = 'cssx-style-root'
+ if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return
+
+ const $style = document.createElement('style')
+ $style.className = STYLE_TAG_CLASS
+
+ const properties = [...PROPERTIES, ...Object.values(EVENT_HANDLERS)]
+
+ $style.textContent = `.cssx-layer {
+ ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')}
+ }`
+
+ document.body.appendChild($style)
+}
+
+export const getPropertyValue = ($element: Element, prop: string) => {
+ const value = `${getComputedStyle($element).getPropertyValue(prop)}`.trim()
+ return !value || value === UNSET_PROPERTY_VALUE ? '' : value
+}
+
+export const getChildrenIds = ($element: Element) => {
+ const value = getPropertyValue($element, '--cssx-children')
+ return value.split(/(\s*,\s*)|\s+/g).filter(Boolean)
+}
+
+const getEvalActions = ($element: Element, event: any): EvalActions => ({
+ addClass: async (id, cls) => document.getElementById(id)?.classList.add(cls),
+ removeClass: async (id, cls) =>
+ document.getElementById(id)?.classList.remove(cls),
+ delay: delay => new Promise(res => setTimeout(res, delay)),
+ jsEval: async js => (0, eval)(js),
+ loadCssx: async (id, url) =>
+ new Promise((resolve, reject) => {
+ const $link = Object.assign(document.createElement('link'), {
+ href: url,
+ rel: 'stylesheet',
+ })
+ $link.onload = () => {
+ const $el = document.getElementById(id)
+ // NOTE: Maybe create and append to body if no root?
+ if ($el) {
+ manageElement($el)
+ resolve(id)
+ } else {
+ console.error(`[CSSX] Unable to find root for ${id}`)
+ reject(`[CSSX] Unable to find root for ${id}`)
+ }
+ }
+ document.body.appendChild($link)
+ }),
+ getVariable: async varName => getPropertyValue($element, varName),
+ updateVariable: async (targetId, varName, value) => {
+ const $el = document.getElementById(targetId)
+ if ($el) {
+ $el.style.setProperty(varName, JSON.stringify(value))
+ }
+ },
+ setAttribute: async (id, name, value) => {
+ const $el = id ? document.getElementById(id) : $element
+ if (value) {
+ $el?.setAttribute(name, value)
+ } else {
+ $el?.removeAttribute(name)
+ }
+ },
+ getAttribute: async (id, name) => {
+ const $el = id ? document.getElementById(id) : $element
+ return $el?.getAttribute(name) ?? undefined
+ },
+ withEvent: async fn => fn(event),
+ getFormData: async () =>
+ $element.nodeName === 'FORM'
+ ? new FormData($element as HTMLFormElement)
+ : undefined,
+ sendRequest: async ({ url, method, data }) => {
+ await fetch(url, { method, body: data })
+ // TODO: Handle response?
+ },
+})
+
+export const handleEvents = async (
+ $element: Element,
+ isNewElement: boolean = false,
+) => {
+ for (const [eventType, property] of Object.entries(EVENT_HANDLERS)) {
+ const handlerExpr = getPropertyValue($element, property)
+
+ if (handlerExpr) {
+ const eventHandler = async (event: any) => {
+ const exprs = parse(handlerExpr)
+ for (const expr of exprs) {
+ await evalExpr(expr, getEvalActions($element, event))
+ }
+ }
+
+ if (eventType === 'mount') {
+ if (isNewElement) setTimeout(eventHandler)
+ } else {
+ ;($element as any)[`on${eventType}`] = eventHandler
+ }
+ }
+ }
+}
+
+export const manageElement = async (
+ $element: Element,
+ isNewElement: boolean = false,
+) => {
+ await handleEvents($element, isNewElement)
+
+ const text = getPropertyValue($element, '--cssx-text')
+ if (text) $element.textContent = text
+
+ const html = getPropertyValue($element, '--cssx-disgustingly-set-innerhtml')
+ if (html) $element.innerHTML = html.replace(/(^'|")|('|"$)/g, '')
+
+ const childrenIds = getChildrenIds($element)
+ if (childrenIds.length > 0) {
+ const LAYER_CLASS = 'cssx-layer'
+ const $childrenRoot =
+ $element.querySelector(`:scope > .${LAYER_CLASS}`) ??
+ Object.assign(document.createElement('div'), { className: LAYER_CLASS })
+ $element.appendChild($childrenRoot)
+
+ for (const childId of childrenIds) {
+ const selector = childId.split('#')
+ const [tag, id] = selector.length >= 2 ? selector : ['div', ...selector]
+ let $child = $childrenRoot.querySelector(`:scope > #${id}`)
+ const isNewElement = !$child
+ if (!$child) {
+ $child = Object.assign(document.createElement(tag || 'div'), { id })
+ }
+ $childrenRoot.appendChild($child)
+ await manageElement($child, isNewElement)
+ }
+ }
+}
+
+export interface Options {
+ root?: HTMLElement
+}
+export const render = async ({ root = document.body }: Options = {}) => {
+ injectStyles()
+ await manageElement(root)
+}
diff --git a/src/renderer.ts b/src/renderer.ts
index 1c8184a..44add3e 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -1,163 +1,3 @@
-import { EvalActions, evalExpr } from './eval'
-import { parse } from './parser'
+import { render } from '.'
-const UNSET_PROPERTY_VALUE = '<unset>'
-const EVENT_HANDLERS = {
- click: '--cssx-on-click',
- load: '--cssx-on-load',
- mount: '--cssx-on-mount',
- submit: '--cssx-on-submit',
-}
-
-const PROPERTIES = [
- '--cssx-children',
- '--cssx-text',
- '--cssx-disgustingly-set-innerhtml',
-]
-
-export const injectStyles = () => {
- const STYLE_TAG_CLASS = 'cssx-style-root'
- if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return
-
- const $style = document.createElement('style')
- $style.className = STYLE_TAG_CLASS
-
- const properties = [...PROPERTIES, ...Object.values(EVENT_HANDLERS)]
-
- $style.textContent = `.cssx-layer {
- ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')}
- }`
-
- document.body.appendChild($style)
-}
-
-export const getPropertyValue = ($element: Element, prop: string) => {
- const value = `${getComputedStyle($element).getPropertyValue(prop)}`.trim()
- return !value || value === UNSET_PROPERTY_VALUE ? '' : value
-}
-
-export const getChildrenIds = ($element: Element) => {
- const value = getPropertyValue($element, '--cssx-children')
- return value.split(/(\s*,\s*)|\s+/g).filter(Boolean)
-}
-
-const getEvalActions = ($element: Element, event: any): EvalActions => ({
- addClass: async (id, cls) => document.getElementById(id)?.classList.add(cls),
- removeClass: async (id, cls) =>
- document.getElementById(id)?.classList.remove(cls),
- delay: delay => new Promise(res => setTimeout(res, delay)),
- jsEval: async js => (0, eval)(js),
- loadCssx: async (id, url) =>
- new Promise((resolve, reject) => {
- const $link = Object.assign(document.createElement('link'), {
- href: url,
- rel: 'stylesheet',
- })
- $link.onload = () => {
- const $el = document.getElementById(id)
- // NOTE: Maybe create and append to body if no root?
- if ($el) {
- manageElement($el)
- resolve(id)
- } else {
- console.error(`[CSSX] Unable to find root for ${id}`)
- reject(`[CSSX] Unable to find root for ${id}`)
- }
- }
- document.body.appendChild($link)
- }),
- getVariable: async varName => getPropertyValue($element, varName),
- updateVariable: async (targetId, varName, value) => {
- const $el = document.getElementById(targetId)
- if ($el) {
- $el.style.setProperty(varName, JSON.stringify(value))
- }
- },
- setAttribute: async (id, name, value) => {
- const $el = id ? document.getElementById(id) : $element
- if (value) {
- $el?.setAttribute(name, value)
- } else {
- $el?.removeAttribute(name)
- }
- },
- getAttribute: async (id, name) => {
- const $el = id ? document.getElementById(id) : $element
- return $el?.getAttribute(name) ?? undefined
- },
- withEvent: async fn => fn(event),
- getFormData: async () =>
- $element.nodeName === 'FORM'
- ? new FormData($element as HTMLFormElement)
- : undefined,
- sendRequest: async ({ url, method, data }) => {
- await fetch(url, { method, body: data })
- // TODO: Handle response?
- },
-})
-
-export const handleEvents = async (
- $element: Element,
- isNewElement: boolean = false,
-) => {
- for (const [eventType, property] of Object.entries(EVENT_HANDLERS)) {
- const handlerExpr = getPropertyValue($element, property)
-
- if (handlerExpr) {
- const eventHandler = async (event: any) => {
- const exprs = parse(handlerExpr)
- for (const expr of exprs) {
- await evalExpr(expr, getEvalActions($element, event))
- }
- }
-
- if (eventType === 'mount') {
- if (isNewElement) setTimeout(eventHandler)
- } else {
- ;($element as any)[`on${eventType}`] = eventHandler
- }
- }
- }
-}
-
-export const manageElement = async (
- $element: Element,
- isNewElement: boolean = false,
-) => {
- await handleEvents($element, isNewElement)
-
- const text = getPropertyValue($element, '--cssx-text')
- if (text) $element.textContent = text
-
- const html = getPropertyValue($element, '--cssx-disgustingly-set-innerhtml')
- if (html) $element.innerHTML = html.replace(/(^'|")|('|"$)/g, '')
-
- const childrenIds = getChildrenIds($element)
- if (childrenIds.length > 0) {
- const LAYER_CLASS = 'cssx-layer'
- const $childrenRoot =
- $element.querySelector(`:scope > .${LAYER_CLASS}`) ??
- Object.assign(document.createElement('div'), { className: LAYER_CLASS })
- $element.appendChild($childrenRoot)
-
- for (const childId of childrenIds) {
- const selector = childId.split('#')
- const [tag, id] = selector.length >= 2 ? selector : ['div', ...selector]
- let $child = $childrenRoot.querySelector(`:scope > #${id}`)
- const isNewElement = !$child
- if (!$child) {
- $child = Object.assign(document.createElement(tag || 'div'), { id })
- }
- $childrenRoot.appendChild($child)
- await manageElement($child, isNewElement)
- }
- }
-}
-
-export interface Options {
- root?: HTMLElement
-}
-export const render = async ({ root = document.body }: Options = {}) => {
- injectStyles()
- await manageElement(root)
-}
+render({ root: document.body })
diff --git a/tests/signup.spec.ts b/tests/signup.spec.ts
index beede57..43cc33a 100644
--- a/tests/signup.spec.ts
+++ b/tests/signup.spec.ts
@@ -7,7 +7,7 @@ import {
import { readFile } from 'node:fs/promises'
import '@testing-library/jest-dom'
-import { render } from '../src/renderer'
+import { render } from '../src'
async function loadFixture(type: string) {
document.documentElement.innerHTML = await readFile(
diff --git a/tsconfig.json b/tsconfig.json
index 8e6bafd..6702f72 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,7 +6,8 @@
"skipLibCheck": true,
"outDir": "dist",
"incremental": true,
- "noEmit": true,
+ "noEmit": false,
+ "declaration": true,
"esModuleInterop": true,
"moduleResolution": "bundler",