create-outsystems-astro 0.1.0
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/LICENSE +21 -0
- package/README.md +75 -0
- package/bin/cli.js +71 -0
- package/package.json +27 -0
- package/template/.env.template +2 -0
- package/template/astro.config.mjs +29 -0
- package/template/output.ts +244 -0
- package/template/package-lock.json +6485 -0
- package/template/package.json +26 -0
- package/template/src/components/Counter.tsx +35 -0
- package/template/src/images/astro.png +0 -0
- package/template/src/images/outsystems.png +0 -0
- package/template/src/pages/counter.astro +11 -0
- package/template/src/styles/index.css +29 -0
- package/template/tsconfig.json +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 hs2323
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# OutSystems Astro Islands
|
|
2
|
+
Generates [Astro Islands](https://docs.astro.build/en/concepts/islands/) for use in OutSystems that can create self contained interactive code elements from different frameworks. It allows an extension of the front-end with these dynamic libraries.
|
|
3
|
+
|
|
4
|
+
## When to use this library
|
|
5
|
+
- Custom interactive elements that would not be difficult/not possible to build directly in OutSystems.
|
|
6
|
+
- Wrappers around interactive elements built in other front-end frameworks.
|
|
7
|
+
- Direct migration of traditional code.
|
|
8
|
+
|
|
9
|
+
## When NOT to use this library
|
|
10
|
+
- You will most likely not need to use this library for most of the front-end development. This is similar in use to the custom code development in for the back-end in [O11](https://success.outsystems.com/documentation/11/integration_with_external_systems/extend_logic_with_your_own_code/) and [ODC](https://success.outsystems.com/documentation/outsystems_developer_cloud/building_apps/extend_your_apps_with_custom_code/).
|
|
11
|
+
- If the functionality is easily buidable in Service Studio.
|
|
12
|
+
- Loading performance of component must be instant. The Astro Island will load after the page/screen has loaded since the initializer and tag will be loaded after.
|
|
13
|
+
|
|
14
|
+
## Current supported frameworks
|
|
15
|
+
- [React](https://docs.astro.build/en/guides/integrations-guide/react/).
|
|
16
|
+
|
|
17
|
+
## Getting started
|
|
18
|
+
Run the Create OutSystems Astro generator:
|
|
19
|
+
```bash
|
|
20
|
+
npx create-outsystems-astro
|
|
21
|
+
```
|
|
22
|
+
This will create the generated files as well as an example component.
|
|
23
|
+
|
|
24
|
+
## ๐ Project Structure
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
/
|
|
28
|
+
โโโ public/
|
|
29
|
+
โโโ src/
|
|
30
|
+
โ โโโ components/
|
|
31
|
+
โ โโโ Counter.tsx
|
|
32
|
+
โ โโโ images/
|
|
33
|
+
โ โโโ image.png
|
|
34
|
+
โ โโโ pages/
|
|
35
|
+
โ โโโ counter.astro
|
|
36
|
+
โ โโโ styles/
|
|
37
|
+
โ โโโ index.css
|
|
38
|
+
โโโ package.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Pages
|
|
42
|
+
Each page inside of the pages file should represent an Island that will be imported into OutSystems.
|
|
43
|
+
|
|
44
|
+
### Components
|
|
45
|
+
The location of the component code.
|
|
46
|
+
|
|
47
|
+
### Images
|
|
48
|
+
Any image assets.
|
|
49
|
+
|
|
50
|
+
### Styles
|
|
51
|
+
Stylesheets that may apply to the component.
|
|
52
|
+
|
|
53
|
+
## ๐ง Commands
|
|
54
|
+
|
|
55
|
+
All commands are run from the root of the project, from a terminal:
|
|
56
|
+
|
|
57
|
+
| Command | Action |
|
|
58
|
+
| :------------------------ | :----------------------------------------------- |
|
|
59
|
+
| `npm install` | Installs dependencies |
|
|
60
|
+
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
|
61
|
+
| `npm run build` | Build distribution to `./dist/` |
|
|
62
|
+
| `npm run output` | Build OutSystems production site to `./output/` |
|
|
63
|
+
| `npm run preview` | Preview build locally, before creating output |
|
|
64
|
+
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
|
65
|
+
| `npm run astro -- --help` | Get help using the Astro CLI |
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## Converting to OutSystems
|
|
69
|
+
|
|
70
|
+
Once development is complete, run:
|
|
71
|
+
```bash
|
|
72
|
+
npm run output
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This will create a set of files that will then need to be coverted to OutSystems components.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import prompts from "prompts";
|
|
6
|
+
import { execSync } from "child_process";
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
console.log("๐ Welcome to create-outsystems-astro!");
|
|
13
|
+
|
|
14
|
+
// Ask for project name
|
|
15
|
+
const response = await prompts({
|
|
16
|
+
type: "text",
|
|
17
|
+
name: "projectName",
|
|
18
|
+
message: "What should we name your project?",
|
|
19
|
+
initial: "outsystems-astro-app"
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const targetDir = path.resolve(process.cwd(), response.projectName);
|
|
23
|
+
const templateDir = path.join(__dirname, "..", "template");
|
|
24
|
+
|
|
25
|
+
// Copy files
|
|
26
|
+
console.log("๐ฆ Copying template...");
|
|
27
|
+
copyDir(templateDir, targetDir);
|
|
28
|
+
|
|
29
|
+
const readmeSrc = path.resolve(__dirname, "../README.md");
|
|
30
|
+
const readmeDest = path.join(targetDir, "README.md");
|
|
31
|
+
|
|
32
|
+
if (fs.existsSync(readmeSrc)) {
|
|
33
|
+
fs.copyFileSync(readmeSrc, readmeDest);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Install dependencies
|
|
37
|
+
console.log("๐ฆ Installing dependencies...");
|
|
38
|
+
try {
|
|
39
|
+
execSync("npm install", { cwd: targetDir, stdio: "inherit" });
|
|
40
|
+
} catch {
|
|
41
|
+
console.warn("โ ๏ธ Failed to automatically install dependencies.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`
|
|
45
|
+
โ
All done!
|
|
46
|
+
|
|
47
|
+
Next steps:
|
|
48
|
+
cd ${response.projectName}
|
|
49
|
+
npm run dev
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Simple recursive copy
|
|
54
|
+
function copyDir(src, dest) {
|
|
55
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
56
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
57
|
+
const srcPath = path.join(src, entry.name);
|
|
58
|
+
const destPath = path.join(dest, entry.name);
|
|
59
|
+
|
|
60
|
+
if (entry.isDirectory()) {
|
|
61
|
+
copyDir(srcPath, destPath);
|
|
62
|
+
} else {
|
|
63
|
+
fs.copyFileSync(srcPath, destPath);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
main().catch(err => {
|
|
69
|
+
console.error(err);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-outsystems-astro",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Create an OutSystems Astro Island project to import as a component into your OutSystems application",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-outsystems-astro": "bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"template"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"astro",
|
|
18
|
+
"outsystems",
|
|
19
|
+
"starter",
|
|
20
|
+
"create",
|
|
21
|
+
"template"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"prompts": "^2.4.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import react from '@astrojs/react';
|
|
3
|
+
import { defineConfig } from 'astro/config';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// https://astro.build/config
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
integrations: [react()],
|
|
9
|
+
build: {
|
|
10
|
+
inlineStylesheets: 'always'
|
|
11
|
+
},
|
|
12
|
+
vite: {
|
|
13
|
+
build: {
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
output: {
|
|
16
|
+
manualChunks: (id) => {
|
|
17
|
+
if (id.includes('node_modules') || id.includes('src')) {
|
|
18
|
+
return 'app.js';
|
|
19
|
+
}
|
|
20
|
+
return 'app.js';
|
|
21
|
+
},
|
|
22
|
+
entryFileNames: `[name]_[hash].js`,
|
|
23
|
+
chunkFileNames: `[name]_[hash].js`,
|
|
24
|
+
assetFileNames: `assets/[name]_[hash].[ext]`,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import beautify from "js-beautify";
|
|
4
|
+
import dotenv from 'dotenv';
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
const { html: beautifyHtml } = beautify;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Extracts all <astro-island>...</astro-island> blocks from HTML.
|
|
11
|
+
*/
|
|
12
|
+
function keepAstroIslands(html: string): string {
|
|
13
|
+
const astroIslandRegex = /<astro-island\b[^>]*>[\s\S]*?<\/astro-island>/gi;
|
|
14
|
+
const islands = html.match(astroIslandRegex) || [];
|
|
15
|
+
return islands.join("\n");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function formatAstroIslandAttributes(html: string): string {
|
|
19
|
+
// For each <astro-island ...>, put attributes on new lines
|
|
20
|
+
return html.replace(
|
|
21
|
+
/<astro-island\b([^>]*)>/gi,
|
|
22
|
+
(match, attrs) => {
|
|
23
|
+
|
|
24
|
+
// ๐ฅ Convert HTML-encoded quotes to actual quotes
|
|
25
|
+
const decoded = attrs.replace(/"/g, '""');
|
|
26
|
+
|
|
27
|
+
// Split attributes by whitespace
|
|
28
|
+
const formattedAttrs = decoded
|
|
29
|
+
.trim()
|
|
30
|
+
.split(/\s+/)
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.map(attr => ` ${attr}`) // indent each attr
|
|
33
|
+
.join("\n");
|
|
34
|
+
|
|
35
|
+
return `<astro-island\n${formattedAttrs}>`;
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Recursively collects files with a given extension in a directory.
|
|
42
|
+
*/
|
|
43
|
+
function getAllFilesWithExtension(dir: string, ext: string): string[] {
|
|
44
|
+
let results: string[] = [];
|
|
45
|
+
|
|
46
|
+
for (const file of fs.readdirSync(dir)) {
|
|
47
|
+
const filePath = path.join(dir, file);
|
|
48
|
+
const stat = fs.statSync(filePath);
|
|
49
|
+
|
|
50
|
+
if (stat.isDirectory()) {
|
|
51
|
+
results = results.concat(getAllFilesWithExtension(filePath, ext));
|
|
52
|
+
} else if (filePath.endsWith(ext)) {
|
|
53
|
+
results.push(filePath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Ensures a directory exists before writing or copying.
|
|
62
|
+
*/
|
|
63
|
+
function ensureDirExists(dir: string) {
|
|
64
|
+
if (!fs.existsSync(dir)) {
|
|
65
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Recursively deletes a directory.
|
|
71
|
+
*/
|
|
72
|
+
function clearDirectory(dir: string) {
|
|
73
|
+
if (!fs.existsSync(dir)) return;
|
|
74
|
+
|
|
75
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
76
|
+
const entryPath = path.join(dir, entry.name);
|
|
77
|
+
if (entry.isDirectory()) {
|
|
78
|
+
clearDirectory(entryPath);
|
|
79
|
+
fs.rmdirSync(entryPath);
|
|
80
|
+
} else {
|
|
81
|
+
fs.unlinkSync(entryPath);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Recursively copies a directory and its contents.
|
|
88
|
+
*/
|
|
89
|
+
function copyDirectory(src: string, dest: string) {
|
|
90
|
+
if (!fs.existsSync(src)) {
|
|
91
|
+
console.warn(`โ ๏ธ Source directory not found: ${src}`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
ensureDirExists(dest);
|
|
96
|
+
|
|
97
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
98
|
+
const srcPath = path.join(src, entry.name);
|
|
99
|
+
const destPath = path.join(dest, entry.name);
|
|
100
|
+
|
|
101
|
+
if (entry.isDirectory()) {
|
|
102
|
+
copyDirectory(srcPath, destPath);
|
|
103
|
+
} else {
|
|
104
|
+
fs.copyFileSync(srcPath, destPath);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Converts dist/foo/index.html โ output/foo.html
|
|
111
|
+
* Keeps dist/index.html as output/index.html
|
|
112
|
+
*/
|
|
113
|
+
function getFlattenedHtmlOutputPath(inputFile: string, inputDir: string, outputDir: string): string {
|
|
114
|
+
const relative = path.relative(inputDir, inputFile);
|
|
115
|
+
const parts = relative.split(path.sep);
|
|
116
|
+
|
|
117
|
+
if (parts.length > 1 && parts[parts.length - 1] === "index.html") {
|
|
118
|
+
const folderName = parts[parts.length - 2];
|
|
119
|
+
return path.join(outputDir, `${folderName}.html`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return path.join(outputDir, relative);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Processes and flattens HTML files (expanded output)
|
|
127
|
+
*/
|
|
128
|
+
function processAllHTML(inputDir: string, outputDir: string): void {
|
|
129
|
+
const htmlFiles = getAllFilesWithExtension(inputDir, ".html");
|
|
130
|
+
if (htmlFiles.length === 0) {
|
|
131
|
+
console.warn(`โ ๏ธ No HTML files found in ${inputDir}`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (const inputFile of htmlFiles) {
|
|
136
|
+
const outputFile = getFlattenedHtmlOutputPath(inputFile, inputDir, outputDir);
|
|
137
|
+
const html = fs.readFileSync(inputFile, "utf-8");
|
|
138
|
+
|
|
139
|
+
// Filter to only keep astro-islands
|
|
140
|
+
const filtered = keepAstroIslands(html);
|
|
141
|
+
|
|
142
|
+
// Beautify / expand the HTML before writing
|
|
143
|
+
const beautified = beautifyHtml(filtered, {
|
|
144
|
+
indent_size: 2,
|
|
145
|
+
preserve_newlines: true,
|
|
146
|
+
max_preserve_newlines: 1,
|
|
147
|
+
wrap_line_length: 120,
|
|
148
|
+
unformatted: ["code", "pre", "em", "strong"],
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const prettyHtml = formatAstroIslandAttributes(beautified);
|
|
152
|
+
|
|
153
|
+
ensureDirExists(path.dirname(outputFile));
|
|
154
|
+
fs.writeFileSync(outputFile, prettyHtml, "utf-8");
|
|
155
|
+
|
|
156
|
+
console.log(`โ
Processed HTML: ${path.relative(inputDir, inputFile)} โ ${path.relative(outputDir, outputFile)}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Copies all .js files from dist/ to output/
|
|
162
|
+
*/
|
|
163
|
+
function copyAllJSFiles(inputDir: string, outputDir: string): void {
|
|
164
|
+
const jsFiles = getAllFilesWithExtension(inputDir, ".js");
|
|
165
|
+
if (jsFiles.length === 0) {
|
|
166
|
+
console.warn(`โ ๏ธ No JavaScript files found in ${inputDir}`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (const inputFile of jsFiles) {
|
|
171
|
+
const relativePath = path.relative(inputDir, inputFile);
|
|
172
|
+
const outputFile = path.join(outputDir, relativePath);
|
|
173
|
+
|
|
174
|
+
ensureDirExists(path.dirname(outputFile));
|
|
175
|
+
fs.copyFileSync(inputFile, outputFile);
|
|
176
|
+
|
|
177
|
+
console.log(`๐ Copied JS: ${relativePath}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function prefixAssetPathsInFile(filePath: string) {
|
|
182
|
+
const ASSET_PATH = process.env.ASSET_PATH || "";
|
|
183
|
+
let content = fs.readFileSync(filePath, "utf-8");
|
|
184
|
+
|
|
185
|
+
// Replace "/assets/..." inside string literals with prefixed path
|
|
186
|
+
// Match quotes + /assets/ at start of string
|
|
187
|
+
content = content.replace(/(["'`])\/assets\//g, `$1/${ASSET_PATH}/`);
|
|
188
|
+
|
|
189
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
190
|
+
console.log(`Prefixed asset paths in ${filePath}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function processAllJsFiles(dir: string) {
|
|
194
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
195
|
+
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
const fullPath = path.join(dir, entry.name);
|
|
198
|
+
if (entry.isDirectory()) {
|
|
199
|
+
processAllJsFiles(fullPath);
|
|
200
|
+
} else if (entry.name.endsWith(".js")) {
|
|
201
|
+
prefixAssetPathsInFile(fullPath);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Main function
|
|
209
|
+
*/
|
|
210
|
+
function processOutput() {
|
|
211
|
+
const inputDir = path.resolve("dist");
|
|
212
|
+
const outputDir = path.resolve("output");
|
|
213
|
+
const assetsSrc = path.join(inputDir, "assets");
|
|
214
|
+
const assetsDest = path.join(outputDir, "assets");
|
|
215
|
+
|
|
216
|
+
if (!fs.existsSync(inputDir)) {
|
|
217
|
+
console.error(`โ Input directory not found: ${inputDir}`);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ๐งน Clear output directory before writing
|
|
222
|
+
if (fs.existsSync(outputDir)) {
|
|
223
|
+
console.log("๐งน Clearing output directory...");
|
|
224
|
+
clearDirectory(outputDir);
|
|
225
|
+
} else {
|
|
226
|
+
ensureDirExists(outputDir);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log("โ๏ธ Processing HTML files...");
|
|
230
|
+
processAllHTML(inputDir, outputDir);
|
|
231
|
+
|
|
232
|
+
console.log("๐ฆ Copying assets...");
|
|
233
|
+
copyDirectory(assetsSrc, assetsDest);
|
|
234
|
+
|
|
235
|
+
console.log("๐ Copying JavaScript files...");
|
|
236
|
+
copyAllJSFiles(inputDir, outputDir);
|
|
237
|
+
|
|
238
|
+
console.log("๐ Processing asset paths...");
|
|
239
|
+
processAllJsFiles("output");
|
|
240
|
+
|
|
241
|
+
console.log("โ
Done!");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
processOutput();
|