buner 0.0.2 → 1.0.1

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.
Files changed (177) hide show
  1. package/.env +15 -0
  2. package/.env.development +6 -0
  3. package/.env.eshn +5 -0
  4. package/README.md +141 -5
  5. package/bin/buner.js +566 -0
  6. package/cli/README.md +1 -0
  7. package/cli/buner.ts +234 -0
  8. package/cli/cli.ts +125 -0
  9. package/cli/create-app.ts +59 -0
  10. package/cli/helpers/copy.ts +62 -0
  11. package/cli/helpers/format-files.ts +189 -0
  12. package/cli/helpers/git.ts +77 -0
  13. package/cli/helpers/install.ts +26 -0
  14. package/cli/helpers/is-folder-empty.ts +40 -0
  15. package/cli/helpers/is-writeable.ts +14 -0
  16. package/cli/helpers/make-dir.ts +7 -0
  17. package/cli/helpers/validate-pkg.ts +17 -0
  18. package/cli/install-template.ts +77 -0
  19. package/eslint.config.mjs +187 -0
  20. package/index.html +44 -0
  21. package/integration.ts +179 -0
  22. package/migrate-scss.ts +42 -0
  23. package/package.json +135 -7
  24. package/prerender.ts +229 -0
  25. package/public/.nojekyll +1 -0
  26. package/public/400.html +1 -0
  27. package/public/401.html +21 -0
  28. package/public/403.html +252 -0
  29. package/public/404.css +51 -0
  30. package/public/404.html +29 -0
  31. package/public/__images__/awww.jpeg +0 -0
  32. package/public/__images__/bat-body.png +0 -0
  33. package/public/__images__/bat-wing.png +0 -0
  34. package/public/__images__/haunted-house-background.png +0 -0
  35. package/public/__images__/haunted-house-foreground.png +0 -0
  36. package/public/assets/fonts/crimson-text/CrimsonText-Bold.ttf +0 -0
  37. package/public/assets/fonts/crimson-text/CrimsonText-BoldItalic.ttf +0 -0
  38. package/public/assets/fonts/crimson-text/CrimsonText-Italic.ttf +0 -0
  39. package/public/assets/fonts/crimson-text/CrimsonText-Regular.ttf +0 -0
  40. package/public/assets/fonts/crimson-text/CrimsonText-SemiBold.ttf +0 -0
  41. package/public/assets/fonts/crimson-text/CrimsonText-SemiBoldItalic.ttf +0 -0
  42. package/public/assets/fonts/crimson-text/CrimsonText.woff2 +0 -0
  43. package/public/assets/fonts/crimson-text/OFL.txt +93 -0
  44. package/public/assets/fonts/work-sans/OFL.txt +93 -0
  45. package/public/assets/fonts/work-sans/README.txt +81 -0
  46. package/public/assets/fonts/work-sans/WorkSans-Italic-VariableFont_wght.ttf +0 -0
  47. package/public/assets/fonts/work-sans/WorkSans-VariableFont_wght.ttf +0 -0
  48. package/public/assets/fonts/work-sans/WorkSans.woff2 +0 -0
  49. package/public/assets/fonts/work-sans/static/WorkSans-Black.ttf +0 -0
  50. package/public/assets/fonts/work-sans/static/WorkSans-BlackItalic.ttf +0 -0
  51. package/public/assets/fonts/work-sans/static/WorkSans-Bold.ttf +0 -0
  52. package/public/assets/fonts/work-sans/static/WorkSans-BoldItalic.ttf +0 -0
  53. package/public/assets/fonts/work-sans/static/WorkSans-ExtraBold.ttf +0 -0
  54. package/public/assets/fonts/work-sans/static/WorkSans-ExtraBoldItalic.ttf +0 -0
  55. package/public/assets/fonts/work-sans/static/WorkSans-ExtraLight.ttf +0 -0
  56. package/public/assets/fonts/work-sans/static/WorkSans-ExtraLightItalic.ttf +0 -0
  57. package/public/assets/fonts/work-sans/static/WorkSans-Italic.ttf +0 -0
  58. package/public/assets/fonts/work-sans/static/WorkSans-Light.ttf +0 -0
  59. package/public/assets/fonts/work-sans/static/WorkSans-LightItalic.ttf +0 -0
  60. package/public/assets/fonts/work-sans/static/WorkSans-Medium.ttf +0 -0
  61. package/public/assets/fonts/work-sans/static/WorkSans-MediumItalic.ttf +0 -0
  62. package/public/assets/fonts/work-sans/static/WorkSans-Regular.ttf +0 -0
  63. package/public/assets/fonts/work-sans/static/WorkSans-SemiBold.ttf +0 -0
  64. package/public/assets/fonts/work-sans/static/WorkSans-SemiBoldItalic.ttf +0 -0
  65. package/public/assets/fonts/work-sans/static/WorkSans-Thin.ttf +0 -0
  66. package/public/assets/fonts/work-sans/static/WorkSans-ThinItalic.ttf +0 -0
  67. package/public/assets/images/icons.svg +67 -0
  68. package/public/assets/images/logo.svg +14 -0
  69. package/public/assets/images/root.svg +49 -0
  70. package/public/assets/vendors/axios@0.24.0/axios.js +2275 -0
  71. package/public/assets/vendors/axios@0.24.0/axios.map +1 -0
  72. package/public/assets/vendors/axios@0.24.0/axios.min.js +2 -0
  73. package/public/assets/vendors/axios@0.24.0/axios.min.map +1 -0
  74. package/public/favicon.ico +0 -0
  75. package/public/favicon.svg +3 -0
  76. package/public/icon-128.png +0 -0
  77. package/public/icon-16.png +0 -0
  78. package/public/icon-192.png +0 -0
  79. package/public/icon-48.png +0 -0
  80. package/public/icon-512.png +0 -0
  81. package/public/json/avatar.json +42 -0
  82. package/public/manifest.webmanifest +29 -0
  83. package/public/mockServiceWorker.js +349 -0
  84. package/public/pl-states.svg +4 -0
  85. package/public/samples/01.svg +1 -0
  86. package/public/samples/Airbnb.svg +3 -0
  87. package/public/samples/Facebook.svg +3 -0
  88. package/public/samples/Google.svg +8 -0
  89. package/public/samples/Microsoft.svg +7 -0
  90. package/public/samples/Spotify.svg +3 -0
  91. package/public/samples/alexandra-stolz.svg +35 -0
  92. package/public/samples/browserconfig.xml +9 -0
  93. package/public/samples/cliff-curtis.jpg +0 -0
  94. package/public/samples/emilia-clarke.jpg +0 -0
  95. package/public/samples/favicon.ico +0 -0
  96. package/public/samples/icons/android-chrome-192x192.png +0 -0
  97. package/public/samples/icons/apple-touch-icon.png +0 -0
  98. package/public/samples/icons/favicon-144x144.png +0 -0
  99. package/public/samples/icons/favicon-150x150.png +0 -0
  100. package/public/samples/icons/favicon-16x16.png +0 -0
  101. package/public/samples/icons/favicon-32x32.png +0 -0
  102. package/public/samples/icons/favicon-48x48.png +0 -0
  103. package/public/samples/icons/favicon-70x70.png +0 -0
  104. package/public/samples/icons/favicon.ico +0 -0
  105. package/public/samples/image-1.svg +166 -0
  106. package/public/samples/image-2.svg +110 -0
  107. package/public/samples/image-3.svg +113 -0
  108. package/public/samples/janet-bray.svg +36 -0
  109. package/public/samples/kate-winslet.jpg +0 -0
  110. package/public/samples/manifest.json +19 -0
  111. package/public/samples/michelle-yeoh.jpg +0 -0
  112. package/public/samples/peg-legge.svg +37 -0
  113. package/public/samples/richard-guerra.svg +42 -0
  114. package/public/samples/rose-leslie.jpg +0 -0
  115. package/public/samples/sample-1.svg +365 -0
  116. package/public/samples/sample-2.svg +129 -0
  117. package/public/samples/sample-3.svg +93 -0
  118. package/public/samples/sample-4.svg +168 -0
  119. package/public/samples/sample-5.svg +155 -0
  120. package/public/samples/sample-6.svg +445 -0
  121. package/public/samples/sample-7.svg +404 -0
  122. package/public/samples/sample-8.png +0 -0
  123. package/public/staticwebapp.config.json +138 -0
  124. package/scripts.ts +56 -0
  125. package/server.ts +29 -0
  126. package/states.ts +63 -0
  127. package/styles.ts +232 -0
  128. package/tsconfig.json +71 -25
  129. package/types.d.ts +54 -0
  130. package/vite.config.ts +3 -0
  131. package/xpack/alias.ts +21 -0
  132. package/xpack/config.ts +59 -0
  133. package/xpack/create-server.ts +68 -0
  134. package/xpack/create-vite-dev-server.ts +33 -0
  135. package/xpack/deploy/deploy-inte.ts +3 -0
  136. package/xpack/filename.ts +43 -0
  137. package/xpack/hooks/build-start.ts +17 -0
  138. package/xpack/hooks/close-bundle.ts +19 -0
  139. package/xpack/hooks/handle-hot-update.ts +22 -0
  140. package/xpack/hooks/options.ts +55 -0
  141. package/xpack/hooks/resolve-dynamic-import.ts +18 -0
  142. package/xpack/hooks/transform-index-html.ts +18 -0
  143. package/xpack/hooks/transform.ts +72 -0
  144. package/xpack/hooks/write-bundle.ts +16 -0
  145. package/xpack/manual-chunk.ts +56 -0
  146. package/xpack/paths.ts +30 -0
  147. package/xpack/react-loader-init.tsx +4 -0
  148. package/xpack/react-loader.tsx +54 -0
  149. package/xpack/renderer.ts +141 -0
  150. package/xpack/root/active-item-options.tsx +98 -0
  151. package/xpack/root/frame-controls.tsx +139 -0
  152. package/xpack/root/index.tsx +107 -0
  153. package/xpack/root/rendered-item.tsx +25 -0
  154. package/xpack/root/root-context.ts +22 -0
  155. package/xpack/root/root-nav.tsx +162 -0
  156. package/xpack/root/state-animation-html.tsx +18 -0
  157. package/xpack/root/template.tsx +23 -0
  158. package/xpack/root/use-click-outside.ts +37 -0
  159. package/xpack/scripts/color-mode.entry.ts +28 -0
  160. package/xpack/scripts/mock-api.entry.ts +11 -0
  161. package/xpack/scripts/pl-states.entry.ts +321 -0
  162. package/xpack/scripts/root.entry.ts +135 -0
  163. package/xpack/scripts/theme-critical.entry.ts +20 -0
  164. package/xpack/states.schema.json +61 -0
  165. package/xpack/styles/_border.scss +22 -0
  166. package/xpack/styles/_breakpoint.scss +117 -0
  167. package/xpack/styles/_form.scss +23 -0
  168. package/xpack/styles/_px2rem.scss +5 -0
  169. package/xpack/styles/_reset.scss +134 -0
  170. package/xpack/styles/_state-toggle.scss +121 -0
  171. package/xpack/styles/_theme.scss +68 -0
  172. package/xpack/styles/_top-panel.scss +87 -0
  173. package/xpack/styles/_xpack-root.scss +322 -0
  174. package/xpack/styles/pl-states.scss +308 -0
  175. package/xpack/styles/root.scss +129 -0
  176. package/.github/workflows/deploy.yaml +0 -32
  177. package/index.ts +0 -1
