mirror of
https://github.com/penpot/penpot.git
synced 2025-05-03 13:55:54 +02:00
Merge pull request #4952 from penpot/ladybenko-8439-storybook-build
Storybook build
This commit is contained in:
commit
d0059cbe29
12 changed files with 188 additions and 32 deletions
|
@ -108,7 +108,7 @@ jobs:
|
||||||
working_directory: "./frontend"
|
working_directory: "./frontend"
|
||||||
command: |
|
command: |
|
||||||
yarn install
|
yarn install
|
||||||
yarn run compile
|
yarn run build:app:assets
|
||||||
clojure -M:dev:shadow-cljs release main
|
clojure -M:dev:shadow-cljs release main
|
||||||
yarn playwright install --with-deps chromium
|
yarn playwright install --with-deps chromium
|
||||||
yarn e2e:test
|
yarn e2e:test
|
||||||
|
@ -129,4 +129,3 @@ jobs:
|
||||||
paths:
|
paths:
|
||||||
- ~/.m2
|
- ~/.m2
|
||||||
key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}
|
key: v1-dependencies-{{ checksum "backend/deps.edn" }}-{{ checksum "frontend/deps.edn"}}-{{ checksum "common/deps.edn"}}
|
||||||
|
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -48,6 +48,8 @@
|
||||||
/deploy
|
/deploy
|
||||||
/docker/images/bundle*
|
/docker/images/bundle*
|
||||||
/exporter/target
|
/exporter/target
|
||||||
|
/frontend/.storybook/preview-body.html
|
||||||
|
/frontend/.storybook/preview-head.html
|
||||||
/frontend/cypress/fixtures/validuser.json
|
/frontend/cypress/fixtures/validuser.json
|
||||||
/frontend/cypress/videos/*/
|
/frontend/cypress/videos/*/
|
||||||
/frontend/cypress/videos/*/
|
/frontend/cypress/videos/*/
|
||||||
|
@ -68,7 +70,6 @@
|
||||||
/web
|
/web
|
||||||
clj-profiler/
|
clj-profiler/
|
||||||
node_modules
|
node_modules
|
||||||
frontend/.storybook/preview-body.html
|
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
|
|
|
@ -149,6 +149,11 @@ http {
|
||||||
proxy_pass http://127.0.0.1:6060/ws/notifications;
|
proxy_pass http://127.0.0.1:6060/ws/notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /storybook {
|
||||||
|
alias /home/penpot/penpot/frontend/storybook-static/;
|
||||||
|
autoindex on;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) {
|
location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) {
|
||||||
proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file;
|
proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file;
|
||||||
|
|
|
@ -17,28 +17,28 @@
|
||||||
"@vitejs/plugin-react": "^4.2.0"
|
"@vitejs/plugin-react": "^4.2.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"fmt:clj:check": "cljfmt check --parallel=false src/ test/",
|
"build:app:assets": "node ./scripts/build-app-assets.js",
|
||||||
|
"build:storybook": "yarn run build:storybook:assets && yarn run build:storybook:cljs && storybook build",
|
||||||
|
"build:storybook:assets": "node ./scripts/build-storybook-assets.js",
|
||||||
|
"build:storybook:cljs": "clojure -M:dev:shadow-cljs release storybook",
|
||||||
|
"e2e:server": "node ./scripts/e2e-server.js",
|
||||||
|
"e2e:test": "playwright test --project default",
|
||||||
"fmt:clj": "cljfmt fix --parallel=true src/ test/",
|
"fmt:clj": "cljfmt fix --parallel=true src/ test/",
|
||||||
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js",
|
"fmt:clj:check": "cljfmt check --parallel=false src/ test/",
|
||||||
"fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w",
|
"fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w",
|
||||||
|
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js",
|
||||||
|
"lint:clj": "clj-kondo --parallel --lint src/",
|
||||||
"lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
|
"lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
|
||||||
"lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
|
"lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
|
||||||
"lint:clj": "clj-kondo --parallel --lint src/",
|
"test": "yarn run test:compile && yarn run test:run",
|
||||||
"test:compile": "clojure -M:dev:shadow-cljs compile test --config-merge '{:autorun false}'",
|
"test:compile": "clojure -M:dev:shadow-cljs compile test --config-merge '{:autorun false}'",
|
||||||
"test:run": "node target/tests.cjs",
|
"test:run": "node target/tests.cjs",
|
||||||
"test:watch": "clojure -M:dev:shadow-cljs watch test",
|
"test:watch": "clojure -M:dev:shadow-cljs watch test",
|
||||||
"test": "yarn run test:compile && yarn run test:run",
|
|
||||||
"translations": "node ./scripts/translations.js",
|
"translations": "node ./scripts/translations.js",
|
||||||
"translations:find-unused": "node ./scripts/find-unused-translations.js",
|
"watch": "yarn run watch:app:assets",
|
||||||
"compile": "node ./scripts/compile.js",
|
"watch:app:assets": "node ./scripts/watch.js",
|
||||||
"compile:cljs": "clojure -M:dev:shadow-cljs compile main",
|
"watch:storybook": "concurrently \"clojure -M:dev:shadow-cljs watch storybook\" \"storybook dev -p 6006 --no-open\" \"yarn run watch:storybook:assets\"",
|
||||||
"watch": "node ./scripts/watch.js",
|
"watch:storybook:assets": "node ./scripts/watch-storybook.js"
|
||||||
"e2e:server": "node ./scripts/e2e-server.js",
|
|
||||||
"e2e:test": "playwright test --project default",
|
|
||||||
"storybook:compile": "yarn run compile && clojure -M:dev:shadow-cljs compile storybook",
|
|
||||||
"storybook:server": "yarn run storybook dev -p 6006 --no-open",
|
|
||||||
"storybook:watch": "concurrently \"clojure -M:dev:shadow-cljs watch storybook\" \"yarn run storybook:server\" \"yarn run watch\"",
|
|
||||||
"storybook:build": "yarn run storybook:compile && storybook build"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "1.44.1",
|
"@playwright/test": "1.44.1",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<link href="/css/main.css" rel="stylesheet" type="text/css" />
|
<link href="/css/ds.css?ts={{& ts}}" rel="stylesheet" type="text/css" />
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
|
@ -82,6 +82,31 @@ export async function compileSassDebug(worker) {
|
||||||
return `${result.css}\n`;
|
return `${result.css}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function compileSassStorybook(worker) {
|
||||||
|
const limitFn = pLimit(4);
|
||||||
|
const sourceDir = ph.join("src", "app", "main", "ui", "ds");
|
||||||
|
|
||||||
|
const dsFiles = (await fs.readdir(sourceDir, { recursive: true }))
|
||||||
|
.filter(isSassFile)
|
||||||
|
.map((filename) => ph.join(sourceDir, filename));
|
||||||
|
const procs = [compileSass(worker, "resources/styles/main-default.scss", {})];
|
||||||
|
|
||||||
|
for (let path of dsFiles) {
|
||||||
|
const proc = limitFn(() => compileSass(worker, path, { modules: true }));
|
||||||
|
procs.push(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await Promise.all(procs);
|
||||||
|
return result.reduce(
|
||||||
|
(acc, item) => {
|
||||||
|
acc.index[item.outputPath] = item.css;
|
||||||
|
acc.items.push(item.outputPath);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ index: {}, items: [] },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function compileSassAll(worker) {
|
export async function compileSassAll(worker) {
|
||||||
const limitFn = pLimit(4);
|
const limitFn = pLimit(4);
|
||||||
const sourceDir = "src";
|
const sourceDir = "src";
|
||||||
|
@ -379,6 +404,15 @@ async function generateTemplates() {
|
||||||
);
|
);
|
||||||
await fs.writeFile("./.storybook/preview-body.html", content);
|
await fs.writeFile("./.storybook/preview-body.html", content);
|
||||||
|
|
||||||
|
content = await renderTemplate(
|
||||||
|
"resources/templates/preview-head.mustache",
|
||||||
|
{
|
||||||
|
manifest: manifest,
|
||||||
|
},
|
||||||
|
partials,
|
||||||
|
);
|
||||||
|
await fs.writeFile("./.storybook/preview-head.html", content);
|
||||||
|
|
||||||
content = await renderTemplate("resources/templates/render.mustache", {
|
content = await renderTemplate("resources/templates/render.mustache", {
|
||||||
manifest: manifest,
|
manifest: manifest,
|
||||||
translations: JSON.stringify(translations),
|
translations: JSON.stringify(translations),
|
||||||
|
@ -394,6 +428,22 @@ async function generateTemplates() {
|
||||||
await fs.writeFile("./resources/public/rasterizer.html", content);
|
await fs.writeFile("./resources/public/rasterizer.html", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function compileStorybookStyles() {
|
||||||
|
const worker = startWorker();
|
||||||
|
const start = process.hrtime();
|
||||||
|
|
||||||
|
log.info("init: compile storybook styles");
|
||||||
|
let result = await compileSassStorybook(worker);
|
||||||
|
result = concatSass(result);
|
||||||
|
|
||||||
|
await fs.mkdir("./resources/public/css", { recursive: true });
|
||||||
|
await fs.writeFile("./resources/public/css/ds.css", result);
|
||||||
|
|
||||||
|
const end = process.hrtime(start);
|
||||||
|
log.info("done: compile storybook styles", `(${ppt(end)})`);
|
||||||
|
worker.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
export async function compileStyles() {
|
export async function compileStyles() {
|
||||||
const worker = startWorker();
|
const worker = startWorker();
|
||||||
const start = process.hrtime();
|
const start = process.hrtime();
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
|
export INCLUDE_STORYBOOK=${BUILD_STORYBOOK:-no};
|
||||||
|
|
||||||
export CURRENT_VERSION=$1;
|
export CURRENT_VERSION=$1;
|
||||||
export BUILD_DATE=$(date -R);
|
export BUILD_DATE=$(date -R);
|
||||||
export CURRENT_HASH=${CURRENT_HASH:-$(git rev-parse --short HEAD)};
|
export CURRENT_HASH=${CURRENT_HASH:-$(git rev-parse --short HEAD)};
|
||||||
|
@ -20,9 +22,16 @@ rm -rf target/dist;
|
||||||
|
|
||||||
clojure -M:dev:shadow-cljs release main --config-merge "{:release-version \"${CURRENT_HASH}-${TS}\"}" $EXTRA_PARAMS || exit 1
|
clojure -M:dev:shadow-cljs release main --config-merge "{:release-version \"${CURRENT_HASH}-${TS}\"}" $EXTRA_PARAMS || exit 1
|
||||||
|
|
||||||
yarn run compile || exit 1;
|
yarn run build:app:assets || exit 1;
|
||||||
|
|
||||||
mkdir -p target/dist;
|
mkdir -p target/dist;
|
||||||
rsync -avr resources/public/ target/dist/
|
rsync -avr resources/public/ target/dist/
|
||||||
|
|
||||||
sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./target/dist/index.html;
|
sed -i -re "s/\%version\%/$CURRENT_VERSION/g" ./target/dist/index.html;
|
||||||
sed -i -re "s/\%buildDate\%/$BUILD_DATE/g" ./target/dist/index.html;
|
sed -i -re "s/\%buildDate\%/$BUILD_DATE/g" ./target/dist/index.html;
|
||||||
|
|
||||||
|
if [ "$INCLUDE_STORYBOOK" = "yes"]; then
|
||||||
|
# build storybook
|
||||||
|
yarn run build:storybook || exit 1;
|
||||||
|
rsync -avr storybook-static/ target/dist/storybook-static;
|
||||||
|
fi
|
||||||
|
|
7
frontend/scripts/build-storybook-assets.js
Normal file
7
frontend/scripts/build-storybook-assets.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import * as h from "./_helpers.js";
|
||||||
|
|
||||||
|
await h.compileStorybookStyles();
|
||||||
|
await h.copyAssets();
|
||||||
|
await h.compileSvgSprites();
|
||||||
|
await h.compileTemplates();
|
||||||
|
await h.compilePolyfills();
|
86
frontend/scripts/watch-storybook.js
Normal file
86
frontend/scripts/watch-storybook.js
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import ph from "node:path";
|
||||||
|
|
||||||
|
import log from "fancy-log";
|
||||||
|
import * as h from "./_helpers.js";
|
||||||
|
import ppt from "pretty-time";
|
||||||
|
|
||||||
|
const worker = h.startWorker();
|
||||||
|
let sass = null;
|
||||||
|
|
||||||
|
async function compileSassAll() {
|
||||||
|
const start = process.hrtime();
|
||||||
|
log.info("init: compile storybook styles");
|
||||||
|
|
||||||
|
sass = await h.compileSassStorybook(worker);
|
||||||
|
let output = await h.concatSass(sass);
|
||||||
|
await fs.writeFile("./resources/public/css/ds.css", output);
|
||||||
|
|
||||||
|
const end = process.hrtime(start);
|
||||||
|
log.info("done: compile storybook styles", `(${ppt(end)})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function compileSass(path) {
|
||||||
|
const start = process.hrtime();
|
||||||
|
log.info("changed:", path);
|
||||||
|
const result = await h.compileSass(worker, path, { modules: true });
|
||||||
|
sass.index[result.outputPath] = result.css;
|
||||||
|
|
||||||
|
const output = h.concatSass(sass);
|
||||||
|
await fs.writeFile("./resources/public/css/ds.css", output);
|
||||||
|
|
||||||
|
const end = process.hrtime(start);
|
||||||
|
log.info("done:", `(${ppt(end)})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.mkdir("./resources/public/css/", { recursive: true });
|
||||||
|
await compileSassAll();
|
||||||
|
await h.copyAssets();
|
||||||
|
await h.compileSvgSprites();
|
||||||
|
await h.compileTemplates();
|
||||||
|
await h.compilePolyfills();
|
||||||
|
|
||||||
|
log.info("watch: scss src (~)");
|
||||||
|
|
||||||
|
h.watch("src", h.isSassFile, async function (path) {
|
||||||
|
const isPartial = ph.basename(path).startsWith("_");
|
||||||
|
const isCommon = isPartial || ph.dirname(path).endsWith("/ds");
|
||||||
|
|
||||||
|
if (isCommon) {
|
||||||
|
await compileSassAll(path);
|
||||||
|
} else {
|
||||||
|
await compileSass(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("watch: scss: resources (~)");
|
||||||
|
h.watch("resources/styles", h.isSassFile, async function (path) {
|
||||||
|
log.info("changed:", path);
|
||||||
|
await compileSassAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("watch: templates (~)");
|
||||||
|
h.watch("resources/templates", null, async function (path) {
|
||||||
|
log.info("changed:", path);
|
||||||
|
await h.compileTemplates();
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("watch: translations (~)");
|
||||||
|
h.watch("translations", null, async function (path) {
|
||||||
|
log.info("changed:", path);
|
||||||
|
await h.compileTemplates();
|
||||||
|
});
|
||||||
|
|
||||||
|
log.info("watch: assets (~)");
|
||||||
|
h.watch(
|
||||||
|
["resources/images", "resources/fonts", "resources/plugins-runtime"],
|
||||||
|
null,
|
||||||
|
async function (path) {
|
||||||
|
log.info("changed:", path);
|
||||||
|
await h.compileSvgSprites();
|
||||||
|
await h.copyAssets();
|
||||||
|
await h.compileTemplates();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
worker.terminate();
|
|
@ -93,7 +93,7 @@
|
||||||
{:entries []}
|
{:entries []}
|
||||||
|
|
||||||
:components
|
:components
|
||||||
{:exports {:default app.main.ui.ds/default}
|
{:exports {default app.main.ui.ds/default}
|
||||||
:depends-on #{:base}}}
|
:depends-on #{:base}}}
|
||||||
|
|
||||||
:compiler-options
|
:compiler-options
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import { configDefaults } from 'vitest/config'
|
import { configDefaults } from "vitest/config";
|
||||||
|
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
exclude: [...configDefaults.exclude, 'target/**', 'resources/**'],
|
exclude: [...configDefaults.exclude, "target/**", "resources/**"],
|
||||||
environment: 'jsdom'
|
environment: "jsdom",
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@target": resolve(__dirname, "./target/storybook"),
|
"@target": resolve(__dirname, "./target/storybook"),
|
||||||
|
|
Loading…
Add table
Reference in a new issue