Skip to content
Merged
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: 2 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
- name: Build
if: success()
run: npm run build
- name: Check demo language files
run: test -f dist/demo/assets/lang/en-US.lang && test -f dist/demo/assets/lang/de-DE.lang
- name: Deploy - https://draggable.github.io/formeo/
if: success()
uses: peaceiris/actions-gh-pages@v4
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
run: npm test
- name: Build
run: npm run build
- name: Check demo language files
run: test -f dist/demo/assets/lang/en-US.lang && test -f dist/demo/assets/lang/de-DE.lang
- name: Test built package
run: npm run test:dist
- name: Publish
Expand Down
53 changes: 53 additions & 0 deletions src/lib/js/copy-assets.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { suite, test } from 'node:test'
import { copyTargets, targets } from '../../../tools/copy-assets.mjs'

const fixture = (t, files = {}) => {
const dir = mkdtempSync(join(tmpdir(), 'formeo-copy-assets-'))
t.after(() => rmSync(dir, { recursive: true, force: true }))
for (const [path, text] of Object.entries(files)) {
mkdirSync(join(dir, path, '..'), { recursive: true })
writeFileSync(join(dir, path), text)
}
return dir
}

suite('copy-assets', () => {
test('copies nested files flat by basename and skips directories', async t => {
const src = fixture(t, { 'lang/de-DE.lang': 'de', 'lang/de-DE.json': '{}', 'top.lang': 'top' })
const dest = join(fixture(t), 'out')

t.assert.strictEqual(await copyTargets([{ src: join(src, '**/*'), dest }]), 0)
t.assert.deepStrictEqual(readdirSync(dest).sort(), ['de-DE.json', 'de-DE.lang', 'top.lang'])
})

test('the language target copies the installed package files into the demo', async t => {
const langTarget = targets.find(({ dest }) => dest.endsWith(join('assets', 'lang')))
const dest = fixture(t)

t.assert.strictEqual(await copyTargets([{ ...langTarget, dest }]), 0)
const files = readdirSync(dest)
t.assert.ok(files.includes('en-US.lang'))
t.assert.ok(files.includes('de-DE.lang'))
t.assert.ok(!files.includes('lang'))
})

test('*.js does not pick up .cjs files', async t => {
const src = fixture(t, { 'formeo.es.js': '', 'formeo.cjs': '' })
const dest = join(fixture(t), 'out')

await copyTargets([{ src: join(src, '*.js'), dest }])
t.assert.deepStrictEqual(readdirSync(dest), ['formeo.es.js'])
})

test('counts a failed copy instead of swallowing it', async t => {
t.mock.method(console, 'error', () => {})
const src = fixture(t, { 'a.lang': 'a' })
const dest = join(fixture(t, { 'not-a-dir': '' }), 'not-a-dir')

t.assert.strictEqual(await copyTargets([{ src: join(src, '*'), dest }]), 1)
t.assert.strictEqual(console.error.mock.callCount(), 1)
})
})
20 changes: 14 additions & 6 deletions tools/copy-assets.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// copyDir.mjs
import { promises as fs } from 'node:fs'
import { basename, dirname, join, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { fileURLToPath, pathToFileURL } from 'node:url'

const __dirname = dirname(fileURLToPath(import.meta.url))

const projectRoot = resolve(__dirname, '..')

const targets = [
export const targets = [
{
src: resolve(projectRoot, 'src/lib/icons/formeo-sprite.svg'),
dest: resolve(projectRoot, 'dist/demo/assets/img/'),
Expand All @@ -17,7 +17,8 @@ const targets = [
dest: resolve(projectRoot, 'dist/'),
},
{
src: resolve(projectRoot, 'node_modules', '@draggable/formeo-languages/dist/lang/*'),
// Any depth: since 3.5.1 the package nests its files in dist/lang/lang/. They are copied flat by basename.
src: resolve(projectRoot, 'node_modules', '@draggable/formeo-languages/dist/lang/**/*'),
dest: resolve(projectRoot, 'dist/demo/assets/lang'),
},
{
Expand All @@ -37,22 +38,29 @@ const targets = [

async function copyFile(src, dest, rename = null) {
for await (const file of fs.glob(src)) {
if ((await fs.stat(file)).isDirectory()) continue
const destPath = rename ? join(dest, rename) : join(dest, basename(file))
await fs.mkdir(dirname(destPath), { recursive: true })
await fs.copyFile(file, destPath)
}
}
Comment on lines 39 to 46

// Entry point
async function main() {
/** Copy every target, carrying on past errors; returns the number of targets that failed. */
export async function copyTargets(targets) {
let failures = 0
for (const target of targets) {
try {
await copyFile(target.src, target.dest, target.rename)
console.log(`Copied ${basename(target.src)} to ${target.dest}`)
} catch (error) {
failures++
console.error(`Error copying file: ${error.message}`)
}
}
return failures
}

main()
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
// A failed copy fails the build, so a broken demo can't be deployed silently.
if (await copyTargets(targets)) process.exitCode = 1
}
Loading