mirror of
https://github.com/MercuryWorkshop/dreamlandjs.git
synced 2025-05-15 15:10:02 -04:00
rewrite build system and bundles
This commit is contained in:
parent
f6367de472
commit
e79b184f41
10 changed files with 291 additions and 110 deletions
95
dreamland.d.ts
vendored
Normal file
95
dreamland.d.ts
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
declare namespace JSX {
|
||||
export type IntrinsicElements = {
|
||||
[index: string]: any
|
||||
}
|
||||
type ElementType = Fragment | string | Component<any, any>
|
||||
type Element = DLElement<any>
|
||||
|
||||
interface ElementAttributesProperty {
|
||||
props: {}
|
||||
}
|
||||
interface ElementChildrenAttribute {
|
||||
children: {}
|
||||
}
|
||||
}
|
||||
|
||||
declare function h(
|
||||
type: string,
|
||||
props?: { [index: string]: any } | null,
|
||||
...children: (HTMLElement | string)[]
|
||||
): Node
|
||||
declare function $if(
|
||||
condition: DLPointer<any> | any,
|
||||
then?: Element,
|
||||
otherwise?: Element
|
||||
): HTMLElement
|
||||
|
||||
type DLPointer<T> = {
|
||||
readonly __symbol: unique symbol
|
||||
readonly __signature: T
|
||||
}
|
||||
|
||||
declare function use<T>(sink: T, mapping?: (arg: T) => any): DLPointer<T>
|
||||
declare function useValue<T>(trap: DLPointer<T>): T
|
||||
|
||||
type Stateful<T> = T & { readonly symbol: unique symbol }
|
||||
|
||||
declare function stateful<T>(target: T): Stateful<T>
|
||||
declare function $state<T>(target: T): Stateful<T>
|
||||
declare function $store<T>(
|
||||
target: T,
|
||||
ident: string,
|
||||
backing: 'localstorage'
|
||||
): Stateful<T>
|
||||
|
||||
declare function handle<T>(
|
||||
references: DLPointer<T>,
|
||||
callback: (value: T) => void
|
||||
): void
|
||||
|
||||
declare function css(strings: TemplateStringsArray, ...values: any): string
|
||||
|
||||
type DLCSS = string
|
||||
|
||||
declare var $el: HTMLElement
|
||||
|
||||
type Fragment = { readonly fragment: unique symbol }
|
||||
declare var Fragment: Fragment
|
||||
|
||||
interface Element {
|
||||
$: OuterComponentTypes & { [index: string | symbol]: any }
|
||||
}
|
||||
|
||||
interface DLElement<T> extends HTMLElement {
|
||||
$: T & OuterComponentTypes
|
||||
}
|
||||
|
||||
type ComponentElement<T extends (...args: any) => any> = ReturnType<T>
|
||||
|
||||
type OuterComponentTypes = {
|
||||
root: Element
|
||||
children: Element[]
|
||||
}
|
||||
type InnerComponentTypes = {
|
||||
css: DLCSS
|
||||
mount?: () => void
|
||||
}
|
||||
type ComponentTypes = OuterComponentTypes & InnerComponentTypes
|
||||
|
||||
type ArrayOrSingular<T extends []> = T | T[keyof T]
|
||||
|
||||
type Component<
|
||||
Public,
|
||||
Private,
|
||||
Constructed extends string | symbol | number = never,
|
||||
> = (
|
||||
this: Public & Private & ComponentTypes,
|
||||
props: ([Constructed] extends [never]
|
||||
? Public
|
||||
: Omit<Public, Constructed>) & {
|
||||
children?: ArrayOrSingular<
|
||||
Private extends { children: any } ? Private['children'] : never
|
||||
>
|
||||
[index: `${'bind:'}${string}`]: any
|
||||
}
|
||||
) => DLElement<Public>
|
28
package.json
28
package.json
|
@ -3,8 +3,7 @@
|
|||
"version": "0.0.6",
|
||||
"description": "A utilitarian HTML rendering library",
|
||||
"scripts": {
|
||||
"build": "rollup -c && prettier -w .",
|
||||
"watch": "rollup -cw",
|
||||
"build": "rollup -c --dloutput dist/minimal.js --disable-css --disable-jsxLiterals --disable-usestring --disable-stores && rollup -c --dloutput dist/dev.js --dev --enable-css --enable-jsxLiterals --enable-usestring --enable-stores && rollup -c --dloutput dist/all.js --enable-css --enable-jsxLiterals --enable-usestring --enable-stores && prettier -w .",
|
||||
"publish": "npm publish --access public"
|
||||
},
|
||||
"keywords": [
|
||||
|
@ -17,28 +16,20 @@
|
|||
"author": "MercuryWorkshop",
|
||||
"repository": "https://github.com/MercuryWorkshop/dreamlandjs",
|
||||
"license": "MIT",
|
||||
"browser": "./dist/dev/index.js",
|
||||
"browser": "./dist/all.js",
|
||||
"types": "./dreamland.d.ts",
|
||||
"node": "./dist/dev/index.js",
|
||||
"node": "./dist/all.js",
|
||||
"exports": {
|
||||
"./dev": {
|
||||
"default": "./dist/dev/index.js",
|
||||
"default": "./dist/dev.js",
|
||||
"types": "./dreamland.d.ts"
|
||||
},
|
||||
"./js": {
|
||||
"default": "./dist/js.js",
|
||||
"./minimal": {
|
||||
"default": "./dist/minimal.js",
|
||||
"types": "./dreamland.d.ts"
|
||||
},
|
||||
"./css": {
|
||||
"default": "./dist/css.js",
|
||||
"types": "./dreamland.d.ts"
|
||||
},
|
||||
"./html": {
|
||||
"default": "./dist/html.js",
|
||||
"types": "./dreamland.d.ts"
|
||||
},
|
||||
"./store": {
|
||||
"default": "./dist/store.js",
|
||||
".": {
|
||||
"default": "./dist/all.js",
|
||||
"types": "./dreamland.d.ts"
|
||||
}
|
||||
},
|
||||
|
@ -52,5 +43,8 @@
|
|||
"prettier": "^3.2.5",
|
||||
"rollup": "^4.13.0",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"rollup-plugin-strip-code": "^0.2.7"
|
||||
}
|
||||
}
|
||||
|
|
33
pnpm-lock.yaml
generated
33
pnpm-lock.yaml
generated
|
@ -4,6 +4,11 @@ settings:
|
|||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
rollup-plugin-strip-code:
|
||||
specifier: ^0.2.7
|
||||
version: 0.2.7
|
||||
|
||||
devDependencies:
|
||||
'@rollup/plugin-strip':
|
||||
specifier: ^3.0.4
|
||||
|
@ -227,6 +232,10 @@ packages:
|
|||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
dev: true
|
||||
|
||||
/estree-walker@0.6.1:
|
||||
resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==}
|
||||
dev: false
|
||||
|
||||
/estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
|
@ -239,6 +248,12 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/magic-string@0.25.3:
|
||||
resolution: {integrity: sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==}
|
||||
dependencies:
|
||||
sourcemap-codec: 1.4.8
|
||||
dev: false
|
||||
|
||||
/magic-string@0.30.8:
|
||||
resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -263,6 +278,19 @@ packages:
|
|||
safe-buffer: 5.2.1
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-strip-code@0.2.7:
|
||||
resolution: {integrity: sha512-+5t9u/VrHPSfiRWWKMVin+KOtFwFak337FAZxeTjxYDjB3DDoHBQRkXHQvBn713eAfW81t41mGuysqsMXiuTjw==}
|
||||
dependencies:
|
||||
magic-string: 0.25.3
|
||||
rollup-pluginutils: 2.8.1
|
||||
dev: false
|
||||
|
||||
/rollup-pluginutils@2.8.1:
|
||||
resolution: {integrity: sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==}
|
||||
dependencies:
|
||||
estree-walker: 0.6.1
|
||||
dev: false
|
||||
|
||||
/rollup@4.13.0:
|
||||
resolution: {integrity: sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
|
@ -312,6 +340,11 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/sourcemap-codec@1.4.8:
|
||||
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
||||
deprecated: Please use @jridgewell/sourcemap-codec instead
|
||||
dev: false
|
||||
|
||||
/terser@5.29.2:
|
||||
resolution: {integrity: sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==}
|
||||
engines: {node: '>=10'}
|
||||
|
|
|
@ -1,74 +1,118 @@
|
|||
import strip from '@rollup/plugin-strip'
|
||||
import terser from '@rollup/plugin-terser'
|
||||
import stripCode from 'rollup-plugin-strip-code'
|
||||
|
||||
const prodPlugins = [
|
||||
strip({
|
||||
functions: ['console.log', 'assert.*', 'panic', 'log'],
|
||||
labels: ['dev'],
|
||||
}),
|
||||
terser({
|
||||
mangle: {
|
||||
toplevel: true,
|
||||
export default (args) => {
|
||||
const plugins = []
|
||||
|
||||
const stripfunctions = []
|
||||
|
||||
if (!args.dev) {
|
||||
stripfunctions.push('console.log', 'assert.*', 'panic', 'log')
|
||||
}
|
||||
|
||||
plugins.push(
|
||||
strip({
|
||||
functions: stripfunctions,
|
||||
sourceMap: true,
|
||||
})
|
||||
)
|
||||
|
||||
if (!args.dev) {
|
||||
plugins.push(
|
||||
stripCode({
|
||||
start_comment: 'DEV.START',
|
||||
end_comment: 'DEV.END',
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const features = {
|
||||
css: true,
|
||||
jsxLiterals: false,
|
||||
usestring: false,
|
||||
stores: false,
|
||||
}
|
||||
|
||||
for (const arg in args) {
|
||||
if (arg.startsWith('disable-')) {
|
||||
const feature = arg.slice(8)
|
||||
features[feature] = false
|
||||
}
|
||||
if (arg.startsWith('enable-')) {
|
||||
const feature = arg.slice(7)
|
||||
features[feature] = true
|
||||
}
|
||||
}
|
||||
|
||||
for (const [feature, enabled] of Object.entries(features)) {
|
||||
if (!enabled) {
|
||||
plugins.push(
|
||||
stripCode({
|
||||
start_comment: `FEATURE.${feature.toUpperCase()}.START`,
|
||||
end_comment: `FEATURE.${feature.toUpperCase()}.END`,
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const dlbanner = `// dreamland.js, MIT license\nconst DLFEATURES = [${Object.entries(
|
||||
features
|
||||
)
|
||||
.filter(([_, enabled]) => enabled)
|
||||
.map(([feature, _]) => `'${feature}'`)
|
||||
.join(', ')}];`
|
||||
if (args.dev || args.nominify) {
|
||||
plugins.push({
|
||||
banner() {
|
||||
return dlbanner
|
||||
},
|
||||
})
|
||||
} else {
|
||||
plugins.push(
|
||||
terser({
|
||||
mangle: {
|
||||
toplevel: true,
|
||||
},
|
||||
compress: {
|
||||
unused: true,
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
preamble: dlbanner,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const sharedOutput = {}
|
||||
|
||||
const iifeOutput = {
|
||||
format: 'iife',
|
||||
name: 'window',
|
||||
extend: true,
|
||||
sourcemap: true,
|
||||
...sharedOutput,
|
||||
}
|
||||
|
||||
const devOutput = {
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
...sharedOutput,
|
||||
}
|
||||
|
||||
const output = args.dev ? devOutput : iifeOutput
|
||||
|
||||
return [
|
||||
{
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
file: args.dloutput,
|
||||
...output,
|
||||
},
|
||||
plugins: plugins,
|
||||
},
|
||||
compress: {
|
||||
unused: true,
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
},
|
||||
output: {
|
||||
comments: false,
|
||||
},
|
||||
}),
|
||||
]
|
||||
const devPlugins = []
|
||||
export default [
|
||||
{
|
||||
input: 'src/dev.js',
|
||||
output: {
|
||||
file: 'dist/dev/index.js',
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: devPlugins,
|
||||
},
|
||||
{
|
||||
input: 'src/js.js',
|
||||
output: {
|
||||
file: 'dist/js.js',
|
||||
strict: false,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: prodPlugins,
|
||||
},
|
||||
{
|
||||
input: 'src/css.js',
|
||||
output: {
|
||||
file: 'dist/css.js',
|
||||
strict: false,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: prodPlugins,
|
||||
},
|
||||
{
|
||||
input: 'src/html.js',
|
||||
output: {
|
||||
file: 'dist/html.js',
|
||||
strict: false,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: prodPlugins,
|
||||
},
|
||||
{
|
||||
input: 'src/store.js',
|
||||
output: {
|
||||
file: 'dist/store.js',
|
||||
strict: false,
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
},
|
||||
plugins: prodPlugins,
|
||||
},
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -33,7 +33,9 @@ Object.defineProperty(window, 'use', {
|
|||
get: () => {
|
||||
__use_trap = true
|
||||
return (ptr, mapping, ...rest) => {
|
||||
/* FEATURE.USESTRING.START */
|
||||
if (ptr instanceof Array) return usestr(ptr, mapping, ...rest)
|
||||
/* FEATURE.USESTRING.END */
|
||||
assert(
|
||||
isDLPtr(ptr),
|
||||
'a value was passed into use() that was not part of a stateful context'
|
||||
|
@ -44,6 +46,8 @@ Object.defineProperty(window, 'use', {
|
|||
}
|
||||
},
|
||||
})
|
||||
|
||||
/* FEATURE.USESTRING.START */
|
||||
const usestr = (strings, ...values) => {
|
||||
__use_trap = false
|
||||
|
||||
|
@ -73,14 +77,14 @@ const usestr = (strings, ...values) => {
|
|||
|
||||
return use(state.string)
|
||||
}
|
||||
Object.assign(window, { isDLPtr, h, stateful, handle, $if, Fragment })
|
||||
/* FEATURE.USESTRING.END */
|
||||
|
||||
let TRAPS = new Map()
|
||||
// This wraps the target in a proxy, doing 2 things:
|
||||
// - whenever a property is accessed, return a "trap" that catches and records accessors
|
||||
// - whenever a property is set, notify the subscribed listeners
|
||||
// This is what makes our "pass-by-reference" magic work
|
||||
function stateful(target, hook) {
|
||||
export function stateful(target, hook) {
|
||||
assert(isobj(target), 'stateful() requires an object')
|
||||
target[LISTENERS] = []
|
||||
target[TARGET] = target
|
||||
|
@ -136,11 +140,11 @@ function stateful(target, hook) {
|
|||
|
||||
let isobj = (o) => o instanceof Object
|
||||
let isfn = (o) => typeof o === 'function'
|
||||
function isDLPtr(arr) {
|
||||
export function isDLPtr(arr) {
|
||||
return isobj(arr) && TARGET in arr
|
||||
}
|
||||
|
||||
function $if(condition, then, otherwise) {
|
||||
export function $if(condition, then, otherwise) {
|
||||
otherwise ??= document.createTextNode('')
|
||||
if (!isDLPtr(condition)) return condition ? then : otherwise
|
||||
|
||||
|
@ -148,7 +152,7 @@ function $if(condition, then, otherwise) {
|
|||
}
|
||||
|
||||
// This lets you subscribe to a stateful object
|
||||
function handle(ptr, callback) {
|
||||
export function handle(ptr, callback) {
|
||||
assert(isDLPtr(ptr), 'handle() requires a stateful object')
|
||||
assert(isfn(callback), 'handle() requires a callback function')
|
||||
let step,
|
||||
|
@ -239,7 +243,7 @@ let curryset = (ptr) => (val) => {
|
|||
}
|
||||
|
||||
// Actual JSX factory. Responsible for creating the HTML elements and all of the *reactive* syntactic sugar
|
||||
function h(type, props, ...children) {
|
||||
export function h(type, props, ...children) {
|
||||
if (type == Fragment) return children
|
||||
if (typeof type == 'function') {
|
||||
// functional components. create the stateful object
|
|
@ -1,4 +1,3 @@
|
|||
Object.assign(window, { css, styled: { new: css, rule: css } })
|
||||
const cssmap = {}
|
||||
|
||||
export function css(strings, ...values) {
|
||||
|
|
12
src/dev.js
12
src/dev.js
|
@ -1,12 +0,0 @@
|
|||
import { log } from './asserts'
|
||||
import { VERSION } from './consts'
|
||||
|
||||
import './js'
|
||||
import './css'
|
||||
import './html'
|
||||
import './store'
|
||||
|
||||
log('Version: ' + VERSION)
|
||||
console.warn(
|
||||
'This is a DEVELOPER build of dreamland.js. It is not suitable for production use.'
|
||||
)
|
|
@ -1,5 +1,4 @@
|
|||
Object.assign(window, { html })
|
||||
function html(strings, ...values) {
|
||||
export function html(strings, ...values) {
|
||||
let flattened = ''
|
||||
let markers = {}
|
||||
for (const i in strings) {
|
26
src/main.js
Normal file
26
src/main.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { VERSION } from './consts'
|
||||
export { VERSION as DLVERSION }
|
||||
|
||||
export * from './core'
|
||||
|
||||
/* FEATURE.CSS.START */
|
||||
export * from './css'
|
||||
/* FEATURE.CSS.END */
|
||||
|
||||
/* FEATURE.JSXLITERALS.START */
|
||||
export * from './jsxLiterals'
|
||||
/* FEATURE.JSXLITERALS.END */
|
||||
|
||||
/* FEATURE.STORES.START */
|
||||
export * from './stores'
|
||||
/* FEATURE.STORES.END */
|
||||
|
||||
/* DEV.START */
|
||||
import { log } from './asserts'
|
||||
|
||||
log('Version: ' + VERSION)
|
||||
console.warn(
|
||||
'This is a DEVELOPER build of dreamland.js. It is not suitable for production use.'
|
||||
)
|
||||
console.info('Enabled features:', DLFEATURES.join(', '))
|
||||
/* DEV.END */
|
|
@ -1,5 +1,4 @@
|
|||
Object.assign(window, { $store })
|
||||
function $store(target, ident, type) {
|
||||
export function $store(target, ident, type) {
|
||||
let stored = localStorage.getItem(ident)
|
||||
target = JSON.parse(stored) ?? target
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue