Merge branch 'format-suggestion-summary' into 'main'
[ProtonMail-WebClient.git] / applications / vpn-settings / webpack.config.ts
blob4ce753f539998acffc6a70a952b38522bd623a49
1 import HtmlWebpackPlugin from 'html-webpack-plugin';
2 import template from 'lodash.template';
3 import { readFileSync } from 'node:fs';
4 import * as path from 'node:path';
5 import type { HrefLang } from 'proton-account/pages/interface';
6 import { getPages } from 'proton-account/pages/pages';
7 import type { Parameters } from 'proton-account/src/pages/interface';
8 import type { Configuration } from 'webpack';
9 import 'webpack-dev-server';
11 import getConfig from '@proton/pack/webpack.config';
12 import CopyIndexHtmlWebpackPlugin from '@proton/pack/webpack/copy-index-html-webpack-plugin';
14 const getTemplateParameters = (
15     originalTemplateParameters: any,
16     hreflangs: HrefLang[],
17     shortLocalizedPathname: string,
18     parameters: Parameters & { pathname: string }
19 ) => {
20     let url = originalTemplateParameters.url;
21     const origin = url.replace(/\/$/, '');
22     if (parameters.pathname) {
23         url = `${origin}${parameters.pathname}`;
24     }
25     return {
26         ...originalTemplateParameters,
27         ...parameters,
28         url,
29         hreflangs: hreflangs.map(({ hreflang, pathname }) => {
30             return {
31                 hreflang,
32                 href: `${origin}${pathname}${parameters.pathname.replace(shortLocalizedPathname, '')}`,
33             };
34         }),
35     };
38 const result = async (env: any): Promise<Configuration> => {
39     const pagesPromise = getPages();
40     const config = getConfig(env);
41     const plugins = config.plugins || [];
42     config.plugins = plugins;
44     const htmlPlugin = plugins.find((plugin): plugin is HtmlWebpackPlugin => {
45         return plugin instanceof HtmlWebpackPlugin;
46     });
47     if (!htmlPlugin) {
48         throw new Error('Missing html plugin');
49     }
51     const rewrites: any[] = [];
52     // @ts-ignore
53     config.devServer.historyApiFallback.rewrites = rewrites;
55     const originalTemplateParameters = htmlPlugin.userOptions.templateParameters as { [key: string]: any };
57     const { pages, hreflangs } = await pagesPromise;
59     pages.forEach(({ rewrite }) => {
60         rewrites.push(rewrite);
61     });
63     plugins.push(
64         new CopyIndexHtmlWebpackPlugin((source) => {
65             const compiled = template(
66                 source,
67                 // Note: We use two different template interpolations, due to <%= require('./favicon.svg' %>, which requires
68                 // a lot more effort to support properly, so we use the default loader for that and our own loader for this.
69                 {
70                     evaluate: /\{\{([\s\S]+?)\}\}/g,
71                     interpolate: /\{\{=([\s\S]+?)\}\}/g,
72                     escape: /\{\{-([\s\S]+?)\}\}/g,
73                 },
74                 undefined
75             );
77             const index = {
78                 name: 'index.html',
79                 data: compiled(
80                     getTemplateParameters(originalTemplateParameters, hreflangs, '', {
81                         title: originalTemplateParameters.appName,
82                         description: originalTemplateParameters.description,
83                         pathname: '/',
84                     })
85                 ),
86             };
88             const rest = pages.map(({ shortLocalizedPathname, filename, parameters }) => {
89                 return {
90                     name: filename,
91                     data: compiled(
92                         getTemplateParameters(originalTemplateParameters, hreflangs, shortLocalizedPathname, parameters)
93                     ),
94                 };
95             });
97             const result = [index, ...rest];
98             const convertSnippet = readFileSync(path.resolve('./src/convert-snippet.html'))
99                 .toString()
100                 .replace(/\n/g, '');
102             return result.flatMap((result) => {
103                 const convertEntry = {
104                     name: result.name.replace('.html', '.convert.html'),
105                     data: result.data.replace('</title>', `</title>${convertSnippet}`),
106                 };
108                 return [result, convertEntry];
109             });
110         })
111     );
113     return config;
116 export default result;