Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 136 additions & 76 deletions configs/webpack/common.js
Original file line number Diff line number Diff line change
@@ -1,183 +1,243 @@
// shared config (dev and prod)
const { resolve, join } = require('path');
const { readFileSync } = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const NpmDtsPlugin = require('npm-dts-webpack-plugin')
const { DefinePlugin, IgnorePlugin } = require('webpack');
const process = require('process');
const { resolve, join } = require("path");
const { readFileSync } = require("fs");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const NpmDtsPlugin = require("npm-dts-webpack-plugin");
const { DefinePlugin, IgnorePlugin } = require("webpack");
const process = require("process");

const commitHash = require('child_process').execSync('git rev-parse --short=8 HEAD').toString().trim();
const commitHash = require("child_process")
.execSync("git rev-parse --short=8 HEAD")
.toString()
.trim();

let dependencies = {};
try {
dependencies = JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'dependencies', 'dependencies.json')));
dependencies = JSON.parse(
readFileSync(
resolve(__dirname, "..", "..", "dependencies", "dependencies.json")
)
);
} catch (e) {
console.log('Failed to read dependencies.json');
console.log("Failed to read dependencies.json");
}

const modules = ['node_modules'];
const modules = ["node_modules"];
if (dependencies.cpython) modules.push(resolve(dependencies.cpython));

let libkiprCDocumentation = undefined;
let libkiprCCCommonDocumentation = undefined;
if (dependencies.libkipr_c_documentation) {
libkiprCDocumentation = JSON.parse(readFileSync(resolve(dependencies.libkipr_c_documentation)));
libkiprCDocumentation = JSON.parse(
readFileSync(resolve(dependencies.libkipr_c_documentation))
);
}
if (dependencies.libkipr_c_common_documentation) {
libkiprCCCommonDocumentation = JSON.parse(
readFileSync(resolve(dependencies.libkipr_c_common_documentation))
);
}

let i18n = {};
try {
i18n = JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'i18n', 'i18n.json')));
i18n = JSON.parse(
readFileSync(resolve(__dirname, "..", "..", "i18n", "i18n.json"))
);
} catch (e) {
console.log('Failed to read i18n.json');
console.log("Failed to read i18n.json");
console.log(`Please run 'yarn run build-i18n'`);
process.exit(1);
}


