Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/nuedom/src/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const RE_FN = /(script|h_fn|fn):\s*(['"`])([^\2]*?)\2/g

export function compileJS(js) {
return js.replace(RE_FN, function(_, key, __, expr) {
return key == 'script' ? `${key}: function() { ${expr.trim().replaceAll('\\n', '\n')} \n\t\t}`
return key == 'script' ? `${key}: function() { ${expr.trim().replace(/\\r/g, '').replace(/\\n/g, '\n')} \n\t\t}`
: `${key}: ${compileFn(expr, key[0] == 'h')}`
})
}
Expand Down
4 changes: 2 additions & 2 deletions packages/nuekit/src/cmd/build.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import { mkdir, rmdir, writeFile, unlink } from 'node:fs/promises'
import { join, sep } from 'node:path'
import { join } from 'node:path'
import { tmpdir } from 'os'

import { generateSitemap, generateFeed } from '../render/feed'
Expand Down Expand Up @@ -55,7 +55,7 @@ export async function buildAll(subset, args) {
await createSystemFiles(dist, init)

// build files
subset = subset.filter(el => !el.is_yaml && !el.dir.startsWith(`@shared${sep}data`))
subset = subset.filter(el => !el.is_yaml && !el.dir.startsWith('@shared/data'))

await Promise.all(subset.map(async asset => {
try {
Expand Down
4 changes: 2 additions & 2 deletions packages/nuekit/src/conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export async function readSiteConf(args={}) {

// build ignore list into config
const ignore = [...SKIP, ...(conf.site?.skip || [])]
ignore.push(conf.server?.dir || join('@shared', 'server'))
ignore.push(join('@shared', 'test'))
ignore.push(conf.server?.dir || '@shared/server')
ignore.push('@shared/test')

// production override
if (is_prod && conf.meta) {
Expand Down
12 changes: 6 additions & 6 deletions packages/nuekit/src/deps.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@

import { join, normalize, dirname, extname, basename, sep } from 'node:path'
import { dirname, extname, basename } from 'node:path'

// app, lib, server are @shared, but not auto-included
const AUTO_INCLUDED = ['data', 'design', 'ui'].map(dir => join('@shared', dir))
const AUTO_INCLUDED = ['data', 'design', 'ui'].map(dir => `@shared/${dir}`)

const ASSET_TYPES = ['.html', '.js', '.ts', '.yaml', '.css']

Expand Down Expand Up @@ -40,12 +40,12 @@ function isDep(page_path, asset_path, all_paths) {
if (dir == '.') return true

// shared dir -> auto-included
if (AUTO_INCLUDED.some(dir => asset_path.startsWith(dir + sep))) return true
if (AUTO_INCLUDED.some(dir => asset_path.startsWith(dir + '/'))) return true

// SPA: entire app tree
if (basename(page_path) == 'index.html') {
const dir = dirname(page_path)
return dir == '.' ? !all_paths.some(el => extname(el) == '.md') : asset_path.startsWith(dir + sep)
return dir == '.' ? !all_paths.some(el => extname(el) == '.md') : asset_path.startsWith(dir + '/')
}

// index.md -> home dir
Expand All @@ -58,14 +58,14 @@ function isDep(page_path, asset_path, all_paths) {

// check if asset is in ui of any parent directory
return page_dirs.some(pageDir => {
const ui_dir = pageDir ? join(pageDir, 'ui') : 'ui'
const ui_dir = pageDir ? pageDir + '/ui' : 'ui'
return asset_dir == ui_dir || asset_dir == pageDir
})
}


// parseDirs('a/b/c') --> ['a', 'a/b', 'a/b/c']
export function parseDirs(dir) {
const els = normalize(dir).split(sep)
const els = dir.split('/').filter(Boolean)
return els.map((el, i) => els.slice(0, i + 1).join('/'))
}
6 changes: 3 additions & 3 deletions packages/nuekit/src/file.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { parse, sep, join } from 'node:path'
import { parse, join } from 'node:path'
import { lstat } from 'node:fs/promises'

export async function createFile(root, path) {
Expand Down Expand Up @@ -53,7 +53,7 @@ export function getFileInfo(path) {
const url = getURL(info)
const slug = getSlug(info)

if (dir.includes(sep)) info.basedir = dir.split(sep)[0]
if (dir.includes('/')) info.basedir = dir.split('/')[0]

return { ...info, path, type, url, slug, [`is_${type}`]: true }
}
Expand All @@ -67,7 +67,7 @@ export function getURL(file) {
}

if (ext == '.ts') ext = '.js'
const els = dir.split(sep)
const els = dir.split('/')
els.push(name + ext)

return `/${ els.join('/') }`.replace('//', '/')
Expand Down
4 changes: 2 additions & 2 deletions packages/nuekit/src/render/head.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { parse, sep } from 'node:path'
import { parse } from 'node:path'

import { elem } from 'nuemark'
import { version } from '../system'
Expand Down Expand Up @@ -86,7 +86,7 @@ function renderTitle(title, template) {
}

export function renderScripts(assets) {
const scripts = assets.filter(f => ['.js', '.ts'].includes(f.ext) && f.dir != `@shared${sep}data`)
const scripts = assets.filter(f => ['.js', '.ts'].includes(f.ext) && f.dir != '@shared/data')
return scripts.map(s => elem('script', { src: `/${s.dir}/${s.name}.js`, type: 'module' }))
}

Expand Down
4 changes: 2 additions & 2 deletions packages/nuekit/src/site.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { parse, sep } from 'node:path'
import { parse } from 'node:path'
import { fswalk } from './tools/fswalk'
import { createAsset } from './asset'
import { createFile } from './file'
Expand Down Expand Up @@ -71,7 +71,7 @@ export function sortAssets(items) {


export async function mergeSharedData(assets, data={}) {
const shared = assets.filter(a => a.dir?.startsWith(`@shared${sep}data`))
const shared = assets.filter(a => a.dir?.startsWith(`@shared/data`))
const statics = shared.filter(f => f.is_json || f.is_yaml)

const dataset = await Promise.all(statics.map(f => f.parse()))
Expand Down
4 changes: 3 additions & 1 deletion packages/nuekit/src/tools/fswalk.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { readdir, stat } from 'node:fs/promises'
import { parse, join, relative } from 'node:path'

export const toPosix = path => path?.replaceAll('\\', '/') || ''

export function matches(path, patterns) {
return patterns.some(pattern => path.includes(pattern))
}
Expand All @@ -24,7 +26,7 @@ async function walkDirectory(dir, root, opts) {

for (const entry of entries) {
const fullPath = join(dir, entry.name)
const relativePath = relative(root, fullPath)
const relativePath = toPosix(relative(root, fullPath))

if (isSkipped(relativePath) || matches(relativePath, ignore)) continue

Expand Down
7 changes: 4 additions & 3 deletions packages/nuekit/src/tools/fswatch.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@

import { promises as fs, watch } from 'node:fs'
import { join, extname } from 'node:path'
import { fswalk, matches } from './fswalk'
import { fswalk, matches, toPosix } from './fswalk'

// Main fswatch function
export function fswatch(root, opts = {}) {
const { ignore = ['.*', '_*', 'node_modules'] } = opts
// const shouldProcess = createDeduplicator()

// Start watching
const watcher = watch(root, { recursive: true }, async function(event, path) {
const watcher = watch(root, { recursive: true }, async function (event, rawPath) {
const path = toPosix(rawPath)
const { onupdate, onremove } = watcher
if (!path) return

Expand All @@ -31,7 +32,7 @@ export function fswatch(root, opts = {}) {
const paths = await fswalk(fullPath, ignore)

for (const subPath of paths) {
await onupdate(join(path, subPath))
await onupdate(toPosix(join(path, subPath)))
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/nuekit/test/file.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ test('createFile', async () => {
const file = await createFile(testDir, path)

expect(file).toMatchObject({
rootpath: 'test_dir/@shared/model/index.ts',
rootpath: join(testDir, '@shared/model/index.ts'),
path: '@shared/model/index.ts',
dir: '@shared/model',
basedir: '@shared',
Expand Down
18 changes: 10 additions & 8 deletions packages/nuekit/test/fswatch.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { test, expect } from 'bun:test'
import { promises as fs } from 'node:fs'
import { join } from 'node:path'
import { tmpdir } from 'node:os'

import {
createDeduplicator,
Expand All @@ -11,7 +12,7 @@ import {
// Helper function to wait for expected array length
async function waitForEvents(array, expectedCount, maxWait = 1000) {
const start = Date.now()
while (array.length < expectedCount && Date.now() - start < maxWait) {
while (new Set(array).size < expectedCount && Date.now() - start < maxWait) {
await new Promise(resolve => setTimeout(resolve, 5))
}
}
Expand All @@ -35,7 +36,7 @@ test.skip('deduplicator blocks rapid events', async () => {
})

test('watches single file changes', async () => {
const tmpDir = await fs.mkdtemp('/tmp/fswatch-test-')
const tmpDir = await fs.mkdtemp(join(tmpdir(), 'fswatch-test-'))
const testFile = join(tmpDir, 'test.txt')

const changes = []
Expand All @@ -55,7 +56,7 @@ test('watches single file changes', async () => {
})

test('watches directory creation and processes files', async () => {
const tmpDir = await fs.mkdtemp('/tmp/fswatch-test-')
const tmpDir = await fs.mkdtemp(join(tmpdir(), 'fswatch-test-'))
const newDir = join(tmpDir, 'newdir')

const changes = []
Expand All @@ -70,15 +71,16 @@ test('watches directory creation and processes files', async () => {
// Wait for events
await waitForEvents(changes, 2)

expect(changes).toContain('newdir/file1.txt')
expect(changes).toContain('newdir/file2.js')
const uniqueChanges = [...new Set(changes)]
expect(uniqueChanges).toContain('newdir/file1.txt')
expect(uniqueChanges).toContain('newdir/file2.js')

watcher.close()
await fs.rm(tmpDir, { recursive: true })
})

test('ignores files matching patterns', async () => {
const tmpDir = await fs.mkdtemp('/tmp/fswatch-test-')
const tmpDir = await fs.mkdtemp(join(tmpdir(), 'fswatch-test-'))

const changes = []
const watcher = fswatch(tmpDir, { ignore: ['*.log', '.hidden*'] })
Expand All @@ -100,7 +102,7 @@ test('ignores files matching patterns', async () => {
})

test('handles file removal', async () => {
const tmpDir = await fs.mkdtemp('/tmp/fswatch-test-')
const tmpDir = await fs.mkdtemp(join(tmpdir(), 'fswatch-test-'))
const testFile = join(tmpDir, 'test.txt')

const removed = []
Expand All @@ -122,7 +124,7 @@ test('handles file removal', async () => {
})

test('ignores files without extensions', async () => {
const tmpDir = await fs.mkdtemp('/tmp/fswatch-test-')
const tmpDir = await fs.mkdtemp(join(tmpdir(), 'fswatch-test-'))

const changes = []
const watcher = fswatch(tmpDir)
Expand Down