diff --git a/.test-esm-loader.mjs b/.test-esm-loader.mjs new file mode 100644 index 00000000..55d9a85f --- /dev/null +++ b/.test-esm-loader.mjs @@ -0,0 +1,30 @@ +// https://ar.al/2021/05/27/make-anything-a-javascript-module-using-node.js-esm-module-loaders/ +// this is for test cases running `import … from '…svg?raw'` + +import { URL } from 'url' + +export default { + loaders: [ + { + resolve(specifier, opts) { + if (specifier.endsWith('.svg')) { + let { parentURL } = opts + let url = new URL(specifier, parentURL).href + return { url } + } + }, + format(url, opts) { + if (url.endsWith('.svg')) { + return { format: 'module' } + } + }, + transform(source, opts) { + if (opts.url.endsWith('.svg')) { + return { + source: `export default ${JSON.stringify(source)}` + } + } + } + } + ] +} diff --git a/index.html b/index.html index ec0102c1..361e5a0e 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,9 @@ html { font-size: 10px; } +body { + margin: 0; +} diff --git a/jest.config.js b/jest.config.mjs similarity index 87% rename from jest.config.js rename to jest.config.mjs index 8a117493..6ed8f10e 100644 --- a/jest.config.js +++ b/jest.config.mjs @@ -1,4 +1,8 @@ -module.exports = { +import module from 'node:module' + +module.register('./.test-esm-loader.mjs', import.meta.url) + +export default { preset: 'ts-jest/presets/default', moduleFileExtensions: ['js', 'ts', 'jsx', 'tsx'], // ↓ DO NOT try to make test work w/ node16 esmodule support @@ -25,4 +29,4 @@ module.exports = { }, resetMocks: true -}; +} diff --git a/layouts-example/counter/index.tsx b/layouts-example/counter/index.tsx index 2e7b989f..6bbe779d 100644 --- a/layouts-example/counter/index.tsx +++ b/layouts-example/counter/index.tsx @@ -1,7 +1,7 @@ import { h, Fragment } from 'preact' import * as preactHooks from 'preact/hooks' -import PreactLayout from '../../src/layout/preact' +import { PreactLayout } from '@day1co/fastcomposer-layout/layouts' export default new PreactLayout({ id: 'counter', diff --git a/package.json b/package.json index b51ab4bb..369bacd6 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,14 @@ { "name": "@day1co/fastcomposer", - "version": "2.1.7", + "version": "2.2.0", "author": "fastcampus", "main": "./dist/fastcomposer.js", + "workspaces": [ + "./src/layout", + "./src/page", + "./src/state" + ], + "type": "module", "exports": { ".": { "import": "./dist/fastcomposer.mjs", @@ -19,33 +25,20 @@ "scripts": { "serve": "vite", "build": "vite build", - "lint": "vue-cli-service lint", + "build-all": "npm run build --workspaces && vite build", "build-layouts": "node layouts/build.js", - "test": "jest", - "test:e2e": "cypress run --browser chrome --headless", - "test:e2e-visible": "cypress open", - "ci:test": "./ci_test.sh" + "test": "jest" }, "repository": { "type": "git", "url": "https://github.com/day1co/fastcomposer.git" }, "dependencies": { - "@types/lodash.template": "^4.5.1", "@vue-a11y/focus-loop": "^0.2.0", - "lodash": "^4.17.20", - "lodash.template": "^4.5.0", - "marked": "^4.0.18", - "normalize.css": "^8.0.1", - "sass-mq": "^5.0.1", "splitpanes": "^2.4.1", "vue": "^2.6.12", "vue-smooth-dnd": "^0.8.1" }, - "peerDependencies": { - "preact": "^10.11.2", - "preact-render-to-string": "^5.2.6" - }, "devDependencies": { "@babel/core": "^7.12.10", "@babel/preset-env": "^7.12.11", @@ -66,10 +59,11 @@ "jest": "^29.0.2", "jsdom": "^20.0.2", "prettier": "2.0.5", - "sass": "^1.32.8", + "sass": "1.32.x", "ts-jest": "^29.0.3", - "typescript": "^4.8.3", - "vite": "^4.4.9", + "typescript": "^5.5.4", + "vite": "^5.4.3", + "vite-plugin-dts": "^4.1.0", "vite-plugin-raw": "^1.0.3", "vue-eslint-parser": "^7.1.0", "vue-template-compiler": "^2.6.12" diff --git a/src/_tsconfig.json b/src/_tsconfig.json new file mode 100644 index 00000000..c68b0a2d --- /dev/null +++ b/src/_tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "./*.ts", + "./**/*.ts" + ], + "exclude": [ + "./test" + ] +} diff --git a/src/_vite.config.mjs b/src/_vite.config.mjs new file mode 100644 index 00000000..81f54704 --- /dev/null +++ b/src/_vite.config.mjs @@ -0,0 +1,23 @@ +import path from 'node:path' +import { defineConfig } from 'vite' +import dts from 'vite-plugin-dts' +import viteRawPlugin from 'vite-plugin-raw' + +export default dirname => defineConfig({ + root: dirname, + plugins: [ + dts(), + viteRawPlugin({ + match: /\.(ejs|svg)$/i + }) + ], + build: { + sourcemap: true, + lib: { + entry: { + index: path.join(dirname, './index.ts') + }, + formats: ['es'] + } + } +}) diff --git a/src/layout/index.ts b/src/layout/index.ts index aa6cd4f8..4f6d35bf 100644 --- a/src/layout/index.ts +++ b/src/layout/index.ts @@ -1,8 +1,4 @@ -import type LayoutMeta from '../structs/LayoutMeta' -import type LayoutParameter from '../structs/LayoutParameter' -import type { ListLayoutParameter } from '../structs/LayoutParameter' - -import { clone } from '../util' +import type { LayoutMeta, LayoutParameter, ListLayoutParameter } from './structs' export interface LayoutOptions { id: string @@ -32,7 +28,7 @@ abstract class LayoutBase { } else if(!this.defaultValues) { params = this.params } else { - return clone(this.defaultValues) + return structuredClone(this.defaultValues) } const entries = [ ...params.entries() ] @@ -79,8 +75,8 @@ export default LayoutBase /// -export abstract class DynamicLayoutBase extends LayoutBase { - override template: (opt: any, ctx: any) => any +export interface DynamicLayoutBase extends LayoutBase { + template: (opt: any, ctx: any) => any // hydrate above hydrate?(el: HTMLElement, opt: any): void diff --git a/src/layout/layouts/broken.ts b/src/layout/layouts/broken.ts new file mode 100644 index 00000000..f0ff426a --- /dev/null +++ b/src/layout/layouts/broken.ts @@ -0,0 +1,11 @@ +import LegacyLayout from './legacy' + +// Some pages +export default new LegacyLayout({ + id: 'broken', + meta: { + description: '다른 레이아웃으로 새 레이어를 만들고 이 레이어는 삭제하세요', + icon: '' + }, + params: new Map() +}) diff --git a/src/layout/layouts/index.ts b/src/layout/layouts/index.ts new file mode 100644 index 00000000..cec27fdd --- /dev/null +++ b/src/layout/layouts/index.ts @@ -0,0 +1,2 @@ +export { default as LegacyLayout } from './legacy' +export { default as PreactLayout } from './preact' diff --git a/src/layout/legacy.ts b/src/layout/layouts/legacy.ts similarity index 96% rename from src/layout/legacy.ts rename to src/layout/layouts/legacy.ts index cef9a138..41f765fd 100644 --- a/src/layout/legacy.ts +++ b/src/layout/layouts/legacy.ts @@ -1,6 +1,6 @@ import type LayoutMeta from '../structs/LayoutMeta' import type LayoutParameter from '../structs/LayoutParameter' -import type { LayoutOptions } from '.' +import type { LayoutOptions } from '..' import type { SingularLayoutParameter, ListLayoutParameter, @@ -11,7 +11,7 @@ import type { import lotemplate from 'lodash.template' import { marked } from 'marked' -import LayoutBase from '.' +import LayoutBase from '..' const paramArrayToMap = (params: Array): Map => diff --git a/src/layout/preact.ts b/src/layout/layouts/preact.ts similarity index 52% rename from src/layout/preact.ts rename to src/layout/layouts/preact.ts index 51fad5d2..143f95e0 100644 --- a/src/layout/preact.ts +++ b/src/layout/layouts/preact.ts @@ -1,27 +1,27 @@ -import type { LayoutOptions } from '.' +import type { LayoutOptions } from '..' import renderToString from 'preact-render-to-string' -import preact from 'preact' +import * as preact from 'preact' import { h, Fragment } from 'preact' -import { DynamicLayoutBase } from '.' +import { DynamicLayoutBase } from '..' export default class PreactLayout extends DynamicLayoutBase { constructor(layout: LayoutOptions) { super(layout) - this.component = opt => h(layout.template, { opt }) + this.template = opt => h(layout.template, { opt }) } render(el: HTMLElement, opt: any): unknown { - return preact.render(this.component(opt), el) + return preact.render(this.template(opt, null), el) } renderToString(opt: any): string { - return renderToString(this.component(opt)) + return renderToString(this.template(opt, null)) } hydrate(el: HTMLElement, opt: any): void { - return preact.hydrate(this.component(opt), el) + return preact.hydrate(this.template(opt, null), el) } } diff --git a/src/layout/package.json b/src/layout/package.json new file mode 100644 index 00000000..1f46dfbe --- /dev/null +++ b/src/layout/package.json @@ -0,0 +1,31 @@ +{ + "name": "@day1co/fastcomposer-layout", + "version": "2.2.0", + "type": "module", + "files": [ + "dist", + "layouts", + "structs", + "*.d.ts" + ], + "main": "./dist/index.js", + "exports": { + ".": "./dist/index.js", + "./layouts": "./dist/layouts.js", + "./structs": "./dist/structs.js" + }, + "scripts": { + "build": "vite build", + "prepack": "vite build", + "clean": "rm -rf ./dist ./node_modules" + }, + "dependencies": { + "@types/lodash.template": "^4.5.1", + "lodash.template": "^4.5.0", + "marked": "^4.0.18" + }, + "peerDependencies": { + "preact": "^10.11.2", + "preact-render-to-string": "^5.2.6" + } +} diff --git a/src/Structs/LayoutMeta.ts b/src/layout/structs/LayoutMeta.ts similarity index 100% rename from src/Structs/LayoutMeta.ts rename to src/layout/structs/LayoutMeta.ts diff --git a/src/layout/structs/LayoutMigration.ts b/src/layout/structs/LayoutMigration.ts new file mode 100644 index 00000000..d53d6ae7 --- /dev/null +++ b/src/layout/structs/LayoutMigration.ts @@ -0,0 +1,9 @@ +type LayoutMigration = { + name: string + options: any + // TODO fix type of options (was typeof this.options) + requires(options, layout, values): boolean + migrate(options, layout, values): any +} + +export default LayoutMigration diff --git a/src/Structs/LayoutParameter.ts b/src/layout/structs/LayoutParameter.ts similarity index 100% rename from src/Structs/LayoutParameter.ts rename to src/layout/structs/LayoutParameter.ts diff --git a/src/Structs/Snippet.ts b/src/layout/structs/Snippet.ts similarity index 78% rename from src/Structs/Snippet.ts rename to src/layout/structs/Snippet.ts index c30ca42c..0137fc57 100644 --- a/src/Structs/Snippet.ts +++ b/src/layout/structs/Snippet.ts @@ -1,4 +1,4 @@ -import type { LayerMeta } from '../page/layer' +import type { LayerMeta } from '../../page/layer' export type SnippetItem = { layout: string, diff --git a/src/layout/structs/index.ts b/src/layout/structs/index.ts new file mode 100644 index 00000000..5b1c0b6b --- /dev/null +++ b/src/layout/structs/index.ts @@ -0,0 +1,10 @@ +export type { default as LayoutMeta } from './LayoutMeta' +export type * from './LayoutMeta' + +export type { default as LayoutMigration } from './LayoutMigration' + +export type { default as LayoutParameter } from './LayoutParameter' +export type * from './LayoutParameter' + +export type { default as Snippet } from './Snippet' +export type * from './Snippet' diff --git a/src/layout/test/layouts/legacy.ts b/src/layout/test/layouts/legacy.ts index 2d35455b..3048047f 100644 --- a/src/layout/test/layouts/legacy.ts +++ b/src/layout/test/layouts/legacy.ts @@ -1,4 +1,4 @@ -import LegacyLayout from '../../legacy' +import LegacyLayout from '../../layouts/legacy' export default LegacyLayout.fromDefinition({ id: 'list', diff --git a/src/layout/test/layouts/preact.tsx b/src/layout/test/layouts/preact.tsx index e0279a18..29f194ae 100644 --- a/src/layout/test/layouts/preact.tsx +++ b/src/layout/test/layouts/preact.tsx @@ -1,7 +1,7 @@ import { h, Fragment } from 'preact' import preactHooks from 'preact/hooks' -import PreactLayoutBase from '../../preact' +import PreactLayoutBase from '../../layouts/preact' export default new PreactLayoutBase({ id: 'preact-example', diff --git a/src/layout/tsconfig.json b/src/layout/tsconfig.json new file mode 120000 index 00000000..81195eb7 --- /dev/null +++ b/src/layout/tsconfig.json @@ -0,0 +1 @@ +../_tsconfig.json \ No newline at end of file diff --git a/src/layout/vite.config.mjs b/src/layout/vite.config.mjs new file mode 100644 index 00000000..775a9cdd --- /dev/null +++ b/src/layout/vite.config.mjs @@ -0,0 +1,17 @@ +import path from 'node:path' +import { defineConfig, mergeConfig } from 'vite' +import config from '../_vite.config.mjs' + +export default defineConfig( + mergeConfig(config(__dirname), { + build: { + lib: { + entry: { + index: path.join(__dirname, './index.ts'), + layouts: path.join(__dirname, './layouts/index.ts'), + structs: path.join(__dirname, './structs/index.ts'), + }, + }, + } + }) +) diff --git a/src/legacy/assets/scss/style.scss b/src/legacy/assets/scss/style.scss index c53eb8c2..b0b583d0 100644 --- a/src/legacy/assets/scss/style.scss +++ b/src/legacy/assets/scss/style.scss @@ -2,12 +2,11 @@ @import 'utils/utilities'; // vendors -@import 'sass-mq'; -@import 'normalize.css'; @import 'splitpanes'; -@import 'pane'; // base +@import 'pane'; + @import 'base/color-scheme'; @import 'base/fonts'; @import 'base/helpers'; diff --git a/src/legacy/components/edit/file.vue b/src/legacy/components/edit/file.vue index b122ca87..8aff87a2 100644 --- a/src/legacy/components/edit/file.vue +++ b/src/legacy/components/edit/file.vue @@ -32,7 +32,7 @@