feat(frontend): configure vendor build scripts and fallback templates

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-10-04 23:04:45 +03:00
co-authored by Junie
parent 73f68e9a2f
commit 1cc070b7c0
7 changed files with 305 additions and 28 deletions
+16 -16
View File
@@ -1,24 +1,24 @@
#!/usr/bin/bash
#!/usr/bin/env bash
set -e
# Необходимо предварительно установить NPM и esbuild:
# Переходим в директорию скрипта
cd "$(dirname "$0")"
# Необходимо предварительно установить Node.js и npm:
# Для Ubuntu/Debian:
# sudo apt install npm
# npm install -g esbuild
# sudo apt install nodejs npm
# Для MacOS (через Homebrew):
# brew install npm
# npm install -g esbuild
# brew install node
# Для Windows:
# Скачайте и установите Node.js с официального сайта: https://nodejs.org/
# Затем установите esbuild глобально:
# npm install -g esbuild
# Устанавливаем CodeMirror и необходимые пакеты
npm install \ [±main ●●]
@codemirror/lang-html \
@codemirror/theme-one-dark \
@codemirror/commands \
@codemirror/language
# Устанавливаем зависимости
npm install
# Собираем js в каталог ./public/static/codemirror/editor.js с помощью esbuild
npx esbuild src/editor.js --bundle --format=esm --outfile=../public/static/codemirror/editor.js
# Собираем всё (CodeMirror и копирование вендорных библиотек в public/static/vendor/)
npm run build
# Подчищаем за собой node_modules
echo "Очистка node_modules..."
rm -rf node_modules
+78
View File
@@ -0,0 +1,78 @@
const fs = require('fs');
const path = require('path');
// Целевая папка для статики вендоров
const targetDir = path.resolve(__dirname, '../public/static/vendor');
// Список файлов и директорий для копирования
const itemsToCopy = [
// Bootstrap 5 (CSS & JS bundle)
{
src: 'node_modules/bootstrap/dist/css/bootstrap.min.css',
dest: 'bootstrap/bootstrap.min.css'
},
{
src: 'node_modules/bootstrap/dist/css/bootstrap.min.css.map',
dest: 'bootstrap/bootstrap.min.css.map'
},
{
src: 'node_modules/bootstrap/dist/js/bootstrap.bundle.min.js',
dest: 'bootstrap/bootstrap.bundle.min.js'
},
{
src: 'node_modules/bootstrap/dist/js/bootstrap.bundle.min.js.map',
dest: 'bootstrap/bootstrap.bundle.min.js.map'
},
// Bootstrap Icons (CSS & WOFF/WOFF2 шрифты)
{
src: 'node_modules/bootstrap-icons/font/bootstrap-icons.min.css',
dest: 'bootstrap-icons/bootstrap-icons.min.css'
},
{
src: 'node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff2',
dest: 'bootstrap-icons/fonts/bootstrap-icons.woff2'
},
{
src: 'node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff',
dest: 'bootstrap-icons/fonts/bootstrap-icons.woff'
},
// HTMX
{
src: 'node_modules/htmx.org/dist/htmx.min.js',
dest: 'htmx/htmx.min.js'
},
// Alpine.js
{
src: 'node_modules/alpinejs/dist/cdn.min.js',
dest: 'alpinejs/cdn.min.js'
}
];
console.log('Сборка и копирование вендорных библиотек в static/vendor/...');
let copiedCount = 0;
for (const item of itemsToCopy) {
const srcPath = path.resolve(__dirname, item.src);
const destPath = path.join(targetDir, item.dest);
if (!fs.existsSync(srcPath)) {
console.warn(`Предупреждение: исходный файл не найден: ${item.src}`);
continue;
}
// Создаем папку назначения, если не существует
const destDirPath = path.dirname(destPath);
if (!fs.existsSync(destDirPath)) {
fs.mkdirSync(destDirPath, { recursive: true });
}
fs.copyFileSync(srcPath, destPath);
console.log(` Скопировано: ${item.src} -> ${path.relative(path.resolve(__dirname, '..'), destPath)}`);
copiedCount++;
}
console.log(`Успешно скопировано файлов: ${copiedCount}`);
+83 -3
View File
@@ -1,11 +1,11 @@
{
"name": "tmp-frontend",
"name": "frontend-assembly",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tmp-frontend",
"name": "frontend-assembly",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
@@ -13,7 +13,11 @@
"@codemirror/lang-html": "^6.4.11",
"@codemirror/language": "^6.12.1",
"@codemirror/theme-one-dark": "^6.1.3",
"codemirror": "^6.0.2"
"alpinejs": "^3.14.8",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"codemirror": "^6.0.2",
"htmx.org": "^1.9.12"
},
"devDependencies": {
"esbuild": "^0.27.2"
@@ -662,6 +666,76 @@
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"license": "MIT"
},
"node_modules/@popperjs/core": {
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@vue/reactivity": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
"integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.1.5"
}
},
"node_modules/@vue/shared": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz",
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==",
"license": "MIT"
},
"node_modules/alpinejs": {
"version": "3.14.8",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.8.tgz",
"integrity": "sha512-wT2fuP2DXpGk/jKaglwy7S/IJpm1FD+b7U6zUrhwErjoq5h27S4dxkJEXVvhbdwyPv9U+3OkUuNLkZT4h2Kfrg==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "~3.1.1"
}
},
"node_modules/bootstrap": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT",
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/bootstrap-icons": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz",
"integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT"
},
"node_modules/codemirror": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz",
@@ -725,6 +799,12 @@
"@esbuild/win32-x64": "0.27.2"
}
},
"node_modules/htmx.org": {
"version": "1.9.12",
"resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.12.tgz",
"integrity": "sha512-VZAohXyF7xPGS52IM8d1T1283y+X4D+Owf3qY1NZ9RuBypyu9l8cGsxUMAG5fEAb/DhT7rDoJ9Hpu5/HxFD3cw==",
"license": "0BSD"
},
"node_modules/style-mod": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
+9 -3
View File
@@ -4,8 +4,10 @@
"description": "CodeMirror build for ETPGRF",
"main": "index.js",
"scripts": {
"build": "esbuild src/editor.js --bundle --format=esm --outfile=dist/editor.js --minify",
"dev": "esbuild src/editor.js --bundle --format=esm --outfile=../public/static/codemirror/editor.js --minify",
"build:codemirror": "esbuild src/editor.js --bundle --format=esm --outfile=../public/static/codemirror/editor.js --minify",
"build:vendor": "node copy-vendor.js",
"build": "npm run build:codemirror && npm run build:vendor",
"dev": "npm run build",
"watch": "esbuild src/editor.js --bundle --format=esm --outfile=../public/static/codemirror/editor.js --watch"
},
"keywords": [],
@@ -17,7 +19,11 @@
"@codemirror/lang-html": "^6.4.11",
"@codemirror/language": "^6.12.1",
"@codemirror/theme-one-dark": "^6.1.3",
"codemirror": "^6.0.2"
"alpinejs": "^3.14.8",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"codemirror": "^6.0.2",
"htmx.org": "^1.9.12"
},
"devDependencies": {
"esbuild": "^0.27.2"