module.exports = {
entry: {
app: './index.tsx',
login: './components/Login/index.tsx',
plugin: './lms/plugin/index.tsx',
parentalConsent: './components/ParentalConsent/index.tsx',
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js',
'ts.worker': 'monaco-editor/esm/vs/language/typescript/ts.worker.js',
app: "./index.tsx",
login: "./components/Login/index.tsx",
plugin: "./lms/plugin/index.tsx",
parentalConsent: "./components/ParentalConsent/index.tsx",
"editor.worker": "monaco-editor/esm/vs/editor/editor.worker.js",
"ts.worker": "monaco-editor/esm/vs/language/typescript/ts.worker.js",
},
output: {
filename: (pathData) => {
if (pathData.chunk.name === 'editor.worker') return 'editor.worker.bundle.js';
if (pathData.chunk.name === 'ts.worker') return 'ts.worker.bundle.js';
return 'js/[name].[contenthash].min.js';
if (pathData.chunk.name === "editor.worker")
return "editor.worker.bundle.js";
if (pathData.chunk.name === "ts.worker") return "ts.worker.bundle.js";
return "js/[name].[contenthash].min.js";
},
path: resolve(__dirname, '../../dist'),
publicPath: '/',
path: resolve(__dirname, "../../dist"),
publicPath: "/",
clean: true,
},
externals: [
'child_process',
'fs',
'path',
'crypto',
],
watchOptions: {
ignored: /node_modules\/(?!ivygate)/,
},

externals: ["child_process", "fs", "path", "crypto"],
snapshot: {
managedPaths: [], // ensures node_modules/ivygate symlink is watched
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
extensions: [".ts", ".tsx", ".js", ".jsx"],
fallback: {
fs: false,
path: false,
},
alias: {
state: resolve(__dirname, '../../src/state'),
'@i18n': resolve(__dirname, '../../src/util/i18n'),
state: resolve(__dirname, "../../src/state"),
"@i18n": resolve(__dirname, "../../src/util/i18n"),
"@ivygate": resolve(__dirname, "../../node_modules/ivygate"),
},
symlinks: false,
modules //: [resolve(__dirname, '../../src'), 'node_modules']
modules, //: [resolve(__dirname, '../../src'), 'node_modules']
},
context: resolve(__dirname, '../../src'),
watchOptions: {
followSymlinks: true,
},
context: resolve(__dirname, "../../src"),
module: {
rules: [
// Apply class static block transform to monaco-editor ESM sources inside node_modules
// because we normally exclude node_modules from Babel handling.
{
test: /\.js$/,
include: /node_modules[\/\\]monaco-editor[\/\\]esm/,
use: [
{
loader: 'babel-loader',
loader: "babel-loader",
options: {
plugins: [
'@babel/plugin-transform-class-static-block'
]
}
}
]
plugins: ["@babel/plugin-transform-class-static-block"],
},
},
],
},
{
test: /\.js$/,
use: ['babel-loader', 'source-map-loader'],
use: ["babel-loader", "source-map-loader"],
exclude: /node_modules/,
},
{
test: /\.tsx?$/,
use: [
{
loader: 'babel-loader',
loader: "babel-loader",
options: {
plugins: ['@babel/plugin-syntax-import-meta']
}
plugins: ["@babel/plugin-syntax-import-meta"],
},
},
{
loader: 'ts-loader',
loader: "ts-loader",
options: {
transpileOnly: true,
allowTsInNodeModules: true,
}
}
},
},
],
// ✅ This allows both IvyGate and Itch from node_modules
exclude: /node_modules\/(?!ivygate|itch)/,
include: [
resolve(__dirname, "../../src"),
resolve(__dirname, "../../ivygate/src"),
resolve(__dirname, "../../node_modules/ivygate/src"),
resolve(__dirname, "../../node_modules/itch/src"),
],
},
{
test: /\.css$/,
use: [
'style-loader',
"style-loader",
{
loader: 'css-loader',
loader: "css-loader",
options: {
importLoaders: 1
}
}
importLoaders: 1,
},
},
],
},
{
test: /\.scss$/,
use: [
'style-loader',
"style-loader",
{
loader: 'css-loader',
loader: "css-loader",
options: {
importLoaders: 1
}
importLoaders: 1,
},
},
'sass-loader',
"sass-loader",
],
},
{
test: /\.(jpe?g|png|gif|svg|PNG)$/i,
use: [
'file-loader?hash=sha512&digest=hex&name=img/[hash].[ext]',
'image-webpack-loader?bypassOnDebug&optipng.optimizationLevel=7&gifsicle.interlaced=false',
{
loader: "file-loader",
options: {
name: "img/[hash].[ext]",
},
},
{
loader: "image-webpack-loader",
options: {
mozjpeg: { progressive: true },
optipng: { optimizationLevel: 7 },
gifsicle: { interlaced: false },
pngquant: { quality: [0.65, 0.9], speed: 4 },
disable: process.env.NODE_ENV === "development",
},
},
],
},
{
test: /\.(woff|woff2|eot|ttf)$/,
loader: 'url-loader',
loader: "url-loader",
options: {
limit: 100000,
},
}
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: 'index.html.ejs', excludeChunks: ['login', 'plugin', 'parentalConsent'] }),
new HtmlWebpackPlugin({ template: 'components/Login/login.html.ejs', filename: 'login.html', chunks: ['login'] }),
new HtmlWebpackPlugin({ template: 'lms/plugin/plugin.html.ejs', filename: 'plugin.html', chunks: ['plugin'] }),
new HtmlWebpackPlugin({ template: 'components/ParentalConsent/parental-consent.html.ejs', filename: 'parental-consent.html', chunks: ['parentalConsent'] }),
new HtmlWebpackPlugin({
template: "index.html.ejs",
excludeChunks: ["login", "plugin", "parentalConsent"],
}),
new HtmlWebpackPlugin({
template: "components/Login/login.html.ejs",
filename: "login.html",
chunks: ["login"],
}),
new HtmlWebpackPlugin({
template: "lms/plugin/plugin.html.ejs",
filename: "plugin.html",
chunks: ["plugin"],
}),
new HtmlWebpackPlugin({
template: "components/ParentalConsent/parental-consent.html.ejs",
filename: "parental-consent.html",
chunks: ["parentalConsent"],
}),
new DefinePlugin({
SIMULATOR_VERSION: JSON.stringify(require('../../package.json').version),
SIMULATOR_VERSION: JSON.stringify(require("../../package.json").version),
SIMULATOR_GIT_HASH: JSON.stringify(commitHash),
SIMULATOR_HAS_CPYTHON: JSON.stringify(dependencies.cpython !== undefined),
SIMULATOR_LIBKIPR_C_DOCUMENTATION: JSON.stringify(libkiprCDocumentation),
SIMULATOR_I18N: JSON.stringify(i18n),

// needed because ivygate relies on them being defined
IDE_LIBKIPR_C_DOCUMENTATION: JSON.stringify(libkiprCDocumentation),
IDE_LIBKIPR_C_COMMON_DOCUMENTATION: null,
IDE_LIBKIPR_C_COMMON_DOCUMENTATION: JSON.stringify(
libkiprCCCommonDocumentation
),
IDE_I18N: JSON.stringify(i18n),
}),
new NpmDtsPlugin({
root: resolve(__dirname, '../../'),
logLevel: 'error',
root: resolve(__dirname, "../../"),
logLevel: "error",
force: true,
output: resolve(__dirname, '../../dist/simulator.d.ts'),
})
output: resolve(__dirname, "../../dist/simulator.d.ts"),
}),
],
performance: {
hints: false,
},
};
};
5 changes: 3 additions & 2 deletions dependencies/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ def is_tool(name):

print('Generating JSON documentation...')
libkipr_c_documentation_json = f'{libkipr_build_c_dir}/documentation/json.json'
libkipr_c_common_documentation = f'{libkipr_build_c_dir}/documentation/json_common.json'
subprocess.run(
[ python, 'generate_doxygen_json.py', f'{libkipr_build_c_dir}/documentation/xml', libkipr_c_documentation_json ],
# [ 'python3', 'generate_doxygen_json.py', f'{libkipr_build_c_dir}/documentation/xml', libkipr_c_documentation_json ],
[ python, 'generate_doxygen_json.py', f'{libkipr_build_c_dir}/documentation/xml', libkipr_c_documentation_json, libkipr_c_common_documentation],
cwd = working_dir,
check = True
)
Expand Down Expand Up @@ -278,6 +278,7 @@ def is_tool(name):
'cpython': f'{cpython_emscripten_build_dir}',
'cpython_hash': hash_dir(cpython_dir),
"libkipr_c_documentation": libkipr_c_documentation_json,
"libkipr_c_common_documentation": libkipr_c_common_documentation,
'scratch_rt': f'{scratch_runtime_path}.js',
})

Expand Down
Loading