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
3 changes: 1 addition & 2 deletions packages/kolibri-build/src/webpack.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,7 @@ module.exports = ({ mode = 'development', hot = false, cache = false, transpile
new TerserPlugin({
parallel: true,
terserOptions: {
mangle: false,
safari10: true,
// Don't specify mangle, as it is true by default.
output: {
comments: false,
},
Expand Down
53 changes: 22 additions & 31 deletions packages/kolibri-i18n/src/intl_code_gen.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const fs = require('fs');
const { writeSourceToFile } = require('kolibri-format');
const logger = require('kolibri-logging');
const uniqBy = require('lodash/uniqBy');

const logging = logger.getLogger('Kolibri Intl Data');

Expand Down Expand Up @@ -49,13 +50,15 @@ module.exports = function (outputDir, languageInfoPath) {
* Polyfill files are copied to ./polyfills/ directory to avoid external dependencies.
*/
`;
const vueIntlHeader = `module.exports = function () {
const data = [];`;
const vueIntlHeader = `module.exports = function (locale) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not entirely sure why we never dynamically loaded these polyfills previously - I think because one of them was always needed, so we just bundled all of them.

Another alternative would be to add loading of these to the base HTML page, so that we don't end up with deferred loading, but I doubt it would make much difference timing wise.

switch (locale) {`;

function generateVueIntlItems(language) {
/*
* Generate entries of this form:
* data.push(require('vue-intl/locale-data/ar.js'));
* Generate entries of this form with lazy loading:
*
* case 'ar':
* return import('vue-intl/locale-data/ar.js');
*
* Some Intl codes look like 'ar' and others look like 'bn-bd', so for Vue Intl
* we strip off the territory code if it's there.
Expand Down Expand Up @@ -88,17 +91,26 @@ module.exports = function (outputDir, languageInfoPath) {
}
}

return `data.push(require('${module_path}'));`;
return `
case '${vue_intl_code}':
return import('${module_path}');`;
}
}

const vueIntlFooter = `
return data;
default:
return import('vue-intl/locale-data/en.js');
}
};
`;

const vueIntlModule =
commonHeader + vueIntlHeader + languageInfo.map(generateVueIntlItems).join('') + vueIntlFooter;
commonHeader +
vueIntlHeader +
uniqBy(languageInfo, l => l.intl_code.split('-')[0])
.map(generateVueIntlItems)
.join('') +
vueIntlFooter;

const vueIntlModulePath = path.resolve(outputDir, 'vue-intl-locale-data.js');
const intlHeader = `module.exports = function(locale) {
Expand All @@ -109,14 +121,7 @@ module.exports = function (outputDir, languageInfoPath) {
* Generate entries of the form:
*
* case 'sw-tz':
* return new Promise(function(resolve) {
* require.ensure(
* ['intl/locale-data/jsonp/sw-TZ.js'],
* function(require) {
* resolve(() => require('intl/locale-data/jsonp/sw-TZ.js'));
* }
* );
* });
* return import('intl/locale-data/jsonp/sw-TZ.js');
*
* Note that not all codes have two parts, e.g. 'en' vs 'es-mx'.
*/
Expand Down Expand Up @@ -174,27 +179,13 @@ module.exports = function (outputDir, languageInfoPath) {

return `
case '${language.intl_code}':
return new Promise(function(resolve) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was originally written before our webpack version supported import() statements, so just updating this as well while we're here.

require.ensure(
['${module_path}'],
function(require) {
resolve(() => require('${module_path}'));
}
);
});`;
return import('${module_path}');`;
}
}

const intlFooter = `
default:
return new Promise(function(resolve) {
require.ensure(
['intl/locale-data/jsonp/en.js'],
function(require) {
resolve(() => require('intl/locale-data/jsonp/en.js'));
}
);
});
return import('intl/locale-data/jsonp/en.js');
}
};
`;
Expand Down
6 changes: 4 additions & 2 deletions packages/kolibri-jest-config/jest.conf/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ Vue.config.silent = true;
Vue.config.devtools = false;
Vue.config.productionTip = false;

i18nSetup(true);

Object.defineProperty(window, 'scrollTo', { value: () => {}, writable: true });

// Shows better NodeJS unhandled promise rejection errors
Expand All @@ -76,3 +74,7 @@ global.flushPromises = function flushPromises() {
});
};
/* eslint-enable vue/one-component-per-file */

module.exports = async function () {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jest allows you to export an async function as the module.exports of the setup module, and it will wait for it to complete before starting any tests. This is needed as otherwise tests start before the i18n configuration has finished.

Previously this wasn't a problem because the vue i18n data was loaded synchronously, but with the changes above, this is now necessary.

await i18nSetup(true);
};
3 changes: 2 additions & 1 deletion packages/kolibri-sandbox/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module.exports = {
[
'@babel/preset-env',
{
useBuiltIns: false,
useBuiltIns: 'usage',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This configuration forces corejs to polyfill things as they are used. We avoid this in the main Kolibri webpack configuration, and instead just provide a blanket environment polyfill with corejs, so as to avoid repeating polyfills and shims across plugins.

corejs: '3.46',
},
],
],
Expand Down
9 changes: 8 additions & 1 deletion packages/kolibri-sandbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,26 @@
"author": "Learning Equality",
"license": "MIT",
"devDependencies": {
"babel-loader": "^10.0.0",
"css-loader": "7.1.2",
"css-minimizer-webpack-plugin": "7.0.2",
"eslint-plugin-compat": "^6.0.2",
"html-webpack-plugin": "5.6.5",
"jquery": "3.5.1",
"jszip": "^3.10.1",
"mini-css-extract-plugin": "^2.9.4",
"mutationobserver-shim": "^0.3.7",
"purgecss": "^6.0.0"
"purgecss": "^6.0.0",
"terser-webpack-plugin": "^5.3.14",
"webpack": "^5.103.0"
},
"dependencies": {
"core-js": "3.47",
"dayjs": "^1.11.19",
"iri": "^1.3.1",
"is-language-code": "^3.1.0",
"iso8601-duration": "^2.1.3",
"lodash": "^4.17.21",
"toposort-class": "^1.0.1",
"uuid": "^13.0.0"
},
Expand Down
7 changes: 0 additions & 7 deletions packages/kolibri-sandbox/src/iframe.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
import 'core-js/es/array/includes';
import 'core-js/es/object/assign';
import 'core-js/es/object/entries';
import 'core-js/es/object/values';
import 'core-js/es/promise';
import 'core-js/es/string/starts-with';
import 'core-js/web/url';
import Sandbox from './iframeClient';

const sandbox = new Sandbox();
Expand Down
2 changes: 0 additions & 2 deletions packages/kolibri-sandbox/src/xAPI/xAPIConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
* xAPI Constants
*/

import 'core-js/features/set';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were individually polyfilling specific features in the kolibri-sandbox code. Much better to use babel present env to handle this for us instead.


export const OBJECT_TYPES = {
AGENT: 'Agent',
GROUP: 'Group',
Expand Down
1 change: 0 additions & 1 deletion packages/kolibri-sandbox/src/xAPI/xAPISchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* For more information, see:
* https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md
*/
import 'core-js/features/set';
import isArray from 'lodash/isArray';
import isBoolean from 'lodash/isBoolean';
import isFunction from 'lodash/isFunction';
Expand Down
38 changes: 34 additions & 4 deletions packages/kolibri-sandbox/webpack.config.js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really do not know how to read/review this file effectively

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross check it against the webpack configurations in kolibri-build test the corejs configuration by taking the built assets and testing them against browserstack for, say, iOS Safari 9.3.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i checked against 9.1 and 10.1 (which were available in browserstack) and ran the pex locally, for both i got a browser not supported message which matches with what I see in the browser list ('Safari >= 11.1') - but just wanted to confirm that this is also what you were thinking would happen....

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const path = require('path');
const fs = require('fs');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

function Plugin() {}
Expand Down Expand Up @@ -30,23 +32,51 @@ module.exports = {
entry: path.resolve(__dirname, './src/iframe.js'),
output: {
filename: 'sandbox-[contenthash].js',
chunkFilename: '[name]-[contenthash].bundle.js',
chunkFilename: 'sandbox-[name]-[contenthash].bundle.js',
path: path.resolve(__dirname, '../../kolibri/core/content/static/sandbox'),
},
mode: 'none',
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
test: /\.(js|mjs)$/,
loader: 'babel-loader',
exclude: { and: [/(uuid|core-js)/, { not: [/\.(esm\.js|mjs)$/] }] },
exclude: [
// From: https://webpack.js.org/loaders/babel-loader/#exclude-libraries-that-should-not-be-transpiled
// \\ for Windows, / for macOS and Linux
/node_modules[\\/]core-js/,
/node_modules[\\/]webpack[\\/]buildin/,
],
options: {
// Let babel auto-detect ES vs CommonJS
sourceType: 'unambiguous',
},
},
],
},
optimization: {
splitChunks: {
minChunks: 2,
},
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
mangle: {
safari10: true,
},
safari10: true,
output: {
comments: false,
},
},
}),
new CssMinimizerPlugin({
minimizerOptions: {
preset: ['default', { reduceIdents: false, zindex: false }],
},
}),
],
},
plugins: [
new Plugin(),
Expand Down
24 changes: 12 additions & 12 deletions packages/kolibri/composables/__tests__/useNav.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,59 @@ import { navItems, registerNavItem } from '../useNav';
describe('nav component', () => {
afterEach(() => {
// Clean up the registered navItems
navItems.pop();
navItems.value = [];
});
it('should not register a navItem that has no nav navItem specific properties defined', () => {
const navItem = {};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
it('should register a navItem that has a valid icon', () => {
const navItem = {
icon: 'timer',
url: 'https://example.com',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(1);
expect(navItems.value).toHaveLength(1);
});
it('should show not register a navItem that has an invalid icon', () => {
const navItem = {
icon: 'not an icon',
url: 'https://example.com',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
it('should not register a navItem that has a non-string icon', () => {
const navItem = {
url: 'https://example.com',
icon: 0.1,
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
it('should register a navItem that has a valid url', () => {
const navItem = {
icon: 'search',
url: 'https://example.com',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(1);
expect(navItems.value).toHaveLength(1);
});
it('should not register a navItem that has no url', () => {
const navItem = {
icon: 'search',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
it('should not register a navItem that has a non-string url', () => {
const navItem = {
icon: 'search',
url: 0.1,
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
Object.values(UserKinds).forEach(role => {
it(`should register a navItem that has a role of ${role}`, () => {
Expand All @@ -69,7 +69,7 @@ describe('nav component', () => {
role,
};
registerNavItem(navItem);
expect(navItems).toHaveLength(1);
expect(navItems.value).toHaveLength(1);
});
});
it('should not register a navItem that has an unrecognized role', () => {
Expand All @@ -79,7 +79,7 @@ describe('nav component', () => {
role: 'bill',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
Object.values(NavComponentSections).forEach(section => {
it(`should register a navItem that has a section of ${section}`, () => {
Expand All @@ -92,7 +92,7 @@ describe('nav component', () => {
section,
};
registerNavItem(navItem);
expect(navItems).toHaveLength(1);
expect(navItems.value).toHaveLength(1);
});
});
it('should not register a navItem that has an unrecognized section', () => {
Expand All @@ -102,6 +102,6 @@ describe('nav component', () => {
section: 'bill',
};
registerNavItem(navItem);
expect(navItems).toHaveLength(0);
expect(navItems.value).toHaveLength(0);
});
});
Loading
Loading