@@ -0,0 +1,77 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { execSync } from 'child_process';
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+
6
+ function isInGitRepository(): boolean {
7
+ try {
8
+ execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
9
+
10
+ return true;
11
+ } catch (_) {
12
+ /* empty */
13
+ }
14
+
15
+ return false;
16
+ }
17
+
18
+ function isInMercurialRepository(): boolean {
19
+ try {
20
+ execSync('hg --cwd . root', { stdio: 'ignore' });
21
+
22
+ return true;
23
+ } catch (_) {
24
+ /* empty */
25
+ }
26
+
27
+ return false;
28
+ }
29
+
30
+ function isDefaultBranchSet(): boolean {
31
+ try {
32
+ execSync('git config init.defaultBranch', { stdio: 'ignore' });
33
+
34
+ return true;
35
+ } catch (_) {
36
+ /* empty */
37
+ }
38
+
39
+ return false;
40
+ }
41
+
42
+ const tryGitInit = (root: string): boolean => {
43
+ let didInit = false;
44
+
45
+ try {
46
+ execSync('git --version', { stdio: 'ignore' });
47
+ if (isInGitRepository() || isInMercurialRepository()) {
48
+ return false;
49
+ }
50
+
51
+ execSync('git init', { stdio: 'ignore' });
52
+ didInit = true;
53
+
54
+ if (!isDefaultBranchSet()) {
55
+ execSync('git checkout -b main', { stdio: 'ignore' });
56
+ }
57
+
58
+ execSync('git add -A', { stdio: 'ignore' });
59
+ execSync('git commit -m "Initial commit from Create App"', {
60
+ stdio: 'ignore',
61
+ });
62
+
63
+ return true;
64
+ } catch (e) {
65
+ if (didInit) {
66
+ try {
67
+ fs.rmSync(path.join(root, '.git'), { recursive: true, force: true });
68
+ } catch (_) {
69
+ /* empty */
70
+ }
71
+ }
72
+
73
+ return false;
74
+ }
75
+ };
76
+
77
+ export { tryGitInit };
@@ -0,0 +1,26 @@
1
+ /* eslint-disable no-console */
2
+ import { exec } from 'node:child_process';
3
+
4
+ import chalk from 'chalk';
5
+
6
+ const { red } = chalk;
7
+
8
+ const install = async () => {
9
+ return new Promise((resolve, reject) => {
10
+ exec('npm install', (error, stdout) => {
11
+ if (error) {
12
+ reject(error);
13
+
14
+ console.log(`${red(error)}`);
15
+
16
+ return;
17
+ }
18
+
19
+ console.log(stdout);
20
+
21
+ resolve(stdout);
22
+ });
23
+ });
24
+ };
25
+
26
+ export { install };
@@ -0,0 +1,40 @@
1
+ import fs from 'fs';
2
+
3
+ const isFolderEmpty = (root: string): boolean => {
4
+ const validFiles = [
5
+ '.DS_Store',
6
+ '.git',
7
+ '.gitattributes',
8
+ '.gitignore',
9
+ '.gitlab-ci.yml',
10
+ '.hg',
11
+ '.hgcheck',
12
+ '.hgignore',
13
+ '.idea',
14
+ '.npmignore',
15
+ '.travis.yml',
16
+ 'LICENSE',
17
+ 'Thumbs.db',
18
+ 'docs',
19
+ 'mkdocs.yml',
20
+ 'npm-debug.log',
21
+ 'yarn-debug.log',
22
+ 'yarn-error.log',
23
+ 'yarnrc.yml',
24
+ '.yarn',
25
+ ];
26
+
27
+ const conflicts = fs
28
+ .readdirSync(root)
29
+ .filter((file) => !validFiles.includes(file))
30
+ // Support IntelliJ IDEA-based editors
31
+ .filter((file) => !/\.iml$/.test(file));
32
+
33
+ if (conflicts.length > 0) {
34
+ return false;
35
+ }
36
+
37
+ return true;
38
+ };
39
+
40
+ export { isFolderEmpty };
@@ -0,0 +1,14 @@
1
+ import fs from 'fs';
2
+
3
+ const isWriteable = async (directory: string): Promise<boolean> => {
4
+ try {
5
+ await fs.promises.access(directory, fs.constants.W_OK);
6
+
7
+ return true;
8
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
9
+ } catch (err) {
10
+ return false;
11
+ }
12
+ };
13
+
14
+ export { isWriteable };
@@ -0,0 +1,7 @@
1
+ import fs from 'fs';
2
+
3
+ const makeDir = (root: string, options = { recursive: true }): Promise<string | undefined> => {
4
+ return fs.promises.mkdir(root, options);
5
+ };
6
+
7
+ export { makeDir };
@@ -0,0 +1,17 @@
1
+ import validateProjectName from 'validate-npm-package-name';
2
+
3
+ export function validateNpmName(name: string): {
4
+ valid: boolean;
5
+ problems?: string[];
6
+ } {
7
+ const nameValidation = validateProjectName(name);
8
+
9
+ if (nameValidation.validForNewPackages && !name.startsWith('-')) {
10
+ return { valid: true };
11
+ }
12
+
13
+ return {
14
+ valid: false,
15
+ problems: [...(nameValidation.errors || []), ...(nameValidation.warnings || [])],
16
+ };
17
+ }
@@ -0,0 +1,77 @@
1
+ /* eslint-disable no-console */
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ import os from 'os';
6
+
7
+ import chalk from 'chalk';
8
+
9
+ import { copy } from './helpers/copy.js';
10
+ import { install } from './helpers/install.js';
11
+ import { formatFiles } from './helpers/format-files.js';
12
+
13
+ export const filename = fileURLToPath(import.meta.url);
14
+ export const dirname = path.dirname(filename);
15
+
16
+ interface Props {
17
+ appName: string;
18
+ root: string;
19
+ }
20
+
21
+ const { cyan } = chalk;
22
+
23
+ const installTemplate = async (model: Props) => {
24
+ const { appName, root } = model;
25
+
26
+ console.log('\nInitializing project');
27
+ const copySource = ['**'];
28
+
29
+ await copy(copySource, root, {
30
+ cwd: path.join(dirname, '..'),
31
+ });
32
+
33
+ await formatFiles(root);
34
+
35
+ const packageJson = JSON.parse(await fs.readFile('package.json', 'utf8'));
36
+
37
+ packageJson.name = appName;
38
+ packageJson.description = '';
39
+ packageJson.version = '0.1.0';
40
+
41
+ delete packageJson.bin;
42
+ packageJson.scripts &&
43
+ Object.keys(packageJson.scripts).map((scriptName: string) => {
44
+ if (scriptName.startsWith('cli')) {
45
+ delete packageJson.scripts[scriptName];
46
+ }
47
+ });
48
+
49
+ packageJson.dependencies &&
50
+ Object.keys(packageJson.dependencies).map((dependency) => {
51
+ if (!dependency.startsWith('react')) {
52
+ delete packageJson.dependencies[dependency];
53
+ }
54
+ });
55
+
56
+ const devDeps = Object.keys(packageJson.devDependencies).length;
57
+
58
+ if (!devDeps) delete packageJson.devDependencies;
59
+
60
+ await fs.writeFile(path.join(root, 'package.json'), JSON.stringify(packageJson, null, 2) + os.EOL);
61
+
62
+ console.log('\nInstalling dependencies:');
63
+
64
+ for (const dependency in packageJson.dependencies) {
65
+ console.log(`- ${cyan(dependency)}`);
66
+ }
67
+
68
+ if (devDeps) {
69
+ console.log('\nInstalling devDependencies:');
70
+
71
+ for (const dependency in packageJson.devDependencies) console.log(`- ${cyan(dependency)}`);
72
+ }
73
+
74
+ await install();
75
+ };
76
+
77
+ export { installTemplate };
@@ -0,0 +1,187 @@
1
+ import { defineConfig, globalIgnores } from 'eslint/config';
2
+ import { fixupConfigRules, fixupPluginRules } from '@eslint/compat';
3
+ import react from 'eslint-plugin-react';
4
+ import unusedImports from 'eslint-plugin-unused-imports';
5
+ import _import from 'eslint-plugin-import';
6
+ import typescriptEslint from '@typescript-eslint/eslint-plugin';
7
+ import jsxA11Y from 'eslint-plugin-jsx-a11y';
8
+ import prettier from 'eslint-plugin-prettier';
9
+ import nextPlugin from '@next/eslint-plugin-next';
10
+ import globals from 'globals';
11
+ import tsParser from '@typescript-eslint/parser';
12
+ import path from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+ import js from '@eslint/js';
15
+ import { FlatCompat } from '@eslint/eslintrc';
16
+ import reactRefresh from 'eslint-plugin-react-refresh';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ const compat = new FlatCompat({
21
+ baseDirectory: __dirname,
22
+ recommendedConfig: js.configs.recommended,
23
+ allConfig: js.configs.all,
24
+ });
25
+
26
+ export default defineConfig([
27
+ globalIgnores([
28
+ '.now/*',
29
+ '**/*.css',
30
+ '**/.changeset',
31
+ '**/dist',
32
+ 'esm/*',
33
+ 'public/*',
34
+ 'tests/*',
35
+ 'scripts/*',
36
+ '**/*.config.js',
37
+ '**/.DS_Store',
38
+ '**/node_modules',
39
+ '**/coverage',
40
+ '**/.next',
41
+ '**/build',
42
+ '!**/.commitlintrc.cjs',
43
+ '!**/.lintstagedrc.cjs',
44
+ '!**/jest.config.js',
45
+ '!**/plopfile.js',
46
+ '!**/react-shim.js',
47
+ '!**/tsup.config.ts',
48
+ ]),
49
+ ...fixupConfigRules(
50
+ compat.extends('plugin:react/recommended', 'plugin:prettier/recommended', 'plugin:react-hooks/recommended', 'plugin:jsx-a11y/recommended')
51
+ ),
52
+ {
53
+ settings: {
54
+ react: {
55
+ version: 'detect',
56
+ },
57
+ },
58
+ },
59
+ {
60
+ files: ['**/*.ts', '**/*.tsx'],
61
+
62
+ plugins: {
63
+ react: fixupPluginRules(react),
64
+ 'unused-imports': unusedImports,
65
+ import: fixupPluginRules(_import),
66
+ '@typescript-eslint': typescriptEslint,
67
+ 'react-refresh': reactRefresh,
68
+ 'jsx-a11y': fixupPluginRules(jsxA11Y),
69
+ prettier: fixupPluginRules(prettier),
70
+ '@next/next': fixupPluginRules(nextPlugin),
71
+ },
72
+
73
+ languageOptions: {
74
+ globals: {
75
+ ...globals.browser,
76
+ ...globals.node,
77
+ },
78
+
79
+ parser: tsParser,
80
+ ecmaVersion: 'latest',
81
+ sourceType: 'module',
82
+
83
+ parserOptions: {
84
+ ecmaFeatures: {
85
+ jsx: true,
86
+ },
87
+ },
88
+ },
89
+
90
+ rules: {
91
+ 'no-console': 'warn',
92
+ 'react/prop-types': 'off',
93
+ 'react/jsx-uses-react': 'off',
94
+ 'react/react-in-jsx-scope': 'off',
95
+ 'react-hooks/exhaustive-deps': 'off',
96
+ 'jsx-a11y/click-events-have-key-events': 'warn',
97
+ 'jsx-a11y/interactive-supports-focus': 'warn',
98
+ 'prettier/prettier': 'warn',
99
+ 'no-unused-vars': 'off',
100
+ 'unused-imports/no-unused-vars': 'off',
101
+ 'unused-imports/no-unused-imports': 'warn',
102
+ 'react-refresh/only-export-components': 'error',
103
+ 'no-new': 'error',
104
+ complexity: ['error', 15],
105
+ 'max-depth': ['error', 4],
106
+
107
+ '@typescript-eslint/no-unused-vars': [
108
+ 'warn',
109
+ {
110
+ args: 'after-used',
111
+ ignoreRestSiblings: false,
112
+ argsIgnorePattern: '^_.*?$',
113
+ },
114
+ ],
115
+
116
+ 'import/order': [
117
+ 'warn',
118
+ {
119
+ groups: ['type', 'builtin', 'object', 'external', 'internal', 'parent', 'sibling', 'index'],
120
+
121
+ pathGroups: [
122
+ {
123
+ pattern: '~/**',
124
+ group: 'external',
125
+ position: 'after',
126
+ },
127
+ {
128
+ pattern: '@/**',
129
+ group: 'internal',
130
+ position: 'after',
131
+ },
132
+ ],
133
+
134
+ 'newlines-between': 'always',
135
+ },
136
+ ],
137
+
138
+ 'react/self-closing-comp': 'warn',
139
+
140
+ 'react/jsx-sort-props': [
141
+ 'warn',
142
+ {
143
+ callbacksLast: true,
144
+ shorthandFirst: true,
145
+ noSortAlphabetically: false,
146
+ reservedFirst: true,
147
+ },
148
+ ],
149
+
150
+ 'padding-line-between-statements': [
151
+ 'warn',
152
+ {
153
+ blankLine: 'always',
154
+ prev: '*',
155
+ next: 'return',
156
+ },
157
+ {
158
+ blankLine: 'always',
159
+ prev: ['const', 'let', 'var'],
160
+ next: '*',
161
+ },
162
+ {
163
+ blankLine: 'any',
164
+ prev: ['const', 'let', 'var'],
165
+ next: ['const', 'let', 'var'],
166
+ },
167
+ ],
168
+
169
+ quotes: [
170
+ 'warn',
171
+ 'single',
172
+ {
173
+ avoidEscape: true,
174
+ },
175
+ ],
176
+ },
177
+ },
178
+ {
179
+ files: ['**/*.ts', '**/*.tsx'],
180
+ plugins: {
181
+ '@next/next': fixupPluginRules(nextPlugin),
182
+ },
183
+ rules: {
184
+ '@next/next/no-img-element': 'off',
185
+ },
186
+ },
187
+ ]);
package/index.html ADDED
@@ -0,0 +1,44 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
5
+ <meta charset="utf-8" />
6
+ <link rel="icon" href="#__BASE_URL__/favicon.ico" sizes="any" />
7
+ <link rel="icon" href="#__BASE_URL__/favicon.svg" type="image/svg+xml" />
8
+ <link rel="manifest" href="#__BASE_URL__/manifest.webmanifest" />
9
+ <meta name="locale" content="en-US" />
10
+ <meta name="ROBOTS" content="NONE, NOARCHIVE" />
11
+ <meta name="GOOGLEBOT" content="NOARCHIVE" />
12
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
13
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.0, user-scalable=yes" />
14
+ <meta name="description" content="This is the description for Precise Alloy page." />
15
+ <title>B2C Home</title>
16
+ <meta name="twitter:image" content="#__BASE_URL__/icons/apple-touch-icon.png" />
17
+ <meta name="og:image" content="#__BASE_URL__/icons/apple-touch-icon.png" />
18
+ <meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)" />
19
+ <meta name="theme-color" content="#fff" media="(prefers-color-scheme: dark)" />
20
+ <link rel="apple-touch-icon" sizes="180x180" href="#__BASE_URL__/icons/apple-touch-icon.png" />
21
+ <link rel="icon" type="image/png" sizes="32x32" href="#__BASE_URL__/icons/favicon-32x32.png" />
22
+ <link rel="icon" type="image/png" sizes="16x16" href="#__BASE_URL__/icons/favicon-16x16.png" />
23
+ <link rel="manifest" href="#__BASE_URL__/manifest.json" crossorigin />
24
+ <link rel="stylesheet" href="#__BASE_URL__/assets/css/style-base.css" as="style" />
25
+ <link rel="stylesheet" href="#__BASE_URL__/assets/css/pl-states.css" as="style" />
26
+ <link rel="preload" href="#__BASE_URL__/assets/fonts/work-sans/WorkSans.woff2" as="font" type="font/woff2" />
27
+ <link rel="preload" href="#__BASE_URL__/assets/fonts/crimson-text/CrimsonText.woff2" as="font" type="font/woff2" />
28
+
29
+ <script defer src="#__BASE_URL__/assets/js/color-mode.js"></script>
30
+ <script src="#__BASE_URL__/assets/js/theme-critical.js"></script>
31
+
32
+ <script defer src="#__BASE_URL__/assets/js/main.js"></script>
33
+
34
+ <!-- Don't include this line in a production site -->
35
+ <script type="module" src="#__BASE_URL__/assets/js/mock-api.js"></script>
36
+ <!-- Don't include this line in a production site -->
37
+ </head>
38
+
39
+ <body>
40
+ <!--app-html-->
41
+ <script type="module" src="/xpack/react-loader-init.tsx"></script>
42
+ <script type="module" defer src="#__BASE_URL__/assets/js/pl-states.js"></script>
43
+ </body>
44
+ </html>
package/integration.ts ADDED
@@ -0,0 +1,179 @@
1
+ /* eslint-disable no-console */
2
+ import fs from 'fs';
3
+ import path, { resolve } from 'path';
4
+ import crypto from 'node:crypto';
5
+ import nodeFs from 'node:fs';
6
+
7
+ import slash from 'slash';
8
+ import { glob } from 'glob';
9
+ import { loadEnv } from 'vite';
10
+ import chalk from 'chalk';
11
+
12
+ interface CopyItem {
13
+ from: string;
14
+ to?: string;
15
+ }
16
+
17
+ interface FileExistCheck {
18
+ folder?: string;
19
+ fileName: string | RegExp;
20
+ }
21
+
22
+ const argvModeIndex = process.argv.indexOf('--mode');
23
+ const mode =
24
+ argvModeIndex >= 0 && argvModeIndex < process.argv.length - 1 && !process.argv[argvModeIndex + 1].startsWith('-')
25
+ ? process.argv[argvModeIndex + 1]
26
+ : 'production';
27
+ const projectRoot = process.cwd();
28
+ const xpackEnv = loadEnv(mode, projectRoot);
29
+ const toAbsolute = (p: string) => slash(path.resolve(projectRoot, p));
30
+ const log = console.log.bind(console);
31
+
32
+ const hashes: Map<string, string> = new Map();
33
+ const staticBasePath = toAbsolute('dist/static');
34
+ const srcBasePath = toAbsolute('dist/static/assets');
35
+ const destBasePath = toAbsolute(xpackEnv.VITE_INTE_ASSET_DIR);
36
+ const patternPath = xpackEnv.VITE_INTE_PATTERN_DIR ? toAbsolute(xpackEnv.VITE_INTE_PATTERN_DIR) : undefined;
37
+
38
+ if (patternPath && fs.existsSync(patternPath)) {
39
+ fs.rmSync(patternPath, { recursive: true, force: true });
40
+
41
+ fs.mkdirSync(patternPath, { recursive: true });
42
+ }
43
+
44
+ const copyItems: CopyItem[] = [
45
+ { from: 'css' },
46
+ { from: 'fonts' },
47
+ { from: 'images' },
48
+ { from: 'js' },
49
+ { from: 'vendors' },
50
+ { from: 'hashes.json' },
51
+ { from: 'pages', to: patternPath },
52
+ ];
53
+ const hashItems: string[] = ['css', 'images', 'js'];
54
+
55
+ copyItems.forEach((item) => {
56
+ const srcPath = slash(path.join(srcBasePath, item.from));
57
+ const destPath = slash(item.to ?? path.join(destBasePath, item.from));
58
+
59
+ if (!fs.existsSync(srcPath)) {
60
+ return;
61
+ }
62
+
63
+ log(`Copy file ${srcPath} to ${destPath}`);
64
+
65
+ if (fs.statSync(srcPath).isDirectory()) {
66
+ if (fs.existsSync(destPath)) {
67
+ fs.rmSync(destPath, { recursive: true, force: true });
68
+ }
69
+
70
+ fs.mkdirSync(destPath, { recursive: true });
71
+
72
+ fs.cpSync(srcPath, destPath, { recursive: true, force: true });
73
+ } else {
74
+ const destDirPath = path.dirname(destPath);
75
+
76
+ if (!fs.existsSync(destDirPath)) {
77
+ fs.mkdirSync(destDirPath);
78
+ }
79
+
80
+ fs.copyFileSync(srcPath, destPath);
81
+ }
82
+ });
83
+
84
+ hashItems.forEach((item) => {
85
+ const srcPath = slash(path.join(srcBasePath, item));
86
+ const files = glob.sync(srcPath + '/**/*.{css,js,svg}');
87
+
88
+ files.forEach((file) => {
89
+ const relativePath = slash(file.substring(staticBasePath.length));
90
+
91
+ if (!/\.0x[a-z0-9_-]{8,12}\.\w+$/gi.test(file)) {
92
+ const content = fs.readFileSync(file);
93
+ const sha1Hash = crypto.createHash('sha1');
94
+
95
+ sha1Hash.update(content);
96
+ const hash = sha1Hash.digest('base64url').substring(0, 10);
97
+
98
+ hashes.set(relativePath, hash);
99
+ } else {
100
+ hashes.set(relativePath, '');
101
+ }
102
+ });
103
+ });
104
+
105
+ const sortedHashes = Array.from(hashes)
106
+ .sort((a, b) => a[0].localeCompare(b[0]))
107
+ .reduce(
108
+ (obj, [key, value]) => {
109
+ obj[key] = value;
110
+
111
+ return obj;
112
+ },
113
+ {} as { [key: string]: string }
114
+ );
115
+
116
+ fs.writeFileSync(path.join(destBasePath, 'hashes.json'), JSON.stringify(sortedHashes, null, ' '));
117
+
118
+ if (patternPath) {
119
+ fs.mkdirSync(patternPath, { recursive: true });
120
+ glob.sync('./dist/static/{atoms,molecules,organisms,templates,pages}/**/*.*').forEach((p) => {
121
+ let basename = '';
122
+ const segments = slash(p).split('/');
123
+
124
+ if (segments.length < 4) return;
125
+ switch (segments.length) {
126
+ case 4:
127
+ basename = path.basename(slash(p).replaceAll(/(atoms|molecules|organisms|templates|pages)\/([\w._-]+)$/gi, '$1-$2'));
128
+ fs.copyFileSync(p, resolve(patternPath, basename));
129
+ break;
130
+ default:
131
+ segments.splice(0, 2);
132
+ nodeFs.cpSync(p, resolve(patternPath, segments.join('-')), { recursive: true });
133
+ break;
134
+ }
135
+ });
136
+
137
+ glob.sync(slash(path.resolve(patternPath + '/**/*.{htm,html}'))).forEach((p) => {
138
+ const text = fs.readFileSync(p, 'utf-8');
139
+ const newText = text
140
+ .replaceAll(/react-loader\.0x[a-z0-9_-]{8,12}\.js/gi, 'react-loader.0x00000000.js')
141
+ .replaceAll(/\.svg\?v=[a-z0-9_-]+/gi, '.svg');
142
+
143
+ if (text !== newText) {
144
+ fs.writeFileSync(p, newText);
145
+ }
146
+ });
147
+ }
148
+
149
+ const checkExistFileList: FileExistCheck[] = [
150
+ { fileName: 'hashes.json' },
151
+ { fileName: /react-loader\.0x[a-z0-9_-]{8,12}\.js/gi, folder: 'js' },
152
+ { fileName: 'main.js', folder: 'js' },
153
+ ];
154
+ let isAllExist = true;
155
+
156
+ checkExistFileList.forEach((file) => {
157
+ if (typeof file.fileName === 'string') {
158
+ const destPath = slash(path.join(destBasePath, file.folder ?? '', file.fileName.toString()));
159
+
160
+ if (!fs.existsSync(destPath)) {
161
+ log(chalk.yellow(`Cannot find: ${destPath}`));
162
+ isAllExist = false;
163
+ }
164
+ } else {
165
+ const fileName = file.fileName;
166
+ const folderFiles = slash(path.join(destBasePath, file.folder ?? ''));
167
+ const files = fs.readdirSync(folderFiles);
168
+ const found = files.find((f) => fileName.test(f));
169
+
170
+ if (!found) {
171
+ log(chalk.yellow(`Cannot find: ${slash(path.join(folderFiles, fileName.toString()))}`));
172
+ isAllExist = false;
173
+ }
174
+ }
175
+ });
176
+
177
+ if (!isAllExist) {
178
+ process.exit(1);
179
+ }