Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

nuekit

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nuekit - npm Package Compare versions

Comparing version 0.1.8 to 0.2.0

test/nuekit.test.js

11

package.json
{
"name": "nuekit",
"version": "0.1.8",
"description": "The Nue framework for building websites and webapps",
"version": "0.2.0",
"description": "The closer-to-standards web framework. Build sites and apps with less effort.",
"homepage": "https://nuejs.org",

@@ -22,8 +22,5 @@ "license": "MIT",

"js-yaml": "^4.1.0",
"marked": "^9.1.6",
"nuejs-core": "^0.3.0"
"nuejs-core": "^0.3.0",
"nuemark": "^0.1.0"
},
"devDependencies": {
"esbuild": "^0.19.11"
},
"engines": {

@@ -30,0 +27,0 @@ "bun": ">= 1",

@@ -17,5 +17,5 @@

- [Improved development experience](https://nuejs.org/docs/why-nue/developer-experience.html)
- [Standards-based development model](https://nuejs.org/docs/why-nue/closer-to-standards.html)
- [Improved website performance](https://nuejs.org/docs/why-nue/website-performance.html)
- [Content first](https://nuejs.org/docs/why-nue/content-first.html)
- [Extreme performance](https://nuejs.org/docs/why-nue/extreme-performance.html)
- [Closer to standards](https://nuejs.org/docs/why-nue/closer-to-standards.html)

@@ -33,5 +33,5 @@ #### Notable features

### Roadmap
The ultimate goal of Nue is to create a simpler and more powerful alternative to **Vercel**, **Gatsby**, and **Netlify**.
The ultimate goal of Nue is to build a content first alternative to **Vercel** and **Netlify**, which is extremely fast and ridiculously easy to use.
![Nue Roadmap](https://nuejs.org/img/roadmap3-big.png)
![Nue Roadmap](https://nuejs.org/img/roadmap4-big.png)

@@ -38,0 +38,0 @@

/* Builders for CSS, JS, and TS */
import { join, extname } from 'node:path'

@@ -72,2 +74,75 @@

const not_found = {}
export async function findModule(name, path='') {
if (not_found[name]) return
const attempts = [
join(process.cwd(), 'node_modules', name, path),
join(process.cwd(), '..', 'node_modules', name, path),
name,
]
for (const path of attempts) {
try {
return await import(path)
} catch {}
}
not_found[name] = true
}
export async function buildCSS({ css, ext, minify }) {
// stylus
if (ext == '.styl') {
const stylus = await findModule('stylus')
if (!stylus) throw 'Module not found: "stylus"'
try {
process.stdout.write('🖌️')
return stylus.render(css, { compress: minify })
} catch({ message, stack }) {
const [l, col] = message.slice(7, message.indexOf('\n')).split(':')
throw {
title: 'Stylus syntax error',
text: stack.split('\n')[0],
lineText: css.split('\n')[l -1],
column: 1 * col,
line: 1 * l,
}
}
}
// Nue CSS (not public yet)
if (ext == '.style') {
const nuecss = await import('nuecss')
return nuecss.default(css, { minify })
}
const mod = await findModule('lightningcss', 'node/index.mjs')
// Standard CSS
if (!mod) return minify ? minifyCSS(css) : css
// Lightning CSS
process.stdout.write('⚡️')
try {
const include = mod.Features.Colors | mod.Features.Nesting
return mod.transform({ code: Buffer.from(css), include, minify }).code?.toString()
} catch({ source, loc, data}) {
throw {
title: 'CSS syntax error',
lineText: source.split('\n')[loc.line -1],
text: data.type,
...loc
}
}
}
// temporary hack, until Bun does this natively

@@ -74,0 +149,0 @@ export function minifyCSS(code) {

@@ -27,3 +27,3 @@ #!/usr/bin/env bun

// skip
if (arg.endsWith('/cli.js') || arg == '--') {
if (arg.endsWith('/cli.js') || arg.endsWith('/nue') || arg == '--') {

@@ -69,3 +69,4 @@ // test suite

const { promises } = await import('fs')
const path = new URL('../package.json', import.meta.url).pathname
const pathname = new URL('../package.json', import.meta.url).pathname
const path = process.platform === "win32" && pathname.startsWith('/') ? pathname.slice(1) : pathname
const json = await promises.readFile(path, 'utf-8')

@@ -72,0 +73,0 @@ return JSON.parse(json).version

@@ -13,3 +13,4 @@

const cwd = process.cwd()
const srcdir = new URL('.', import.meta.url).pathname
const pathname = new URL('.', import.meta.url).pathname
const srcdir = process.platform === "win32" && pathname.startsWith('/') ? pathname.slice(1) : pathname
const fromdir = join(srcdir, 'browser')

@@ -21,3 +22,3 @@ const outdir = join(cwd, dist, '@nue')

// has all latest?
const latest = join(outdir, '.016')
const latest = join(outdir, '.020')
try {

@@ -27,3 +28,3 @@ return await fs.stat(latest)

} catch {
await fs.rmdir(outdir, { recursive: true })
await fs.rm(outdir, { recursive: true, force: true })
await fs.mkdir(outdir, { recursive: true })

@@ -70,5 +71,4 @@ await fs.writeFile(latest, '')

await buildPackage('nuemark', 'nuemark.js')
await buildPackage('nuejs-core', 'nue.js')
await buildPackage('diff-dom', 'diffdom.js')
await buildFile('page-router')

@@ -80,2 +80,3 @@ await buildFile('app-router')

if (is_dev) {
await buildPackage('diff-dom', 'diffdom.js')
await buildFile('hotreload')

@@ -82,0 +83,0 @@ await copy('error.css', outdir)

@@ -61,3 +61,3 @@ import { extname } from 'node:path'

// inline style
inline_css.forEach(css => head.push(`<style href="${base}${css.path}">${ css.content }</style>`))
inline_css.forEach(el => head.push(`<style href="${base}${el.path}">${ el.css }</style>`))

@@ -64,0 +64,0 @@ // stylesheets

@@ -38,3 +38,3 @@

if (e.errno == -2) await onremove(path)
else console.info(e)
else console.error(e)
}

@@ -48,3 +48,3 @@ })

for (const f of files) {
if (!ignore(f.name[0])) {
if (!ignore(f.name)) {
const path = join(_dir, f.name)

@@ -59,4 +59,6 @@ if (isDir(f)) await fswalk(root, path, _ret)

const IGNORE = ['node_modules', 'package.json', 'bun.lockb', 'pnpm-lock.yaml']
function ignore(name) {
return '._'.includes(name[0])
return '._'.includes(name[0]) || IGNORE.includes(name)
}

@@ -63,0 +65,0 @@

import { parse as parseNue, compile as compileNue } from 'nuejs-core/index.js'
import { log, colors, parseMarkdown, getAppDir, getParts } from './util.js'
import { join, parse as parsePath, extname, basename } from 'node:path'
import { renderHead, getDefaultHTML, getDefaultSPA } from './layout.js'
import { join, parse as parsePath, extname } from 'node:path'
import { readStats, printTable, categorize } from './stats.js'
import { log, colors, getAppDir, getParts } from './util.js'
import { parsePage, renderPage } from 'nuemark/index.js'
import { createServer, send } from './nueserver.js'
import { minifyCSS, buildJS } from './builder.js'
import { buildCSS, buildJS } from './builder.js'
import { promises as fs } from 'node:fs'

@@ -37,4 +38,7 @@ import { createSite } from './site.js'

// alphabtical order
paths.sort()
if (data.inline_css) {
data.inline_css = await readAllCSS(paths)
data.inline_css = await buildAllCSS(paths)

@@ -49,2 +53,11 @@ // prefetch global CSS

async function buildAllCSS(paths) {
const arr = []
for (const path of paths) {
const { css } = await processStyle({ path, ...parsePath(path)})
arr.push({ path, css })
}
return arr
}
async function setupScripts(dir, data) {

@@ -66,2 +79,3 @@

if (is_dev && !data.no_hotreload) push('hotreload')
if (data.page?.isomorphic) push('nuemark')
if (data.components?.length) push('mount')

@@ -73,11 +87,14 @@ }

const { dir } = parsePath(path)
const data = await site.getData(dir)
// markdown
const raw = await read(path)
const { meta, content } = parseMarkdown(raw)
const file = parsePath(path)
const dir = meta.appdir || file.dir || '.'
// { meta, sections, headings, links }
const page = parsePage(raw, data)
const { meta } = page
// YAML data
const data = { ...await site.getData(dir), content, ...getParts(path), ...meta }
Object.assign(data, getParts(path), meta, { page })

@@ -92,4 +109,5 @@ // content collection

// scripts & styling
await setupScripts(dir, data)
await setupStyles(dir, data)
const asset_dir = meta.appdir || dir
await setupScripts(asset_dir, data)
await setupStyles(asset_dir, data)

@@ -103,6 +121,6 @@ return data

// data
const file = parsePath(index_path)
const dir = file.dir
const appdir = getAppDir(index_path)
const data = { ...await site.getData(appdir), ...getParts(index_path), is_spa: true }
const file = parsePath(index_path)
const dir = file.dir || '.'

@@ -129,8 +147,12 @@ // scripts & styling

// Markdown- based multi-page application page
async function renderPage(path, data) {
const appdir = data.appdir || getAppDir(path)
const lib = await site.getLayoutComponents(appdir)
async function renderMPA(path, data) {
const file = parsePath(path)
const dir = data.appdir || file.dir
const lib = await site.getLayoutComponents(dir)
data.content = renderPage(data.page, { data, lib }).html
function render(name, def) {
const layout = lib.find(el => el.tagName == name) || def && parseNue(def)[0]
try {

@@ -155,6 +177,7 @@ return layout ? layout.render(data, lib) : ''

async function writePage(file) {
// processor methods
async function processPage(file) {
const { dir, name, path } = file
const data = await getPageData(path)
const html = await renderPage(path, data)
const html = await renderMPA(path, data)
await write(html, dir, `${name}.html`)

@@ -164,18 +187,3 @@ return html

async function renderNueCSS(path) {
const nuecss = await import('nuecss')
const raw = await read(path)
return nuecss.default(raw, { minify: is_prod })
}
async function readAllCSS(paths) {
const arr = []
for (const path of paths) {
const content = extname(path) == '.css' ? await read(path) : await renderNueCSS(path)
arr.push({ path, content })
}
return arr
}
async function processScript(file) {

@@ -188,4 +196,4 @@ const { path } = file

await buildJS({
outdir: join(dist, file.dir),
path: join('.', root, path),
outdir: join(process.cwd(), dist, file.dir),
path: join(process.cwd(), root, path),
minify: is_prod,

@@ -198,3 +206,10 @@ bundle

async function processStyle({ path, ext, name, dir}) {
const raw = await read(path)
const css = await buildCSS({ css: raw, ext, minify: is_prod })
await write(css, dir, `${name}.css`)
return { css }
}
// the page user is currently working on

@@ -216,3 +231,3 @@ let active_page

if (file.is_md) {
const html = await writePage(file)
const html = await processPage(file)
active_page = file

@@ -233,21 +248,6 @@ return { html }

// Nue CSS (not official yet)
if (file.is_style) {
const css = await renderNueCSS(path)
await write(css, dir, `${name}.css`)
return { css }
}
// style
const is_style = ['.css', '.styl', '.style'].includes(ext)
if (is_style) return await processStyle(file)
// Plain CSS
if (file.is_css) {
const css = await read(path)
// production -> minify
if (is_prod) return await write(minifyCSS(css), dir, base)
// development -> return for hot-reload
await copy(file)
return { css }
}
// reactive component

@@ -281,3 +281,4 @@ if (file.is_nue) {

async function gen(path, is_bulk) {
await processFile({ path, ...parsePath(path) }, is_bulk)
const page = await processFile({ path, ...parsePath(path) }, is_bulk)
return page?.html
}

@@ -344,4 +345,4 @@

} catch (e) {
send({ error: e, ...file })
console.error(e)
send({ error: e, ...file })
}

@@ -357,6 +358,11 @@

// server.once('error', e => { if (e.code == 'EADDRINUSE') {} })
try {
server.listen(port)
log(`http://localhost:${port}/`)
server.listen(port)
log(`http://localhost:${port}/`)
} catch (e) {
if (e.code != 'EADDRINUSE') console.error(e)
log.error(e.message, '\n')
process.exit()
}
}

@@ -373,3 +379,3 @@

// for testing only
gen, getPageData, renderPage, renderSPA,
gen, getPageData, renderMPA, renderSPA,

@@ -376,0 +382,0 @@ // public API

import { log, parseMarkdown, getParts, getAppDir, getDirs, colors } from './util.js'
import { join, extname, basename, sep, parse as parsePath } from 'node:path'
import { log, getParts, getAppDir, getDirs, colors } from './util.js'
import { parse as parseNue } from 'nuejs-core/index.js'
import { nuemark } from 'nuemark/index.js'
import { promises as fs } from 'node:fs'

@@ -12,2 +13,4 @@ import { fswalk } from './nuefs.js'

const NOT_FOUND = -2
// file not found error code in windows
const ENOENT = -4058

@@ -42,3 +45,3 @@ export async function createSite(args) {

} catch (e) {
if (e.errno != NOT_FOUND) {
if (e.errno != NOT_FOUND && e.errno != ENOENT) {
throw `YAML parse error in ${path}`

@@ -78,3 +81,2 @@ } else if (path == env) throw e

async function write(content, dir, filename) {

@@ -90,3 +92,3 @@ const todir = join(dist, dir)

} catch (e) {
if (e.errno != NOT_FOUND) throw e
if (e.errno != NOT_FOUND && e.errno != ENOENT) throw e
await fs.mkdir(todir, { recursive: true })

@@ -106,3 +108,3 @@ return await write(content, dir, filename)

} catch (e) {
if (e.errno != NOT_FOUND) throw e
if (e.errno != NOT_FOUND && e.errno != ENOENT) throw e
await fs.mkdir(join(dist, dir), { recursive: true })

@@ -115,3 +117,3 @@ await copy(file)

async function getAssets(dir, exts, to_ext) {
const dirs = [...self.globals, ...getDirs(dir)]
const dirs = [...self.globals, ...getDirs(dir || '.')]
const key = ':' + dir + exts

@@ -136,3 +138,3 @@ const arr = []

} catch (e) {
if (e.errno != NOT_FOUND) return console.error(e)
if (e.errno != NOT_FOUND && e.errno != ENOENT) return console.error(e)
}

@@ -155,7 +157,8 @@ }

self.getData = async function (appdir) {
if (!appdir || appdir == '.') return site_data
const app_data = await readData(`${appdir}/app.yaml`)
return { ...site_data, ...app_data }
self.getData = async function (pagedir) {
const data = { ...site_data }
for (const dir of getDirs(pagedir)) {
Object.assign(data, await readData(`${dir}/app.yaml`))
}
return data
}

@@ -173,14 +176,13 @@

// get fromt matter data from all .md files on a directory
self.getContentCollection = async function (appdir) {
const key = 'coll:' + appdir
self.getContentCollection = async function (dir) {
const key = 'coll:' + dir
if (cache[key]) return cache[key]
const paths = await fswalk(join(root, dir))
const mds = paths.filter(el => el.endsWith('.md')).map(el => join(dir, el))
const paths = await fswalk(join(root, appdir))
const mds = paths.filter(el => el.endsWith('.md')).map(el => join(appdir, el))
const arr = []
for (const path of mds) {
const raw = await read(path)
const meta = parseMarkdown(raw, true)
const { meta } = nuemark(raw)
arr.push({ ...meta, ...getParts(path) })

@@ -199,14 +201,12 @@ }

self.getLayoutComponents = async function (appdir) {
const dirs = ['.']
if (appdir && appdir != '.') dirs.unshift(appdir)
self.getLayoutComponents = async function (pagedir) {
const lib = []
for (const dir of dirs) {
for (const dir of ['.', ...getDirs(pagedir)]) {
const path = join(dir, `layout.html`)
try {
const html = await read(path)
lib.push(...parseNue(html))
lib.unshift(...parseNue(html))
} catch (e) {
if (e.errno != NOT_FOUND) {
if (e.errno != NOT_FOUND && e.errno != ENOENT) {
log.error('parse error', path)

@@ -251,2 +251,1 @@ console.error(e)

}
/* misc stuff. think shame.css */
import { sep, parse } from 'node:path'
import { marked } from 'marked'
import yaml from 'js-yaml'
// .md stuff will be lot cooler with Nuemark
export function parseMarkdown(raw, meta_only) {
const [_, front, md] = raw.split(/---+\n/)
const matter = front?.endsWith('---') ? front.slice(0, -3) : front
const meta = front && yaml.load(matter) || {}
if (!meta.title) {
marked.use({ walkTokens: function({ type, text }) {
if (!meta.title && type == 'heading') meta.title = text
}})
}
return meta_only ? meta : { meta, content: marked(md || _) }
}
export function log(msg, extra='') {

@@ -58,5 +41,6 @@ console.log(colors.green('✓'), msg, extra)

const [ appdir ] = path.split(sep)
return appdir == path ? '.' : appdir
return appdir == path ? '' : appdir
}
// getDirs('a/b/c') --> ['a', 'a/b', 'a/b/c']
export function getDirs(dir) {

@@ -63,0 +47,0 @@ if (!dir) return []

import { buildCSS, findModule } from '../src/builder.js'
import { parseMarkdown, getParts } from '../src/util.js'

@@ -8,4 +9,57 @@ import { match } from '../src/browser/app-router.js'

const lcss = await findModule('lightningcss')
const stylus = await findModule('stylus')
test('Lightning CSS errors', async () => {
if (!lcss) return
try {
await buildCSS({ css: 'body margin: 0 }', minify: true })
} catch (e) {
expect(e.lineText).toBe('body margin: 0 }')
expect(e.line).toBe(1)
}
})
test('Lightning CSS', async () => {
if (lcss) {
const css = await buildCSS({ css: 'body { margin: 0 }', minify: true })
expect(css).toBe('body{margin:0}')
}
})
test('Stylus error', async () => {
if (!stylus) return
try {
const css = await buildCSS({ css: 'foo { mb: 0', ext: '.styl' })
} catch (e) {
expect(e.line).toBe(1)
expect(e.column).toBe(12)
expect(e.lineText).toBe('foo { mb: 0')
}
})
test('Stylus', async () => {
if (!stylus) return
const css = await buildCSS({ css: 'body\n margin: 0', ext: '.styl', minify: true })
expect(css).toBe('body{margin:0}')
})
test('Lightning CSS errors', async () => {
if (!lcss) return
try {
await buildCSS({ css: 'body margin: 0 }', minify: true })
} catch (e) {
expect(e.lineText).toBe('body margin: 0 }')
expect(e.line).toBe(1)
}
})
test('Lightning CSS', async () => {
if (!lcss) return
const css = await buildCSS({ css: 'body { margin: 0 }', minify: true })
expect(css).toBe('body{margin:0}')
})
test('CLI args', () => {

@@ -12,0 +66,0 @@ const args = getArgs(['nue', 'build', '--verbose', '-pnve', 'joku.yaml'])

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc