create-absolutejs 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/formatProject.d.ts +4 -2
- package/dist/commands/formatProject.js +21 -0
- package/dist/commands/installDependencies.js +19 -0
- package/dist/constants.js +4 -0
- package/dist/data.js +125 -0
- package/dist/generators/configurations/addConfigurationFiles.js +21 -0
- package/dist/generators/configurations/generateDrizzleConfig.js +11 -0
- package/dist/generators/configurations/generatePackageJson.js +74 -0
- package/dist/generators/configurations/generatePrettierrc.js +13 -0
- package/dist/generators/configurations/initializeRoot.js +26 -0
- package/dist/generators/db/scaffoldDatabase.js +16 -0
- package/dist/generators/html/scaffoldHTML.js +14 -0
- package/dist/generators/htmx/scaffoldHTMX.js +15 -0
- package/dist/generators/project/generateMarkupCSS.js +133 -0
- package/dist/generators/project/generateServer.js +159 -0
- package/dist/generators/project/scaffoldFrontends.js +71 -0
- package/dist/generators/react/scaffoldReact.js +14 -0
- package/dist/generators/svelte/scaffoldSvelte.js +13 -0
- package/dist/generators/vue/scaffoldVue.js +8 -0
- package/dist/index.js +23 -2464
- package/dist/messages.js +84 -0
- package/dist/prompt.js +84 -0
- package/dist/questions/authProvider.js +15 -0
- package/dist/questions/codeQualityTool.js +18 -0
- package/dist/questions/configurationType.js +15 -0
- package/dist/questions/databaseEngine.js +24 -0
- package/dist/questions/databaseHost.js +51 -0
- package/dist/questions/directoryConfiguration.js +77 -0
- package/dist/questions/frontendDirectoryConfigurations.js +29 -0
- package/dist/questions/frontends.js +16 -0
- package/dist/questions/htmlScriptingOption.js +10 -0
- package/dist/questions/initializeGitNow.js +10 -0
- package/dist/questions/installDependenciesNow.js +10 -0
- package/dist/questions/orm.js +16 -0
- package/dist/questions/plugins.js +13 -0
- package/dist/questions/projectName.js +11 -0
- package/dist/questions/useTailwind.js +8 -0
- package/dist/scaffold.js +70 -0
- package/dist/typeGuards.js +24 -0
- package/dist/types.js +1 -0
- package/dist/utils/abort.js +8 -0
- package/dist/utils/commandMaps.d.ts +3 -1
- package/dist/utils/commandMaps.js +18 -0
- package/dist/utils/getPackageVersion.js +12 -0
- package/dist/utils/parseCommandLineOptions.js +170 -0
- package/dist/utils/t3-utils.js +24 -0
- package/package.json +2 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { PackageManager } from '../types';
|
|
1
2
|
type FormatProjectProps = {
|
|
2
3
|
projectName: string;
|
|
3
|
-
packageManager:
|
|
4
|
+
packageManager: PackageManager;
|
|
5
|
+
installDependenciesNow: boolean;
|
|
4
6
|
};
|
|
5
|
-
export declare const formatProject: ({ projectName, packageManager }: FormatProjectProps) => void;
|
|
7
|
+
export declare const formatProject: ({ projectName, packageManager, installDependenciesNow }: FormatProjectProps) => void;
|
|
6
8
|
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { exit } from 'process';
|
|
3
|
+
import { spinner } from '@clack/prompts';
|
|
4
|
+
import { green, red } from 'picocolors';
|
|
5
|
+
import { formatCommands, formatNoInstallCommands } from '../utils/commandMaps';
|
|
6
|
+
export const formatProject = ({ projectName, packageManager, installDependenciesNow }) => {
|
|
7
|
+
const spin = spinner();
|
|
8
|
+
try {
|
|
9
|
+
const fmt = installDependenciesNow
|
|
10
|
+
? formatCommands[packageManager]
|
|
11
|
+
: formatNoInstallCommands[packageManager];
|
|
12
|
+
spin.start('Formatting files…');
|
|
13
|
+
execSync(fmt, { cwd: projectName, stdio: 'pipe' });
|
|
14
|
+
spin.stop(green('Files formatted'));
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
spin.stop(red('Failed to format files'), 1);
|
|
18
|
+
console.error('Error formatting:', err);
|
|
19
|
+
exit(1);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { exit } from 'process';
|
|
3
|
+
import { spinner } from '@clack/prompts';
|
|
4
|
+
import { green, red } from 'picocolors';
|
|
5
|
+
import { installCommands } from '../utils/commandMaps';
|
|
6
|
+
export const installDependencies = async ({ projectName, packageManager }) => {
|
|
7
|
+
const spin = spinner();
|
|
8
|
+
const cmd = installCommands[packageManager] ?? 'bun install';
|
|
9
|
+
try {
|
|
10
|
+
spin.start('Installing dependencies…');
|
|
11
|
+
execSync(cmd, { cwd: projectName, stdio: 'pipe' });
|
|
12
|
+
spin.stop(green('Dependencies installed'));
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
spin.stop(red('Installation failed'), 1);
|
|
16
|
+
console.error('Error installing dependencies:', err);
|
|
17
|
+
exit(1);
|
|
18
|
+
}
|
|
19
|
+
};
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { cyan, green, magenta } from 'picocolors';
|
|
2
|
+
export const availableFrontends = [
|
|
3
|
+
'react',
|
|
4
|
+
'html',
|
|
5
|
+
'svelte',
|
|
6
|
+
// 'angular',
|
|
7
|
+
'vue',
|
|
8
|
+
'htmx'
|
|
9
|
+
];
|
|
10
|
+
export const availableAuthProviders = ['absoluteAuth', 'none'];
|
|
11
|
+
export const availableDatabaseEngines = [
|
|
12
|
+
'postgresql',
|
|
13
|
+
'mysql',
|
|
14
|
+
'sqlite',
|
|
15
|
+
'mongodb',
|
|
16
|
+
'redis',
|
|
17
|
+
'singlestore',
|
|
18
|
+
'cockroachdb',
|
|
19
|
+
'mssql',
|
|
20
|
+
'none'
|
|
21
|
+
];
|
|
22
|
+
export const availableDirectoryConfigurations = ['default', 'custom'];
|
|
23
|
+
export const availableORMs = ['drizzle', 'prisma', 'none'];
|
|
24
|
+
export const availableDatabaseHosts = [
|
|
25
|
+
'neon',
|
|
26
|
+
'planetscale',
|
|
27
|
+
'supabase',
|
|
28
|
+
'turso',
|
|
29
|
+
'vercel',
|
|
30
|
+
'upstash',
|
|
31
|
+
'atlas',
|
|
32
|
+
'none'
|
|
33
|
+
];
|
|
34
|
+
export const availableCodeQualityTools = ['eslint+prettier', 'biome'];
|
|
35
|
+
/* eslint-disable absolute/sort-keys-fixable */
|
|
36
|
+
export const frontendLabels = {
|
|
37
|
+
react: cyan('React'),
|
|
38
|
+
html: 'HTML',
|
|
39
|
+
htmx: 'HTMX',
|
|
40
|
+
svelte: magenta('Svelte'),
|
|
41
|
+
vue: green('Vue')
|
|
42
|
+
// angular: red('Angular'),
|
|
43
|
+
};
|
|
44
|
+
/* eslint-enable absolute/sort-keys-fixable */
|
|
45
|
+
export const availablePlugins = [
|
|
46
|
+
{
|
|
47
|
+
imports: [{ config: null, isPlugin: true, packageName: 'cors' }],
|
|
48
|
+
label: cyan('⚙️ @elysiajs/cors'),
|
|
49
|
+
latestVersion: '1.3.3',
|
|
50
|
+
value: '@elysiajs/cors'
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
imports: [{ config: null, isPlugin: true, packageName: 'swagger' }],
|
|
54
|
+
label: cyan('📑 @elysiajs/swagger'),
|
|
55
|
+
latestVersion: '1.3.0',
|
|
56
|
+
value: '@elysiajs/swagger'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
imports: [{ config: null, isPlugin: true, packageName: 'rateLimit' }],
|
|
60
|
+
label: green('🛠️ elysia-rate-limit'),
|
|
61
|
+
latestVersion: '4.3.0',
|
|
62
|
+
value: 'elysia-rate-limit'
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
export const absoluteAuthPlugin = {
|
|
66
|
+
imports: [
|
|
67
|
+
{
|
|
68
|
+
config: { providersConfiguration: {} },
|
|
69
|
+
isPlugin: true,
|
|
70
|
+
packageName: 'absoluteAuth'
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
latestVersion: '0.3.2',
|
|
74
|
+
value: '@absolutejs/auth'
|
|
75
|
+
};
|
|
76
|
+
export const scopedStatePlugin = {
|
|
77
|
+
imports: [
|
|
78
|
+
{
|
|
79
|
+
config: { count: { value: 0 } },
|
|
80
|
+
isPlugin: true,
|
|
81
|
+
packageName: 'scopedState'
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
latestVersion: '0.1.1',
|
|
85
|
+
value: 'elysia-scoped-state'
|
|
86
|
+
};
|
|
87
|
+
export const eslintAndPrettierDependencies = [
|
|
88
|
+
{
|
|
89
|
+
latestVersion: '9.27.0',
|
|
90
|
+
value: 'eslint'
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
latestVersion: '3.5.3',
|
|
94
|
+
value: 'prettier'
|
|
95
|
+
}
|
|
96
|
+
];
|
|
97
|
+
export const defaultDependencies = [
|
|
98
|
+
{
|
|
99
|
+
imports: [{ isPlugin: false, packageName: 'Elysia' }],
|
|
100
|
+
latestVersion: '1.3.1',
|
|
101
|
+
value: 'elysia'
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
export const defaultPlugins = [
|
|
105
|
+
{
|
|
106
|
+
imports: [
|
|
107
|
+
{ isPlugin: false, packageName: 'asset' },
|
|
108
|
+
{ isPlugin: false, packageName: 'build' },
|
|
109
|
+
{ isPlugin: true, packageName: 'networking' }
|
|
110
|
+
],
|
|
111
|
+
latestVersion: '0.11.1',
|
|
112
|
+
value: '@absolutejs/absolute'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
imports: [
|
|
116
|
+
{
|
|
117
|
+
config: { assets: './build', prefix: '' },
|
|
118
|
+
isPlugin: true,
|
|
119
|
+
packageName: 'staticPlugin'
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
latestVersion: '1.3.0',
|
|
123
|
+
value: '@elysiajs/static'
|
|
124
|
+
}
|
|
125
|
+
];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { copyFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { dim, yellow } from 'picocolors';
|
|
4
|
+
import { generatePrettierrc } from './generatePrettierrc';
|
|
5
|
+
export const addConfigurationFiles = ({ tailwind, templatesDirectory, codeQualityTool, frontends, initializeGitNow, projectName }) => {
|
|
6
|
+
copyFileSync(join(templatesDirectory, 'configurations', 'tsconfig.example.json'), join(projectName, 'tsconfig.json'));
|
|
7
|
+
if (tailwind) {
|
|
8
|
+
copyFileSync(join(templatesDirectory, 'tailwind', 'postcss.config.ts'), join(projectName, 'postcss.config.ts'));
|
|
9
|
+
copyFileSync(join(templatesDirectory, 'tailwind', 'tailwind.config.ts'), join(projectName, 'tailwind.config.ts'));
|
|
10
|
+
}
|
|
11
|
+
if (initializeGitNow)
|
|
12
|
+
copyFileSync(join(templatesDirectory, 'git', 'gitignore'), join(projectName, '.gitignore'));
|
|
13
|
+
if (codeQualityTool === 'eslint+prettier') {
|
|
14
|
+
copyFileSync(join(templatesDirectory, 'configurations', 'eslint.config.mjs'), join(projectName, 'eslint.config.mjs'));
|
|
15
|
+
copyFileSync(join(templatesDirectory, 'configurations', '.prettierignore'), join(projectName, '.prettierignore'));
|
|
16
|
+
const prettierrc = generatePrettierrc(frontends);
|
|
17
|
+
writeFileSync(join(projectName, '.prettierrc.json'), prettierrc);
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
console.warn(`${dim('│')}\n${yellow('▲')} Biome support not implemented yet`);
|
|
21
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export const createDrizzleConfig = ({ projectName, databaseEngine }) => {
|
|
4
|
+
const drizzleConfig = `import { defineConfig } from "drizzle-kit";
|
|
5
|
+
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
dialect: '${databaseEngine}'
|
|
8
|
+
});
|
|
9
|
+
`;
|
|
10
|
+
writeFileSync(join(projectName, 'drizzle.config.ts'), drizzleConfig);
|
|
11
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { spinner } from '@clack/prompts';
|
|
4
|
+
import { green } from 'picocolors';
|
|
5
|
+
import { absoluteAuthPlugin, availablePlugins, defaultPlugins, eslintAndPrettierDependencies } from '../../data';
|
|
6
|
+
import { getPackageVersion } from '../../utils/getPackageVersion';
|
|
7
|
+
export const createPackageJson = ({ projectName, authProvider, plugins, useTailwind, latest, frontendDirectories, codeQualityTool }) => {
|
|
8
|
+
const s = spinner();
|
|
9
|
+
void (latest && s.start('Resolving package versions…'));
|
|
10
|
+
const resolveVersion = (name, listed) => latest ? (getPackageVersion(name) ?? listed) : listed;
|
|
11
|
+
const dependencies = {};
|
|
12
|
+
const devDependencies = {};
|
|
13
|
+
const requiresReact = frontendDirectories['react'] !== undefined;
|
|
14
|
+
const requiresSvelte = frontendDirectories['svelte'] !== undefined;
|
|
15
|
+
const requiresVue = frontendDirectories['vue'] !== undefined;
|
|
16
|
+
const requiresHtmx = frontendDirectories['htmx'] !== undefined;
|
|
17
|
+
for (const p of defaultPlugins) {
|
|
18
|
+
dependencies[p.value] = resolveVersion(p.value, p.latestVersion);
|
|
19
|
+
}
|
|
20
|
+
if (authProvider === 'absoluteAuth') {
|
|
21
|
+
dependencies[absoluteAuthPlugin.value] = resolveVersion(absoluteAuthPlugin.value, absoluteAuthPlugin.latestVersion);
|
|
22
|
+
}
|
|
23
|
+
for (const pluginValue of plugins) {
|
|
24
|
+
const meta = availablePlugins.find((p) => p.value === pluginValue);
|
|
25
|
+
if (!meta)
|
|
26
|
+
continue;
|
|
27
|
+
dependencies[meta.value] = resolveVersion(meta.value, meta.latestVersion);
|
|
28
|
+
}
|
|
29
|
+
if (codeQualityTool === 'eslint+prettier') {
|
|
30
|
+
eslintAndPrettierDependencies.forEach((dep) => {
|
|
31
|
+
devDependencies[dep.value] = resolveVersion(dep.value, dep.latestVersion);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (useTailwind) {
|
|
35
|
+
devDependencies['autoprefixer'] = resolveVersion('autoprefixer', '10.4.21');
|
|
36
|
+
devDependencies['postcss'] = resolveVersion('postcss', '8.5.3');
|
|
37
|
+
devDependencies['tailwindcss'] = resolveVersion('tailwindcss', '4.1.7');
|
|
38
|
+
devDependencies['@tailwindcss/cli'] = resolveVersion('@tailwindcss/cli', '4.1.7');
|
|
39
|
+
}
|
|
40
|
+
if (requiresReact) {
|
|
41
|
+
dependencies['react'] = resolveVersion('react', '19.1.0');
|
|
42
|
+
dependencies['react-dom'] = resolveVersion('react-dom', '19.1.0');
|
|
43
|
+
devDependencies['@types/react'] = resolveVersion('@types/react', '19.1.5');
|
|
44
|
+
devDependencies['@types/react-dom'] = resolveVersion('@types/react-dom', '19.1.5');
|
|
45
|
+
}
|
|
46
|
+
if (requiresSvelte) {
|
|
47
|
+
dependencies['svelte'] = resolveVersion('svelte', '5.34.7');
|
|
48
|
+
void (codeQualityTool === 'eslint+prettier' &&
|
|
49
|
+
(devDependencies['prettier-plugin-svelte'] = resolveVersion('prettier-plugin-svelte', '3.4.0')));
|
|
50
|
+
}
|
|
51
|
+
if (requiresVue) {
|
|
52
|
+
dependencies['vue'] = resolveVersion('vue', '3.5.17');
|
|
53
|
+
}
|
|
54
|
+
if (requiresHtmx) {
|
|
55
|
+
dependencies['elysia-scoped-state'] = resolveVersion('elysia-scoped-state', '0.1.1');
|
|
56
|
+
}
|
|
57
|
+
void (latest && s.stop(green('Package versions resolved')));
|
|
58
|
+
const scripts = {
|
|
59
|
+
dev: 'bun run --watch src/backend/server.ts',
|
|
60
|
+
format: `prettier --write "./**/*.{js,ts,css,json,mjs,md${requiresReact ? ',jsx,tsx' : ''}${requiresSvelte ? ',svelte' : ''}${requiresVue ? ',vue' : ''}}"`,
|
|
61
|
+
lint: 'eslint ./src',
|
|
62
|
+
test: 'echo "Error: no test specified" && exit 1',
|
|
63
|
+
typecheck: 'bun run tsc --noEmit'
|
|
64
|
+
};
|
|
65
|
+
const packageJson = {
|
|
66
|
+
dependencies,
|
|
67
|
+
devDependencies,
|
|
68
|
+
name: projectName,
|
|
69
|
+
scripts,
|
|
70
|
+
type: 'module',
|
|
71
|
+
version: '0.0.0'
|
|
72
|
+
};
|
|
73
|
+
writeFileSync(join(projectName, 'package.json'), JSON.stringify(packageJson));
|
|
74
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const generatePrettierrc = (frontends) => {
|
|
2
|
+
const usesSvelte = frontends.some((frontend) => frontend === 'svelte');
|
|
3
|
+
return `{
|
|
4
|
+
"endOfLine": "auto",
|
|
5
|
+
"printWidth": 80,
|
|
6
|
+
"semi": true,
|
|
7
|
+
"singleQuote": true,
|
|
8
|
+
"tabWidth": 4,
|
|
9
|
+
"trailingComma": "none",
|
|
10
|
+
"useTabs": true
|
|
11
|
+
${usesSvelte ? `,"plugins": ["prettier-plugin-svelte"],\n"overrides": [{"files": "*.svelte", "options": {"parser": "svelte"}}]` : ''}
|
|
12
|
+
}`;
|
|
13
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const initalizeRoot = (projectName, templatesDirectory) => {
|
|
4
|
+
if (existsSync(projectName)) {
|
|
5
|
+
throw new Error(`Cannot create project "${projectName}": directory already exists.`);
|
|
6
|
+
}
|
|
7
|
+
mkdirSync(projectName);
|
|
8
|
+
const srcDir = join(projectName, 'src');
|
|
9
|
+
mkdirSync(srcDir);
|
|
10
|
+
mkdirSync(join(srcDir, 'types'));
|
|
11
|
+
const constantsSrc = join(templatesDirectory, 'constants.ts');
|
|
12
|
+
const constantsDest = join(srcDir, 'constants.ts');
|
|
13
|
+
copyFileSync(constantsSrc, constantsDest);
|
|
14
|
+
const frontendDirectory = join(srcDir, 'frontend');
|
|
15
|
+
const backendDirectory = join(srcDir, 'backend');
|
|
16
|
+
mkdirSync(frontendDirectory);
|
|
17
|
+
mkdirSync(backendDirectory);
|
|
18
|
+
const projectAssetsDirectory = join(backendDirectory, 'assets');
|
|
19
|
+
mkdirSync(projectAssetsDirectory);
|
|
20
|
+
mkdirSync(join(projectAssetsDirectory, 'ico'), { recursive: true });
|
|
21
|
+
mkdirSync(join(projectAssetsDirectory, 'png'), { recursive: true });
|
|
22
|
+
mkdirSync(join(projectAssetsDirectory, 'svg'), { recursive: true });
|
|
23
|
+
copyFileSync(join(templatesDirectory, 'assets', 'ico', 'favicon.ico'), join(projectAssetsDirectory, 'ico', 'favicon.ico'));
|
|
24
|
+
copyFileSync(join(templatesDirectory, 'assets', 'png', 'absolutejs-temp.png'), join(projectAssetsDirectory, 'png', 'absolutejs-temp.png'));
|
|
25
|
+
return { backendDirectory, frontendDirectory, projectAssetsDirectory };
|
|
26
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { mkdirSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { dim, yellow } from 'picocolors';
|
|
4
|
+
import { createDrizzleConfig } from '../configurations/generateDrizzleConfig';
|
|
5
|
+
export const scaffoldDatabase = ({ projectName, databaseEngine, databaseDirectory, orm }) => {
|
|
6
|
+
mkdirSync(join(projectName, databaseDirectory), { recursive: true });
|
|
7
|
+
if (databaseEngine !== 'postgresql' && databaseEngine !== 'none') {
|
|
8
|
+
console.warn(`${dim('│')}\n${yellow('▲')} Only PostgreSQL support is implemented so far`);
|
|
9
|
+
}
|
|
10
|
+
if (orm === 'drizzle') {
|
|
11
|
+
createDrizzleConfig({ databaseEngine, projectName });
|
|
12
|
+
}
|
|
13
|
+
if (orm === 'prisma') {
|
|
14
|
+
console.warn(`${dim('│')}\n${yellow('▲')} Prisma support is not implemented yet`);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { generateMarkupCSS } from '../project/generateMarkupCSS';
|
|
4
|
+
export const scaffoldHTML = ({ isSingleFrontend, targetDirectory, useHTMLScripts, templatesDirectory, projectAssetsDirectory }) => {
|
|
5
|
+
copyFileSync(join(templatesDirectory, 'assets', 'svg', 'HTML5_Badge.svg'), join(projectAssetsDirectory, 'svg', 'HTML5_Badge.svg'));
|
|
6
|
+
cpSync(join(templatesDirectory, 'html'), targetDirectory, {
|
|
7
|
+
recursive: true
|
|
8
|
+
});
|
|
9
|
+
const cssOutputDir = join(targetDirectory, 'styles');
|
|
10
|
+
mkdirSync(cssOutputDir, { recursive: true });
|
|
11
|
+
const cssOutputFile = join(cssOutputDir, 'html-example.css');
|
|
12
|
+
const htmlCSS = generateMarkupCSS(isSingleFrontend);
|
|
13
|
+
writeFileSync(cssOutputFile, htmlCSS, 'utf-8');
|
|
14
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { generateMarkupCSS } from '../project/generateMarkupCSS';
|
|
4
|
+
export const scaffoldHTMX = ({ targetDirectory, templatesDirectory, projectAssetsDirectory, isSingleFrontend }) => {
|
|
5
|
+
copyFileSync(join(templatesDirectory, 'assets', 'svg', 'htmx-logo-black.svg'), join(projectAssetsDirectory, 'svg', 'htmx-logo-black.svg'));
|
|
6
|
+
copyFileSync(join(templatesDirectory, 'assets', 'svg', 'htmx-logo-white.svg'), join(projectAssetsDirectory, 'svg', 'htmx-logo-white.svg'));
|
|
7
|
+
cpSync(join(templatesDirectory, 'htmx'), targetDirectory, {
|
|
8
|
+
recursive: true
|
|
9
|
+
});
|
|
10
|
+
const cssOutputDir = join(targetDirectory, 'styles');
|
|
11
|
+
mkdirSync(cssOutputDir, { recursive: true });
|
|
12
|
+
const cssOutputFile = join(cssOutputDir, 'htmx-example.css');
|
|
13
|
+
const htmxCSS = generateMarkupCSS(isSingleFrontend);
|
|
14
|
+
writeFileSync(cssOutputFile, htmxCSS, 'utf-8');
|
|
15
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export const generateMarkupCSS = (isSingleFrontend) => `@import url('${isSingleFrontend ? '../styles/reset.css' : '../../styles/reset.css'}');
|
|
2
|
+
|
|
3
|
+
header {
|
|
4
|
+
align-items: center;
|
|
5
|
+
background-color: #1a1a1a;
|
|
6
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
padding: 2rem;
|
|
10
|
+
text-align: center;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
header a {
|
|
14
|
+
position: relative;
|
|
15
|
+
color: #5fbeeb;
|
|
16
|
+
text-decoration: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
header a::after {
|
|
20
|
+
content: '';
|
|
21
|
+
position: absolute;
|
|
22
|
+
left: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: 2px;
|
|
26
|
+
background: linear-gradient(90deg, #5fbeeb 0%, #35d5a2 50%, #ff4b91 100%);
|
|
27
|
+
transform: scaleX(0);
|
|
28
|
+
transform-origin: left;
|
|
29
|
+
transition: transform 0.25s ease-in-out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
header a:hover::after {
|
|
33
|
+
transform: scaleX(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
h1 {
|
|
37
|
+
font-size: 2.5rem;
|
|
38
|
+
margin-top: 2rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.logo {
|
|
42
|
+
height: 8rem;
|
|
43
|
+
width: 8rem;
|
|
44
|
+
will-change: filter;
|
|
45
|
+
transition: filter 300ms;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.logo:hover {
|
|
49
|
+
filter: drop-shadow(0 0 2rem #5fbeeb);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.logo.html:hover {
|
|
53
|
+
filter: drop-shadow(0 0 2rem #e34f26);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
nav {
|
|
57
|
+
display: flex;
|
|
58
|
+
gap: 4rem;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
header details {
|
|
63
|
+
position: relative;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
header details summary {
|
|
67
|
+
list-style: none;
|
|
68
|
+
appearance: none;
|
|
69
|
+
-webkit-appearance: none;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
user-select: none;
|
|
72
|
+
color: #5fbeeb;
|
|
73
|
+
font-size: 1.5rem;
|
|
74
|
+
font-weight: 500;
|
|
75
|
+
padding: 0.5rem 1rem;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
header summary::after {
|
|
79
|
+
content: '▼';
|
|
80
|
+
display: inline-block;
|
|
81
|
+
margin-left: 0.5rem;
|
|
82
|
+
font-size: 0.75rem;
|
|
83
|
+
transition: transform 0.3s ease;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
header details[open] summary::after {
|
|
87
|
+
transform: rotate(180deg);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
header details nav {
|
|
91
|
+
position: absolute;
|
|
92
|
+
top: 100%;
|
|
93
|
+
right: -0.5rem;
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
gap: 0.75rem;
|
|
97
|
+
background: rgba(185, 185, 185, 0.1);
|
|
98
|
+
backdrop-filter: blur(4px);
|
|
99
|
+
border: 1px solid #5fbeeb;
|
|
100
|
+
border-radius: 1rem;
|
|
101
|
+
padding: 1rem 1.5rem;
|
|
102
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
103
|
+
opacity: 0;
|
|
104
|
+
transform: translateY(-8px);
|
|
105
|
+
pointer-events: none;
|
|
106
|
+
transition:
|
|
107
|
+
opacity 0.3s ease,
|
|
108
|
+
transform 0.3s ease;
|
|
109
|
+
z-index: 1000;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
header details[open] nav {
|
|
113
|
+
opacity: 1;
|
|
114
|
+
transform: translateY(0);
|
|
115
|
+
pointer-events: auto;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
header details nav a {
|
|
119
|
+
font-size: 1.1rem;
|
|
120
|
+
padding: 0.25rem 0;
|
|
121
|
+
white-space: nowrap;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@media (prefers-color-scheme: light) {
|
|
125
|
+
header {
|
|
126
|
+
background-color: #ffffff;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
button {
|
|
130
|
+
background-color: #ffffff;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
`;
|