Commit 5167e59f authored by Daniele Berardo's avatar Daniele Berardo

Merge branch 'development' into 'master'

Development

See merge request !32
parents 947a66e8 bce0e54c
Pipeline #186899519 passed with stages
in 13 minutes and 15 seconds
# This file is a template, and might need editing before it works on your project.
image: node:latest
# This folder is cached between builds
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- lib/node_modules/
# Default cache directory from https://classic.yarnpkg.com/en/docs/install-ci/#gitlab.
- node_modules/
# Enables git-lab CI caching. Both .cache and public must be cached, otherwise builds will fail.
- .cache/
- public/
before_script:
- cd lib/
......@@ -14,7 +16,7 @@ before_script:
stages:
- build
- test
- deploy
- pages
build:
stage: build
......@@ -31,9 +33,13 @@ test:
- npm install
- npm run test
deploy:
stage: deploy
pages:
stage: pages
script:
- cd ../pages
- npm install
- ./node_modules/.bin/gatsby build --prefix-paths
- cd ../lib
- npm install
- npm run build
- npm run storybook:build
......
......@@ -6,6 +6,8 @@
"parser": "@typescript-eslint/parser",
"extends": "airbnb",
"rules": {
"no-confusing-arrow": "off",
"implicit-arrow-linebreak": "off",
"import/no-webpack-loader-syntax": "off",
"no-eval": "warn",
"no-continue": "off",
......
{
"name": "@tecnojest/widget-base",
"version": "1.4.27",
"version": "1.4.32",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -4356,14 +4356,15 @@
}
},
"asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
"integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"dev": true,
"requires": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0"
"minimalistic-assert": "^1.0.0",
"safer-buffer": "^2.1.0"
},
"dependencies": {
"bn.js": {
......@@ -5264,9 +5265,9 @@
"dev": true
},
"bn.js": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz",
"integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
"integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
"dev": true
},
"body-parser": {
......@@ -5563,16 +5564,16 @@
}
},
"browserify-sign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.0.tgz",
"integrity": "sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
"integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"dev": true,
"requires": {
"bn.js": "^5.1.1",
"browserify-rsa": "^4.0.1",
"create-hash": "^1.2.0",
"create-hmac": "^1.1.7",
"elliptic": "^6.5.2",
"elliptic": "^6.5.3",
"inherits": "^2.0.4",
"parse-asn1": "^5.1.5",
"readable-stream": "^3.6.0",
......@@ -5892,9 +5893,9 @@
"dev": true
},
"chokidar": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz",
"integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==",
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
"integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
"dev": true,
"optional": true,
"requires": {
......@@ -5983,6 +5984,7 @@
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
"integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
"dev": true,
"optional": true,
"requires": {
"arr-union": "^3.1.0",
"define-property": "^0.2.5",
......@@ -5995,15 +5997,10 @@
"resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
"integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
"dev": true,
"optional": true,
"requires": {
"is-descriptor": "^0.1.0"
}
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
}
}
},
......@@ -6681,13 +6678,13 @@
}
},
"create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
"integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
"integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"dev": true,
"requires": {
"bn.js": "^4.1.0",
"elliptic": "^6.0.0"
"elliptic": "^6.5.3"
},
"dependencies": {
"bn.js": {
......@@ -15178,14 +15175,13 @@
}
},
"parse-asn1": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
"integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
"integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"dev": true,
"requires": {
"asn1.js": "^4.0.0",
"asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0",
"create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.0",
"pbkdf2": "^3.0.3",
"safe-buffer": "^5.1.1"
......@@ -20049,6 +20045,15 @@
"to-regex": "^3.0.2"
}
},
"serialize-javascript": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
......@@ -20056,16 +20061,16 @@
"dev": true
},
"terser-webpack-plugin": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz",
"integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
"integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
"dev": true,
"requires": {
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
"serialize-javascript": "^3.1.0",
"serialize-javascript": "^4.0.0",
"source-map": "^0.6.1",
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
......
{
"name": "@tecnojest/widget-base",
"author": "Tecnojest srl https://www.invidea.it",
"version": "1.4.27",
"version": "1.4.32",
"publishConfig": {
"registry": "https://npm.invidea.it"
},
......@@ -21,7 +21,7 @@
"start": "webpack-dev-server",
"test-update-snapshots": "jest --updateSnapshot",
"storybook": "start-storybook -p 6006",
"storybook:build": "build-storybook -c .storybook -o ../public",
"storybook:build": "build-storybook -c .storybook -o ../public/storybook",
"storybook:serve": "npx http-server ../public"
},
"devDependencies": {
......@@ -88,7 +88,7 @@
"uglify-loader": "^3.0.0",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^4.0.0",
"webpack": "4.42.0",
"webpack": "^4.42.0",
"webpack-cli": "3.3.10",
"webpack-dev-server": "3.10.3",
"webpack-obfuscator": "0.18.5",
......@@ -139,6 +139,7 @@
"postcss-loader": "3.0.0",
"raw-loader": "^4.0.1",
"sass-loader": "8.0.0",
"semver": "^7.1.3",
"source-map-loader": "^1.0.1",
"style-loader": "1.0.1",
"tape": "^4.13.0",
......
......@@ -23,18 +23,17 @@ import EventManager from './events/event-manager';
const DEFAULT_UID: UID = '-1';
const INITIAL_OPTIONS: Options = {
appendFooter: true,
appendTooltip: true,
singleton: false,
setCookie: false,
setCookieDomain: null,
loadScriptAJAX: false,
tokenName: 'token',
className: parseClassName(process.env.WIDGET_MAIN_CSS_CLASS),
};
export default class EmbeddableWidget {
static INITIAL_OPTIONS: Options = {
appendFooter: true,
appendTooltip: true,
singleton: false,
setCookie: false,
setCookieDomain: null,
loadScriptAJAX: false,
tokenName: 'token',
className: parseClassName(process.env.WIDGET_MAIN_CSS_CLASS),
};
/**
* The engine configuration
*/
......@@ -86,6 +85,9 @@ export default class EmbeddableWidget {
}
static getState(uid: UID): State | void {
if (EmbeddableWidget.Engine.getState) {
return EmbeddableWidget.Engine.getState(uid);
}
if (EmbeddableWidget.Widget.getState) {
return EmbeddableWidget.Widget.getState(uid);
}
......@@ -182,7 +184,7 @@ export default class EmbeddableWidget {
: {};
const options: Options = {
...INITIAL_OPTIONS,
...EmbeddableWidget.INITIAL_OPTIONS,
...EmbeddableWidget.options,
...defaultOptionsFromProps,
...this.Widget.options,
......
......@@ -63,6 +63,7 @@ export interface Engine {
unmountComponentAtNode: (node: HTMLElement) => void;
resetState?: (uid: UID, state: State) => void;
getState?: (uid: UID) => State;
}
export interface PackageJson {
......@@ -72,17 +73,18 @@ export interface PackageJson {
}
export interface Script {
authenticate: boolean | undefined;
src: string;
defer: boolean;
name: string;
src: string;
dependsOn: string;
aliases: string[];
minVersion: string;
maxVersion: string;
defer: boolean;
isLoading: boolean;
loaded: boolean;
dependsOn: string;
authenticate: boolean | undefined;
}
export interface Style {
......
......@@ -2,6 +2,9 @@ import { Style, Script, Options } from '../types';
const semver = require('semver');
const getScriptElement = (name: string): HTMLScriptElement | null =>
document.querySelector(`script[data-package="${name}"`);
export const loadStyles = (styles: Style[] = []): void => {
styles.map(({ src, name }) => {
if (!document.getElementById(name) || !name) {
......@@ -24,51 +27,37 @@ export const loadStyles = (styles: Style[] = []): void => {
const scriptAlreadyLoaded = ({
name,
src,
aliases,
minVersion,
maxVersion,
loaded,
}: Script): boolean => {
if (loaded) return !!loaded;
let alreadyLoaded: boolean = !!document.querySelector('script#' + name);
name = name.toLowerCase();
if (loaded) return true;
const includesJquery: boolean = name.includes('jquery');
const isJquery: boolean =
src.includes('jquery.js') || src.includes('jquery.js') || name === 'jquery';
if (!alreadyLoaded) {
let namespace: any;
if (includesJquery) {
if (typeof window['$'] == 'function') namespace = window['$'];
else if (typeof window['jQuery'] == 'function') namespace = window['jQuery'];
else namespace = window['jQuery'] || window['$'] || window['JQuery'];
if (namespace && !isJquery) {
namespace = namespace[name.replace('jquery-', '')];
}
if (namespace && isJquery) namespace = { version: namespace.fn.jquery };
} else {
namespace = window[name];
const possibleScriptNames = aliases && aliases.length ? [name, ...aliases] : [name];
let alreadyLoaded: boolean = possibleScriptNames.some(
(possibleName) => !!getScriptElement(possibleName)
);
let namespace: any,
namespaceName: string = '';
possibleScriptNames.forEach((possibleName) => {
if (window[possibleName]) {
namespaceName = possibleName;
namespace = window[possibleName];
}
});
alreadyLoaded = !!namespace;
if (alreadyLoaded) {
const version = namespace.version;
console.warn(
'Namespace version, ',
version,
'of',
name,
'already loadad'
);
if (minVersion && !semver.gt(version, semver.coerce(minVersion))) {
throw Error(
`Version ${version} of ${name} is lower than min version ${minVersion}`
);
}
if (maxVersion && !semver.lt(version, maxVersion)) {
throw Error(
`Version ${version} of ${name} is higher than min version ${maxVersion}`
);
}
alreadyLoaded = !!namespace;
if (alreadyLoaded) {
const version = namespace.version || (namespace.fn && namespace.fn.jquery);
console.warn('Namespace version,', version, 'of', name, 'already loaded under', namespaceName);
if (minVersion && semver.lt(version, semver.coerce(minVersion))) {
throw Error(`Version ${version} of ${name} is lower than min version ${minVersion}`);
}
if (maxVersion && semver.gt(version, maxVersion)) {
throw Error(`Version ${version} of ${name} is higher than min version ${maxVersion}`);
}
}
return !!alreadyLoaded;
......@@ -98,17 +87,9 @@ export const loadScript = ({
if (script.authenticate && token) headers['Authorization'] = 'Bearer ' + token;
}
const parent: Script =
scripts[scripts.findIndex((s) => s.name === script.dependsOn)];
const parent: Script = scripts[scripts.findIndex((s) => script.dependsOn.includes(s.name))];
if (parent && !scriptAlreadyLoaded(parent)) {
//&& !parent.isLoading)
console.log(
'script',
name,
'going after',
parent,
scriptAlreadyLoaded(parent)
);
console.log('script', name, 'going after', parent, scriptAlreadyLoaded(parent));
loadScript({ script: parent, options, scripts })
.then(() => {
loadScript({ script, options, scripts })
......@@ -120,9 +101,7 @@ export const loadScript = ({
reject(e);
});
} else {
scripts[
scripts.findIndex((s) => s.name === script.name)
].isLoading = true;
scripts[scripts.findIndex((s) => s.name === script.name)].isLoading = true;
fetch(src, {
mode: 'cors',
// credentials: 'include',
......@@ -132,12 +111,8 @@ export const loadScript = ({
.then((scrpt) => {
eval.apply(null, [scrpt]);
// Possible alternative to eval: new Function(scrpt).apply(null, [scrpt]);
scripts[
scripts.findIndex((s) => s.name === script.name)
].loaded = true;
scripts[
scripts.findIndex((s) => s.name === script.name)
].isLoading = false;
scripts[scripts.findIndex((s) => s.name === script.name)].loaded = true;
scripts[scripts.findIndex((s) => s.name === script.name)].isLoading = false;
console.warn('here loading ', name);
resolve();
return;
......@@ -150,18 +125,17 @@ export const loadScript = ({
}
} else {
const scriptEl: HTMLScriptElement = document.createElement('script');
scriptEl.id = name;
scriptEl.dataset.package = name;
scriptEl.src = src;
scriptEl.addEventListener('load', () => {
console.log('loaded', name);
resolve();
});
scriptEl.addEventListener('error', (e) => {
reject(e);
});
const parent: HTMLScriptElement | null = dependsOn
? document.querySelector('script#' + dependsOn)
: null;
const parent: HTMLScriptElement | null = dependsOn ? getScriptElement(dependsOn) : null;
if (parent) {
parent.addEventListener('load', () => {
if (scriptAlreadyLoaded(script)) {
......
......@@ -12,10 +12,10 @@ export const prepareScripts = (
const script: Script = scripts[key];
if (skip.indexOf(script.name) !== -1) continue;
if (script.dependsOn) {
const index = scripts.findIndex((s) => s.name === script.dependsOn);
const index = scripts.findIndex((s) => script.dependsOn.includes(s.name));
const scriptDep: Script = scripts[index];
if (scriptsToLoad.filter((s: Script) => s.name === script.dependsOn).length == 0) {
if (scriptsToLoad.filter((s: Script) => script.dependsOn.includes(s.name)).length == 0) {
scriptsToLoad.push(scriptDep);
skip.push(scriptDep.name);
}
......@@ -24,7 +24,8 @@ export const prepareScripts = (
}
const promises: FIX_TYPE[] = [];
scriptsToLoad.forEach((script) => promises.push(
scriptsToLoad.forEach((script) =>
promises.push(
loadScript({
script,
options: widgetOptions,
......
{
"lockfileVersion": 1
}
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
{
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended",
"prettier",
"prettier/react"
],
"plugins": ["react", "import", "jsx-a11y"],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"react/prop-types": 0,
"react/react-in-jsx-scope": "off",
"lines-between-class-members": ["error", "always"],
"padding-line-between-statements": [
"error",
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
{
"blankLine": "always",
"prev": ["const", "let", "var"],
"next": ["const", "let", "var"]
},
{ "blankLine": "always", "prev": "directive", "next": "*" },
{ "blankLine": "any", "prev": "directive", "next": "directive" }
]
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 10,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"env": {
"es6": true,
"browser": true,
"node": true
},
"globals": {
"graphql": false
}
}
public
.cache
node_modules
*DS_Store
*.env
.idea/
const pathPrefix = "/widgets";
const config = {