Skip to content

Commit

Permalink
feat: initial SvelteKit support (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianrothe authored May 25, 2021
1 parent 1033c4a commit 0c008d7
Show file tree
Hide file tree
Showing 15 changed files with 615 additions and 363 deletions.
7 changes: 7 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"recommendations": [
"editorconfig.editorconfig",
"standard.vscode-standard",
"svelte.svelte-vscode"
]
}
11 changes: 11 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
// disable builtin validation
"javascript.validate.enable": false,

"standard.autoFixOnSave": true,

// SVELTE
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode"
}
}
File renamed without changes.
22 changes: 22 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/
export default {
coverageProvider: 'v8',

moduleFileExtensions: ['js', 'ts', 'cjs'],

testMatch: [
'**/__tests__/**/*.?(c)[jt]s?(x)',
'**/?(*.)+(spec|test).?(c)[tj]s?(x)',
'!**/fixtures/**'
],

testRunner: 'jest-circus/runner',

transform: {
'^.+\\.ts$': 'esbuild-jest',
'^.+\\.js$': 'esbuild-jest'
}
}
613 changes: 378 additions & 235 deletions package-lock.json

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"name": "svelte-jester",
"version": "1.5.0",
"description": "A Jest transformer for Svelte - compile your components before importing them into tests",
"main": "src/transformer.js",
"main": "src/transformer.cjs",
"type": "module",
"license": "MIT",
"author": "Rahim Alwer <rahim_alwer@hotmail.com>",
"engines": {
"node": ">= 8"
"node": ">= 14"
},
"homepage": "https://github.com/mihar-22/svelte-jester#readme",
"repository": {
Expand All @@ -20,15 +21,16 @@
"svelte-jester",
"jest",
"svelte",
"sveltekit",
"compile",
"transformer",
"preprocess",
"test"
],
"files": [
"src/transformer.js",
"src/transformer.cjs",
"src/preprocess.js",
"src/svelteconfig.js"
"src/svelteconfig.cjs"
],
"scripts": {
"toc": "doctoc README.md",
Expand All @@ -43,18 +45,19 @@
"peerDependencies": {
"svelte": ">= 3"
},
"dependencies": {
"cosmiconfig": "^7.0.0"
},
"devDependencies": {
"@types/jest": "^26.0.22",
"@sveltejs/adapter-static": "^1.0.0-next.10",
"@types/jest": "^26.0.23",
"doctoc": "^2.0.0",
"esbuild": "^0.12.1",
"esbuild-jest": "^0.5.0",
"jest": "^26.6.3",
"node-sass": "^5.0.0",
"jest-circus": "^26.6.3",
"node-sass": "^6.0.0",
"standard": "^16.0.3",
"standard-version": "^9.2.0",
"standard-version": "^9.3.0",
"svelte": "^3.18.2",
"svelte-preprocess": "^4.7.2",
"svelte-preprocess": "^4.7.3",
"typescript": "^4.2.4",
"why-is-node-running": "^2.2.0"
}
Expand Down
62 changes: 62 additions & 0 deletions src/__tests__/fixtures/shared/commonTransformerTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const sharedTests = (dependencies) => {
const { path, runTransformer } = dependencies

it('should transform basic component', () => {
runTransformer('BasicComp')
})

it('should transform when using sass preprocessor', () => {
runTransformer('SassComp', { preprocess: true })
})

it('should transform when using full path to preprocess', () => {
const preprocessPath = path.resolve(__dirname, '../../../../_svelte.config.cjs')
runTransformer('SassComp', { preprocess: preprocessPath })
})

it('should search for "svelte.config.cjs" as well as "svelte.config.js"', () => {
const results = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' })
// this is a little brittle, but it demonstrates that the replacements in
// "svelte.config.cjs" are working
expect(results).toContain('text("Bye ");')
})

it('should transform when using typescript preprocessor', () => {
runTransformer('TypescriptComp', { preprocess: true })
})

it('should transform basic component and keep styles', () => {
const code = runTransformer('BasicComp')
expect(code).toContain('add_css()')
expect(code).toContain('.counter.active')
})

it('should accept compiler options', () => {
const code = runTransformer('BasicComp', { compilerOptions: { css: false } })
expect(code).not.toContain('add_css()')
expect(code).not.toContain('.counter.active')
})

it('should output code to console when debug is true', () => {
global.window.console.log = jest.fn()
const code = runTransformer('BasicComp', { debug: true })
const esInterop = 'Object.defineProperty(exports, "__esModule", { value: true });'
expect(global.window.console.log).toHaveBeenCalledWith(code.replace(esInterop, ''))
})

it('should accept maxBuffer option for preprocess buffer limit', () => {
expect(
() => runTransformer('SassComp', { preprocess: true, maxBuffer: 1 })
).toThrow('spawnSync /bin/sh ENOBUFS')
runTransformer('SassComp', { preprocess: true, maxBuffer: 5 * 1024 * 1024 })
})

it('should pass and transform process.env.NODE_ENV variable', () => {
const code = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' })

// JEST sets NODE_ENV to test automatically
expect(code).toContain('test')
})
}

export default sharedTests
20 changes: 20 additions & 0 deletions src/__tests__/fixtures/sveltekit.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import sveltePreprocess from 'svelte-preprocess'
import adapter from '@sveltejs/adapter-static'

const { replace } = sveltePreprocess

const config = {
kit: {
adapter: adapter
},
preprocess: [
replace([
// strip style tag
[/<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi, ''],
[/Hello/gi, 'Bye'],
// replace env var
[/process\.env\.NODE_ENV/gi, JSON.stringify(process.env.NODE_ENV)]
])
]
}
export default config
26 changes: 26 additions & 0 deletions src/__tests__/transformer.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const fs = require('fs')
const path = require('path')
const transformer = require('../transformer')
const sharedTests = require('./fixtures/shared/commonTransformerTests').default

const runTransformer = (filename, options) => {
const process = transformer.createTransformer(options).process
const path = require.resolve(`./fixtures/${filename}.svelte`)
const source = fs.readFileSync(path).toString()
const result = process(source, path)
expect(result.code).toBeDefined()
expect(result.code).toContain('SvelteComponent')
expect(result.map).toBeDefined()
return result.code
}

describe('CJS transformer', () => {
it('should search for "svelte.config.cjs" as well as "svelte.config.js"', () => {
const results = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' })
// this is a little brittle, but it demonstrates that the replacements in
// "svelte.config.cjs" are working
expect(results).toContain('text("Bye ");')
})

sharedTests({ runTransformer, path })
})
67 changes: 10 additions & 57 deletions src/__tests__/transformer.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const fs = require('fs')
const path = require('path')
const transformer = require('../transformer')
import fs from 'fs'
import path from 'path'
import transformer from '../transformer'
import sharedTests from './fixtures/shared/commonTransformerTests'

const runTransformer = (filename, options) => {
const process = transformer.createTransformer(options).process
Expand All @@ -13,62 +14,14 @@ const runTransformer = (filename, options) => {
return result.code
}

describe('transformer', () => {
it('should transform basic component', () => {
runTransformer('BasicComp')
})

it('should transform when using sass preprocessor', () => {
runTransformer('SassComp', { preprocess: true })
})

it('should transform when using full path to preprocess', () => {
const preprocessPath = path.resolve(__dirname, '../../_svelte.config.js')
runTransformer('SassComp', { preprocess: preprocessPath })
})

it('should search for "svelte.config.cjs" as well as "svelte.config.js"', () => {
const results = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' })
describe('ESM transformer', () => {
it('should transform with config in ESM format', () => {
const svelteKitConfig = path.resolve(__dirname, './fixtures/sveltekit.config.js')
const results = runTransformer('BasicComp', { preprocess: svelteKitConfig })
// this is a little brittle, but it demonstrates that the replacements in
// "svelte.config.cjs" are working
// "sveltekit.config.js" are working
expect(results).toContain('text("Bye ");')
})

// TODO: it works but it's really slow, it might have to do with the preprocessor.
// it('should transform when using typescript preprocessor', () => {
// runTransformer('TypescriptComp', { preprocess: true })
// })

it('should transform basic component and keep styles', () => {
const code = runTransformer('BasicComp')
expect(code).toContain('add_css()')
expect(code).toContain('.counter.active')
})

it('should accept compiler options', () => {
const code = runTransformer('BasicComp', { compilerOptions: { css: false } })
expect(code).not.toContain('add_css()')
expect(code).not.toContain('.counter.active')
})

it('should output code to console when debug is true', () => {
global.window.console.log = jest.fn()
const code = runTransformer('BasicComp', { debug: true })
const esInterop = 'Object.defineProperty(exports, "__esModule", { value: true });'
expect(global.window.console.log).toHaveBeenCalledWith(code.replace(esInterop, ''))
})

it('should accept maxBuffer option for preprocess buffer limit', () => {
expect(
() => runTransformer('SassComp', { preprocess: true, maxBuffer: 1 })
).toThrow('spawnSync /bin/sh ENOBUFS')
runTransformer('SassComp', { preprocess: true, maxBuffer: 5 * 1024 * 1024 })
})

it('should pass and transform process.env.NODE_ENV variable', () => {
const code = runTransformer('BasicComp', { preprocess: true, rootMode: 'upward' })

// JEST sets NODE_ENV to test automatically
expect(code).toContain('test')
})
sharedTests({ runTransformer, path })
})
14 changes: 8 additions & 6 deletions src/preprocess.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const svelte = require('svelte/compiler')
const { cosmiconfigSync } = require('cosmiconfig')
import { preprocess } from 'svelte/compiler'

const { source, filename, svelteConfig } = process.env
const config = cosmiconfigSync().load(svelteConfig).config
import(svelteConfig).then(configImport => {
// ESM or CommonJS
const config = configImport.default ? configImport.default : configImport

svelte.preprocess(source, config.preprocess || {}, { filename }).then((r) => {
process.stdout.write(JSON.stringify(r))
})
preprocess(source, config.preprocess || {}, { filename }).then((r) => {
process.stdout.write(JSON.stringify(r))
})
}).catch(err => process.stderr.write(err))
2 changes: 1 addition & 1 deletion src/svelteconfig.js → src/svelteconfig.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ exports.getSvelteConfig = (rootMode, filename, preprocess) => {
}

if (configFile === null || !fs.existsSync(configFile)) {
throw Error(`Could not find ${configFilenames.join(' or ')}`)
throw Error(`Could not find ${configFilenames.join(' or ')} or ${configFile}.`)
}

return configFile
Expand Down
56 changes: 56 additions & 0 deletions src/transformer.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// const log = require('why-is-node-running')
const { basename } = require('path')
const { execSync } = require('child_process')
const svelte = require('svelte/compiler')
const { getSvelteConfig } = require('./svelteconfig.cjs')

const transformer = (options = {}) => (source, filename) => {
const { preprocess, rootMode, maxBuffer } = options

if (!preprocess) {
return compiler(options, filename, source)
}

const svelteConfig = getSvelteConfig(rootMode, filename, preprocess)
const preprocessor = require.resolve('./preprocess.js')

const preprocessResult = execSync(
`node --unhandled-rejections=strict --abort-on-uncaught-exception ${preprocessor}`,
{
env: { ...process.env, source, filename, svelteConfig },
maxBuffer: maxBuffer || 10 * 1024 * 1024
}
).toString()

const parsedPreprocessResult = JSON.parse(preprocessResult)
return compiler(options, filename, parsedPreprocessResult.code, parsedPreprocessResult.map)
}

const compiler = (options = {}, filename, processedCode, processedMap) => {
const { debug, compilerOptions } = options

const result = svelte.compile(processedCode, {
filename: basename(filename),
css: true,
accessors: true,
dev: true,
format: 'cjs',
sourcemap: processedMap,
...compilerOptions
})

if (debug) {
console.log(result.js.code)
}

const esInterop = 'Object.defineProperty(exports, "__esModule", { value: true });'

return {
code: result.js.code + esInterop,
map: JSON.stringify(result.js.map)
}
}

exports.createTransformer = (options) => ({
process: transformer(options)
})
Loading

0 comments on commit 0c008d7

Please sign in to comment.