mirror of
https://github.com/ApfelTeeSaft/LiveSplitOne.git
synced 2026-09-02 19:20:05 +00:00
This is necessary for the changelog generation to work correctly. Additionally this includes an improvement to sort the contributors alphabetically, if they have the same amount of contributions.
216 lines
7.7 KiB
JavaScript
216 lines
7.7 KiB
JavaScript
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
import HtmlInlineScriptPlugin from 'html-inline-script-webpack-plugin';
|
|
import FaviconsWebpackPlugin from "favicons-webpack-plugin";
|
|
import { CleanWebpackPlugin } from "clean-webpack-plugin";
|
|
import WorkboxPlugin from "workbox-webpack-plugin";
|
|
import ReactRefreshTypeScript from 'react-refresh-typescript';
|
|
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
|
|
import webpack from "webpack";
|
|
import { execSync } from "child_process";
|
|
import moment from "moment";
|
|
import path from "path";
|
|
import fetch from "node-fetch";
|
|
import { fileURLToPath } from 'url';
|
|
import * as sass from "sass";
|
|
|
|
function parseChangelog() {
|
|
return execSync("git log --grep \"^Changelog: \" -10")
|
|
.toString()
|
|
.split(/^commit /)
|
|
.slice(1)
|
|
.map((commit) => {
|
|
const changelogIndex = commit.indexOf(" Changelog: ");
|
|
if (changelogIndex === -1) {
|
|
return {};
|
|
}
|
|
const dateIndex = commit.indexOf(/^Date: /);
|
|
if (dateIndex === -1) {
|
|
return {};
|
|
}
|
|
const afterDate = commit.substring(dateIndex + 8);
|
|
const date = moment(new Date(afterDate.substring(0, afterDate.indexOf("\n")))).utc().format("YYYY-MM-DD");
|
|
const id = commit.substring(0, commit.indexOf("\n"));
|
|
const message = commit
|
|
.substring(changelogIndex + 15)
|
|
.replaceAll("\n ", "\n")
|
|
.trim();
|
|
return {
|
|
id,
|
|
message,
|
|
date,
|
|
};
|
|
})
|
|
.filter((changelog) => changelog.message);
|
|
}
|
|
|
|
export default async (env, argv) => {
|
|
const getContributorsForRepo = async (repoName) => {
|
|
const contributorsData = await fetch(`https://api.github.com/repos/LiveSplit/${repoName}/contributors`);
|
|
return contributorsData.json();
|
|
}
|
|
|
|
const lsoContributorsList = await getContributorsForRepo("LiveSplitOne");
|
|
const coreContributorsList = await getContributorsForRepo("livesplit-core");
|
|
|
|
const coreContributorsMap = {};
|
|
for (const coreContributor of coreContributorsList) {
|
|
if (coreContributor.type === "User" && !coreContributor.login.includes("dependabot")) {
|
|
coreContributorsMap[coreContributor.login] = coreContributor;
|
|
}
|
|
}
|
|
|
|
for (let lsoContributor of lsoContributorsList) {
|
|
const existingContributor = coreContributorsMap[lsoContributor.login];
|
|
if (existingContributor) {
|
|
existingContributor.contributions += lsoContributor.contributions;
|
|
} else if (lsoContributor.type === "User" && !lsoContributor.login.includes("dependabot")) {
|
|
coreContributorsMap[lsoContributor.login] = lsoContributor;
|
|
}
|
|
}
|
|
|
|
const contributorsList = Object.values(coreContributorsMap)
|
|
// Sort by contributions, but fallback to alphabetical order for the
|
|
// same amount of contributions
|
|
.sort((a, b) => a.login > b.login ? 1 : b.login > a.login ? -1 : 0)
|
|
.sort((a, b) => b.contributions - a.contributions)
|
|
.map((user) => {
|
|
return { id: user.id, name: user.login };
|
|
});
|
|
const commitHash = execSync("git rev-parse --short HEAD").toString();
|
|
const date = moment.utc().format("YYYY-MM-DD kk:mm:ss z");
|
|
|
|
const changelog = parseChangelog();
|
|
|
|
const basePath = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
const isProduction = argv.mode === "production";
|
|
const distPath = path.join(basePath, "dist");
|
|
|
|
return {
|
|
entry: {
|
|
"bundle": ["./src/index.tsx"],
|
|
},
|
|
output: {
|
|
filename: "[name].js",
|
|
path: distPath,
|
|
publicPath: '',
|
|
},
|
|
|
|
devtool: isProduction ? undefined : "source-map",
|
|
|
|
devServer: {
|
|
port: 8080,
|
|
hot: true
|
|
},
|
|
|
|
resolve: {
|
|
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js", ".json", ".wasm"],
|
|
},
|
|
|
|
plugins: [
|
|
...(isProduction ? [new CleanWebpackPlugin()] : []),
|
|
new FaviconsWebpackPlugin({
|
|
logo: path.resolve("src/assets/icon.svg"),
|
|
inject: true,
|
|
favicons: {
|
|
appName: "LiveSplit One",
|
|
appDescription: "A version of LiveSplit that works on a lot of platforms.",
|
|
developerName: "CryZe",
|
|
developerURL: "https://livesplit.org",
|
|
background: "#171717",
|
|
theme_color: "#232323",
|
|
appleStatusBarStyle: "black-translucent",
|
|
icons: {
|
|
coast: false,
|
|
yandex: false,
|
|
},
|
|
start_url: "/",
|
|
},
|
|
}),
|
|
new HtmlWebpackPlugin({
|
|
template: "./src/index.html",
|
|
}),
|
|
new webpack.DefinePlugin({
|
|
BUILD_DATE: JSON.stringify(date),
|
|
COMMIT_HASH: JSON.stringify(commitHash),
|
|
CONTRIBUTORS_LIST: JSON.stringify(contributorsList),
|
|
CHANGELOG: JSON.stringify(changelog),
|
|
}),
|
|
...(isProduction ? [
|
|
new HtmlInlineScriptPlugin({
|
|
scriptMatchPattern: ['^bundle.js$'],
|
|
}),
|
|
new WorkboxPlugin.GenerateSW({
|
|
clientsClaim: true,
|
|
skipWaiting: true,
|
|
maximumFileSizeToCacheInBytes: 100 * 1024 * 1024,
|
|
exclude: [
|
|
/^assets/,
|
|
/\.LICENSE\.txt$/,
|
|
],
|
|
|
|
runtimeCaching: [{
|
|
urlPattern: (context) => {
|
|
return self.origin === context.url.origin &&
|
|
context.url.pathname.startsWith("/assets/");
|
|
},
|
|
handler: "CacheFirst",
|
|
}],
|
|
})
|
|
] : []),
|
|
...(!isProduction ? [new ReactRefreshWebpackPlugin()] : [])
|
|
],
|
|
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.tsx?$/,
|
|
use: [
|
|
{
|
|
loader: "ts-loader",
|
|
options: {
|
|
getCustomTransformers: () => ({
|
|
before: [!isProduction && ReactRefreshTypeScript()].filter(Boolean),
|
|
}),
|
|
transpileOnly: !isProduction,
|
|
},
|
|
},
|
|
],
|
|
exclude: "/node_modules",
|
|
},
|
|
{
|
|
test: /\.(s?)css$/,
|
|
use: [
|
|
"style-loader",
|
|
{
|
|
loader: "css-loader",
|
|
options: {
|
|
importLoaders: 1,
|
|
modules: "icss",
|
|
},
|
|
},
|
|
{
|
|
loader: "sass-loader",
|
|
options: {
|
|
// Prefer `dart-sass`
|
|
implementation: sass,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
test: /\.(png|jpg|gif|woff|ico|svg)$/,
|
|
type: 'asset/resource'
|
|
},
|
|
],
|
|
},
|
|
|
|
experiments: {
|
|
syncWebAssembly: true,
|
|
topLevelAwait: true,
|
|
},
|
|
|
|
mode: isProduction ? "production" : "development",
|
|
};
|
|
};
|