@financial-times/custom-code-component 0.0.9 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/custom-code-component.d.ts +9 -3
- package/dist/custom-code-component.js +13 -10
- package/package.json +5 -2
- package/src/custom-code-component.ts +16 -6
- package/src/custom-code-component.xsd +67 -0
- package/.circleci/config.yml +0 -44
- package/.eslintignore +0 -1
- package/.eslintrc.cjs +0 -23
- package/.github/CODEOWNERS +0 -1
- package/index.html +0 -22
- package/test/styles.css +0 -6
- package/test/test16.jsx +0 -31
- package/test/test18.jsx +0 -29
- package/test.json +0 -1
- package/vite.config.js +0 -18
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file
|
|
3
|
-
* Main component definition for
|
|
3
|
+
* Main component definition for custom-code-component
|
|
4
4
|
*/
|
|
5
5
|
import { ContentTree } from "@financial-times/content-tree";
|
|
6
6
|
export declare const init: () => void;
|
|
@@ -9,7 +9,13 @@ export interface CustomCodeComponent extends ContentTree.Node {
|
|
|
9
9
|
path: string;
|
|
10
10
|
versionRange: string;
|
|
11
11
|
altText: string;
|
|
12
|
-
|
|
12
|
+
lastModified: string;
|
|
13
13
|
fallbackImage?: ContentTree.Image;
|
|
14
|
-
|
|
14
|
+
displayFallbackText: boolean;
|
|
15
|
+
layout: "in-line" | "mid-grid" | "full-grid" | "full-bleed";
|
|
16
|
+
attributes: {
|
|
17
|
+
[key: string]: string | boolean | undefined;
|
|
18
|
+
} | {
|
|
19
|
+
children?: CustomCodeComponent | Array<CustomCodeComponent>;
|
|
20
|
+
};
|
|
15
21
|
}
|
|
@@ -11,36 +11,39 @@ class u extends HTMLElement {
|
|
|
11
11
|
]);
|
|
12
12
|
}
|
|
13
13
|
async connectedCallback() {
|
|
14
|
-
var
|
|
15
|
-
const n = this.getAttribute("path"), s = this.hasAttribute("shadow-open") ? "open" : "closed", c = this.getAttribute("version"),
|
|
14
|
+
var i;
|
|
15
|
+
const n = this.getAttribute("path"), s = this.hasAttribute("shadow-open") ? "open" : "closed", c = this.getAttribute("version"), h = (i = this.getAttribute("env")) == null ? void 0 : i.toLowerCase().startsWith("d");
|
|
16
16
|
if (!n)
|
|
17
17
|
throw new Error(
|
|
18
18
|
"path attribute not specified in <custom-code-component>"
|
|
19
19
|
);
|
|
20
|
-
const [
|
|
20
|
+
const [e, a, r] = n.split("/").reverse();
|
|
21
|
+
if (!e || !a || !r)
|
|
22
|
+
return;
|
|
23
|
+
const d = h ? `http://localhost:5173/src/${e}/index.jsx` : `https://www.ft.com/__component/${r}/${a}${c ? `@${c}` : "@latest"}/${e}/${e}.js`;
|
|
21
24
|
try {
|
|
22
|
-
const
|
|
25
|
+
const o = await import(
|
|
23
26
|
/* webpackIgnore: true */
|
|
24
27
|
d
|
|
25
28
|
/* @vite-ignore */
|
|
26
|
-
),
|
|
29
|
+
), m = JSON.parse(this.getAttribute("data-component-props")), p = Object.fromEntries(
|
|
27
30
|
[...this.attributes].filter((t) => !this.RESERVED_ATTRS.has(t.name)).map((t) => [t.name, t.value])
|
|
28
31
|
);
|
|
29
32
|
if (this.hasAttribute("iframe")) {
|
|
30
33
|
const t = document.createElement("iframe");
|
|
31
34
|
t.addEventListener("load", () => {
|
|
32
|
-
|
|
35
|
+
o.default(
|
|
33
36
|
t.contentDocument,
|
|
34
|
-
{ ...
|
|
37
|
+
{ ...p, data: m },
|
|
35
38
|
...this.children
|
|
36
39
|
);
|
|
37
40
|
}), this.attachShadow({ mode: s }).append(t);
|
|
38
41
|
} else {
|
|
39
42
|
const t = this.attachShadow({ mode: s });
|
|
40
|
-
|
|
43
|
+
o.default(t, { ...p, data: m }, ...this.children);
|
|
41
44
|
}
|
|
42
|
-
} catch (
|
|
43
|
-
console.info(
|
|
45
|
+
} catch (o) {
|
|
46
|
+
console.info(`<custom-code-component> uncaught error from ${n}: `, o);
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/custom-code-component",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"@vitejs/plugin-react": "^4.0.4",
|
|
19
19
|
"eslint": "^8.47.0",
|
|
20
20
|
"eslint-plugin-react": "^7.33.1",
|
|
21
|
-
"prettier": "^3.0.1",
|
|
22
21
|
"react-dom16": "npm:react-dom@^16.14.0",
|
|
23
22
|
"react16": "npm:react@^16.14.0",
|
|
24
23
|
"typescript": "^5.2.2",
|
|
@@ -29,6 +28,10 @@
|
|
|
29
28
|
"react": "^18.2.0",
|
|
30
29
|
"react-dom": "^18.2.0"
|
|
31
30
|
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"src"
|
|
34
|
+
],
|
|
32
35
|
"overrides": {
|
|
33
36
|
"react-dom16": {
|
|
34
37
|
"react": "react16"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file
|
|
3
|
-
* Main component definition for
|
|
3
|
+
* Main component definition for custom-code-component
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { ContentTree } from "@financial-times/content-tree";
|
|
@@ -33,11 +33,14 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
33
33
|
.split("/")
|
|
34
34
|
.reverse();
|
|
35
35
|
|
|
36
|
+
if (!componentName || !componentRepo || !componentOrg) return;
|
|
37
|
+
|
|
36
38
|
const source = useLocalVersion
|
|
37
39
|
? `http://localhost:5173/src/${componentName}/index.jsx`
|
|
38
|
-
: `https://www.ft.com/__component/${componentOrg}/${componentRepo}
|
|
40
|
+
: `https://www.ft.com/__component/${componentOrg}/${componentRepo}${
|
|
39
41
|
componentVersionRange ? `@${componentVersionRange}` : "@latest"
|
|
40
|
-
}/${componentName}.js`;
|
|
42
|
+
}/${componentName}/${componentName}.js`;
|
|
43
|
+
|
|
41
44
|
try {
|
|
42
45
|
const App = await import(
|
|
43
46
|
/* webpackIgnore: true */ source /* @vite-ignore */
|
|
@@ -69,14 +72,16 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
69
72
|
App.default(shadowRoot, { ...extraProps, data }, ...this.children);
|
|
70
73
|
}
|
|
71
74
|
} catch (e) {
|
|
72
|
-
console.info(
|
|
75
|
+
console.info(`<custom-code-component> uncaught error from ${path}: `, e);
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|
|
80
|
+
// Register the custom element
|
|
77
81
|
export const init = () =>
|
|
78
82
|
customElements.define("custom-code-component", FTCustomCodeComponent);
|
|
79
83
|
|
|
84
|
+
// Allows module to be imported multiple times but custom element only registered once
|
|
80
85
|
if (customElements && !customElements.get("custom-code-component")) init();
|
|
81
86
|
|
|
82
87
|
export interface CustomCodeComponent extends ContentTree.Node {
|
|
@@ -84,7 +89,12 @@ export interface CustomCodeComponent extends ContentTree.Node {
|
|
|
84
89
|
path: string;
|
|
85
90
|
versionRange: string;
|
|
86
91
|
altText: string;
|
|
87
|
-
|
|
92
|
+
lastModified: string;
|
|
88
93
|
fallbackImage?: ContentTree.Image;
|
|
89
|
-
|
|
94
|
+
displayFallbackText: boolean;
|
|
95
|
+
layout: "in-line" | "mid-grid" | "full-grid" | "full-bleed";
|
|
96
|
+
/* prettier-ignore */
|
|
97
|
+
attributes: {
|
|
98
|
+
[key: string]: string | boolean | undefined;
|
|
99
|
+
} | { children?: CustomCodeComponent | Array<CustomCodeComponent> };
|
|
90
100
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
|
|
3
|
+
<xs:schema
|
|
4
|
+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
5
|
+
xmlns:sch="http://purl.oclc.org/dsdl/schematron"
|
|
6
|
+
>
|
|
7
|
+
<xs:complexType name="CustomCodeComponent">
|
|
8
|
+
<xs:sequence minOccurs="0">
|
|
9
|
+
<xs:element
|
|
10
|
+
name="custom-code-component"
|
|
11
|
+
type="CustomCodeComponent"
|
|
12
|
+
maxOccurs="unbounded"
|
|
13
|
+
/>
|
|
14
|
+
</xs:sequence>
|
|
15
|
+
<xs:attribute
|
|
16
|
+
name="path"
|
|
17
|
+
type="xs:anyURI"
|
|
18
|
+
use="required"
|
|
19
|
+
/>
|
|
20
|
+
<xs:attribute
|
|
21
|
+
name="versionRange"
|
|
22
|
+
type="xs:string"
|
|
23
|
+
use="required"
|
|
24
|
+
/>
|
|
25
|
+
<xs:attribute
|
|
26
|
+
name="altText"
|
|
27
|
+
type="xs:string"
|
|
28
|
+
use="required"
|
|
29
|
+
/>
|
|
30
|
+
<xs:attribute
|
|
31
|
+
name="lastModifiedTimestamp"
|
|
32
|
+
type="xs:string"
|
|
33
|
+
use="required"
|
|
34
|
+
/>
|
|
35
|
+
<xs:attribute
|
|
36
|
+
name="fallbackImageURL"
|
|
37
|
+
type="xs:string"
|
|
38
|
+
/>
|
|
39
|
+
<xs:attribute
|
|
40
|
+
name="displayFallbackText"
|
|
41
|
+
type="xs:boolean"
|
|
42
|
+
default="false"
|
|
43
|
+
/>
|
|
44
|
+
<xs:attribute
|
|
45
|
+
name="layout"
|
|
46
|
+
default="in-line"
|
|
47
|
+
>
|
|
48
|
+
<xs:simpleType>
|
|
49
|
+
<xs:restriction base="xs:string">
|
|
50
|
+
<xs:enumeration value="in-line" />
|
|
51
|
+
<xs:enumeration value="mid-grid" />
|
|
52
|
+
<xs:enumeration value="full-grid" />
|
|
53
|
+
<xs:enumeration value="full-bleed" />
|
|
54
|
+
</xs:restriction>
|
|
55
|
+
</xs:simpleType>
|
|
56
|
+
</xs:attribute>
|
|
57
|
+
<xs:attribute
|
|
58
|
+
name="attributes"
|
|
59
|
+
type="xs:string"
|
|
60
|
+
default="{}"
|
|
61
|
+
/>
|
|
62
|
+
</xs:complexType>
|
|
63
|
+
<xs:element
|
|
64
|
+
name="custom-code-component"
|
|
65
|
+
type="CustomCodeComponent"
|
|
66
|
+
/>
|
|
67
|
+
</xs:schema>
|
package/.circleci/config.yml
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
version: 2.1
|
|
2
|
-
|
|
3
|
-
orbs:
|
|
4
|
-
node: circleci/node@5.1.0
|
|
5
|
-
doppler-circleci: ft-circleci-orbs/doppler-circleci@1.3
|
|
6
|
-
|
|
7
|
-
references:
|
|
8
|
-
default_container_config: &default_container_config
|
|
9
|
-
executor:
|
|
10
|
-
name: node/default
|
|
11
|
-
tag: 'lts'
|
|
12
|
-
|
|
13
|
-
only_version_tags: &only_version_tags
|
|
14
|
-
tags:
|
|
15
|
-
only: /^v.*/
|
|
16
|
-
branches:
|
|
17
|
-
ignore: /.*/
|
|
18
|
-
|
|
19
|
-
jobs:
|
|
20
|
-
build:
|
|
21
|
-
<<: *default_container_config
|
|
22
|
-
steps:
|
|
23
|
-
- checkout
|
|
24
|
-
- doppler-circleci/install
|
|
25
|
-
- doppler-circleci/load_secrets:
|
|
26
|
-
doppler_token: DOPPLER_TOKEN_VS_COMPONENTS
|
|
27
|
-
- run:
|
|
28
|
-
name: Install dependencies
|
|
29
|
-
command: npm install
|
|
30
|
-
- run:
|
|
31
|
-
name: Publish package
|
|
32
|
-
command: |
|
|
33
|
-
npm set @Financial-Times:registry=https://npm.pkg.github.com/
|
|
34
|
-
npm set //npm.pkg.github.com/:_authToken=${GPR_WRITE_AUTH_TOKEN}
|
|
35
|
-
npm publish
|
|
36
|
-
|
|
37
|
-
workflows:
|
|
38
|
-
build-and-release:
|
|
39
|
-
jobs:
|
|
40
|
-
- build:
|
|
41
|
-
context:
|
|
42
|
-
- djd-starter-kit-s3-deployment # context is named the same in both orgs
|
|
43
|
-
filters:
|
|
44
|
-
<<: *only_version_tags
|
package/.eslintignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dist
|
package/.eslintrc.cjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
env: {
|
|
3
|
-
browser: true,
|
|
4
|
-
es2021: true,
|
|
5
|
-
},
|
|
6
|
-
extends: ["eslint:recommended", "plugin:react/recommended"],
|
|
7
|
-
overrides: [
|
|
8
|
-
{
|
|
9
|
-
env: {
|
|
10
|
-
node: true,
|
|
11
|
-
},
|
|
12
|
-
files: [".eslintrc.{js,cjs}"],
|
|
13
|
-
parserOptions: {
|
|
14
|
-
sourceType: "script",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
parserOptions: {
|
|
19
|
-
ecmaVersion: "latest",
|
|
20
|
-
sourceType: "module",
|
|
21
|
-
},
|
|
22
|
-
rules: {},
|
|
23
|
-
};
|
package/.github/CODEOWNERS
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
* @Financial-Times/visual-data-journalism-admins
|
package/index.html
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>custom-code-component loader</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<custom-code-component
|
|
10
|
-
src="../test/test16.jsx"
|
|
11
|
-
data='{"jsonWorks": true}'
|
|
12
|
-
extra="test 1"
|
|
13
|
-
></custom-code-component>
|
|
14
|
-
<custom-code-component
|
|
15
|
-
src="../test/test18.jsx"
|
|
16
|
-
data="./test.json"
|
|
17
|
-
extra="test 2"
|
|
18
|
-
></custom-code-component>
|
|
19
|
-
|
|
20
|
-
<script type="module" src="./src/custom-code-component.js"></script>
|
|
21
|
-
</body>
|
|
22
|
-
</html>
|
package/test/styles.css
DELETED
package/test/test16.jsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from "react16";
|
|
2
|
-
import ReactDOM from "react-dom16";
|
|
3
|
-
import css from "./styles.css?inline";
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line react/prop-types
|
|
6
|
-
const App = ({ children, ...props }) => (
|
|
7
|
-
<div>
|
|
8
|
-
<h1>React 16 component</h1>
|
|
9
|
-
{JSON.stringify(props)}
|
|
10
|
-
{children}
|
|
11
|
-
</div>
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
export default async (shadowRoot, props, ...children) => {
|
|
15
|
-
const style = document.createElement("style");
|
|
16
|
-
const mountPoint = document.createElement("div");
|
|
17
|
-
|
|
18
|
-
style.innerHTML = css;
|
|
19
|
-
mountPoint.id = "component-root";
|
|
20
|
-
|
|
21
|
-
shadowRoot.appendChild(style);
|
|
22
|
-
shadowRoot.appendChild(mountPoint);
|
|
23
|
-
|
|
24
|
-
// eslint-disable-next-line react/no-deprecated
|
|
25
|
-
ReactDOM.render(
|
|
26
|
-
<React.StrictMode>
|
|
27
|
-
<App {...props}>{children}</App>
|
|
28
|
-
</React.StrictMode>,
|
|
29
|
-
mountPoint
|
|
30
|
-
);
|
|
31
|
-
};
|
package/test/test18.jsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ReactDOM from "react-dom/client";
|
|
3
|
-
import css from "./styles.css?inline";
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line react/prop-types
|
|
6
|
-
const App = ({ children, ...props }) => (
|
|
7
|
-
<>
|
|
8
|
-
<h1>React 18 component</h1>
|
|
9
|
-
{JSON.stringify(props)}
|
|
10
|
-
{children}
|
|
11
|
-
</>
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
export default (shadowRoot, props, ...children) => {
|
|
15
|
-
const style = document.createElement("style");
|
|
16
|
-
const mountPoint = document.createElement("div");
|
|
17
|
-
|
|
18
|
-
style.innerHTML = css;
|
|
19
|
-
mountPoint.id = "component-root";
|
|
20
|
-
|
|
21
|
-
shadowRoot.appendChild(style);
|
|
22
|
-
shadowRoot.appendChild(mountPoint);
|
|
23
|
-
|
|
24
|
-
ReactDOM.createRoot(mountPoint).render(
|
|
25
|
-
<React.StrictMode>
|
|
26
|
-
<App {...props}>{children}</App>
|
|
27
|
-
</React.StrictMode>
|
|
28
|
-
);
|
|
29
|
-
};
|
package/test.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "hasJSON": true }
|
package/vite.config.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Vite.config.js
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import react from "@vitejs/plugin-react";
|
|
4
|
-
import { basename } from "path";
|
|
5
|
-
import dts from "vite-plugin-dts";
|
|
6
|
-
|
|
7
|
-
export default defineConfig({
|
|
8
|
-
build: {
|
|
9
|
-
lib: {
|
|
10
|
-
// Could also be a dictionary or array of multiple entry points
|
|
11
|
-
entry: "./src/custom-code-component.ts",
|
|
12
|
-
formats: ["es"],
|
|
13
|
-
fileName: (format, entry) => `${basename(entry)}.js`,
|
|
14
|
-
name: "CustomCodeComponent",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
plugins: [react(), dts()],
|
|
18
|
-
});
|