@antv/infographic 0.1.3 → 0.2.0
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/README.md +54 -40
- package/README.zh-CN.md +52 -36
- package/dist/infographic.min.js +110 -105
- package/dist/infographic.min.js.map +1 -1
- package/esm/constants/element.d.ts +1 -1
- package/esm/constants/index.d.ts +1 -0
- package/esm/constants/index.js +1 -0
- package/esm/constants/service.d.ts +1 -0
- package/esm/constants/service.js +1 -0
- package/esm/designs/components/Illus.js +1 -1
- package/esm/designs/structures/chart-wordcloud.d.ts +11 -0
- package/esm/designs/structures/chart-wordcloud.js +156 -0
- package/esm/designs/structures/hierarchy-tree.d.ts +2 -0
- package/esm/designs/structures/hierarchy-tree.js +179 -50
- package/esm/designs/structures/index.d.ts +2 -0
- package/esm/designs/structures/index.js +2 -0
- package/esm/designs/structures/sequence-stairs-front.d.ts +8 -0
- package/esm/designs/structures/sequence-stairs-front.js +116 -0
- package/esm/designs/types.d.ts +8 -0
- package/esm/editor/managers/state.js +1 -1
- package/esm/exporter/font.js +4 -9
- package/esm/index.d.ts +2 -0
- package/esm/index.js +1 -0
- package/esm/options/parser.d.ts +1 -1
- package/esm/options/parser.js +33 -15
- package/esm/renderer/composites/icon.js +1 -1
- package/esm/renderer/composites/illus.js +1 -1
- package/esm/resource/loader.d.ts +2 -2
- package/esm/resource/loader.js +22 -11
- package/esm/resource/loaders/index.d.ts +1 -0
- package/esm/resource/loaders/index.js +1 -0
- package/esm/resource/loaders/remote.d.ts +1 -1
- package/esm/resource/loaders/remote.js +12 -3
- package/esm/resource/loaders/search.d.ts +1 -0
- package/esm/resource/loaders/search.js +52 -0
- package/esm/resource/types/index.d.ts +1 -0
- package/esm/resource/types/resource.d.ts +8 -1
- package/esm/resource/types/scene.d.ts +1 -0
- package/esm/resource/utils/data-uri.js +20 -11
- package/esm/resource/utils/parser.js +92 -1
- package/esm/resource/utils/ref.js +2 -2
- package/esm/runtime/Infographic.d.ts +10 -6
- package/esm/runtime/Infographic.js +66 -17
- package/esm/runtime/utils.d.ts +4 -2
- package/esm/runtime/utils.js +33 -13
- package/esm/syntax/index.d.ts +3 -0
- package/esm/syntax/index.js +101 -0
- package/esm/syntax/mapper.d.ts +3 -0
- package/esm/syntax/mapper.js +334 -0
- package/esm/syntax/parser.d.ts +14 -0
- package/esm/syntax/parser.js +142 -0
- package/esm/syntax/schema.d.ts +6 -0
- package/esm/syntax/schema.js +86 -0
- package/esm/syntax/types.d.ts +68 -0
- package/esm/syntax/types.js +1 -0
- package/esm/templates/built-in.js +4 -0
- package/esm/templates/hierarchy-tree.js +25 -11
- package/esm/templates/sequence-stairs.d.ts +2 -0
- package/esm/templates/sequence-stairs.js +42 -0
- package/esm/templates/word-cloud.d.ts +2 -0
- package/esm/templates/word-cloud.js +19 -0
- package/esm/themes/types.d.ts +1 -1
- package/esm/utils/design.d.ts +2 -0
- package/esm/utils/design.js +10 -0
- package/esm/utils/fetch.d.ts +1 -0
- package/esm/utils/fetch.js +61 -0
- package/esm/utils/font.js +11 -1
- package/esm/utils/index.d.ts +2 -0
- package/esm/utils/index.js +2 -0
- package/lib/constants/element.d.ts +1 -1
- package/lib/constants/index.d.ts +1 -0
- package/lib/constants/index.js +1 -0
- package/lib/constants/service.d.ts +1 -0
- package/lib/constants/service.js +4 -0
- package/lib/designs/components/Illus.js +1 -1
- package/lib/designs/structures/chart-wordcloud.d.ts +11 -0
- package/lib/designs/structures/chart-wordcloud.js +160 -0
- package/lib/designs/structures/hierarchy-tree.d.ts +2 -0
- package/lib/designs/structures/hierarchy-tree.js +179 -50
- package/lib/designs/structures/index.d.ts +2 -0
- package/lib/designs/structures/index.js +2 -0
- package/lib/designs/structures/sequence-stairs-front.d.ts +8 -0
- package/lib/designs/structures/sequence-stairs-front.js +120 -0
- package/lib/designs/types.d.ts +8 -0
- package/lib/editor/managers/state.js +1 -1
- package/lib/exporter/font.js +3 -8
- package/lib/index.d.ts +2 -0
- package/lib/index.js +4 -1
- package/lib/options/parser.d.ts +1 -1
- package/lib/options/parser.js +32 -14
- package/lib/renderer/composites/icon.js +1 -1
- package/lib/renderer/composites/illus.js +1 -1
- package/lib/resource/loader.d.ts +2 -2
- package/lib/resource/loader.js +21 -10
- package/lib/resource/loaders/index.d.ts +1 -0
- package/lib/resource/loaders/index.js +1 -0
- package/lib/resource/loaders/remote.d.ts +1 -1
- package/lib/resource/loaders/remote.js +12 -3
- package/lib/resource/loaders/search.d.ts +1 -0
- package/lib/resource/loaders/search.js +55 -0
- package/lib/resource/types/index.d.ts +1 -0
- package/lib/resource/types/resource.d.ts +8 -1
- package/lib/resource/types/scene.d.ts +1 -0
- package/lib/resource/utils/data-uri.js +20 -11
- package/lib/resource/utils/parser.js +92 -1
- package/lib/resource/utils/ref.js +2 -2
- package/lib/runtime/Infographic.d.ts +10 -6
- package/lib/runtime/Infographic.js +65 -16
- package/lib/runtime/utils.d.ts +4 -2
- package/lib/runtime/utils.js +35 -13
- package/lib/syntax/index.d.ts +3 -0
- package/lib/syntax/index.js +104 -0
- package/lib/syntax/mapper.d.ts +3 -0
- package/lib/syntax/mapper.js +341 -0
- package/lib/syntax/parser.d.ts +14 -0
- package/lib/syntax/parser.js +146 -0
- package/lib/syntax/schema.d.ts +6 -0
- package/lib/syntax/schema.js +89 -0
- package/lib/syntax/types.d.ts +68 -0
- package/lib/syntax/types.js +2 -0
- package/lib/templates/built-in.js +4 -0
- package/lib/templates/hierarchy-tree.js +25 -11
- package/lib/templates/sequence-stairs.d.ts +2 -0
- package/lib/templates/sequence-stairs.js +45 -0
- package/lib/templates/word-cloud.d.ts +2 -0
- package/lib/templates/word-cloud.js +22 -0
- package/lib/themes/types.d.ts +1 -1
- package/lib/utils/design.d.ts +2 -0
- package/lib/utils/design.js +13 -0
- package/lib/utils/fetch.d.ts +1 -0
- package/lib/utils/fetch.js +67 -0
- package/lib/utils/font.js +11 -1
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +2 -0
- package/package.json +14 -2
- package/src/constants/element.ts +1 -1
- package/src/constants/index.ts +1 -0
- package/src/constants/service.ts +1 -0
- package/src/designs/components/Illus.tsx +1 -1
- package/src/designs/structures/chart-wordcloud.tsx +278 -0
- package/src/designs/structures/hierarchy-tree.tsx +212 -59
- package/src/designs/structures/index.ts +2 -0
- package/src/designs/structures/sequence-stairs-front.tsx +291 -0
- package/src/designs/types.ts +9 -0
- package/src/editor/managers/state.ts +1 -1
- package/src/exporter/font.ts +4 -9
- package/src/index.ts +2 -0
- package/src/options/parser.ts +57 -28
- package/src/renderer/composites/icon.ts +1 -1
- package/src/renderer/composites/illus.ts +1 -1
- package/src/resource/loader.ts +22 -8
- package/src/resource/loaders/index.ts +1 -0
- package/src/resource/loaders/remote.ts +11 -3
- package/src/resource/loaders/search.ts +53 -0
- package/src/resource/types/index.ts +2 -1
- package/src/resource/types/resource.ts +12 -1
- package/src/resource/types/scene.ts +1 -0
- package/src/resource/utils/data-uri.ts +20 -11
- package/src/resource/utils/parser.ts +103 -2
- package/src/resource/utils/ref.ts +2 -2
- package/src/runtime/Infographic.tsx +103 -22
- package/src/runtime/utils.ts +38 -16
- package/src/syntax/index.ts +124 -0
- package/src/syntax/mapper.ts +496 -0
- package/src/syntax/parser.ts +171 -0
- package/src/syntax/schema.ts +112 -0
- package/src/syntax/types.ts +100 -0
- package/src/templates/built-in.ts +4 -0
- package/src/templates/hierarchy-tree.ts +34 -11
- package/src/templates/sequence-stairs.ts +44 -0
- package/src/templates/word-cloud.ts +21 -0
- package/src/themes/types.ts +1 -1
- package/src/utils/design.ts +14 -0
- package/src/utils/fetch.ts +90 -0
- package/src/utils/font.ts +11 -1
- package/src/utils/index.ts +2 -0
- package/esm/resource/types/font.d.ts +0 -12
- package/lib/resource/types/font.d.ts +0 -12
- package/src/resource/types/font.ts +0 -23
- /package/esm/resource/types/{font.js → scene.js} +0 -0
- /package/lib/resource/types/{font.js → scene.js} +0 -0
package/lib/options/parser.js
CHANGED
|
@@ -12,19 +12,37 @@ function parseOptions(options) {
|
|
|
12
12
|
? document.querySelector(container) || document.createElement('div')
|
|
13
13
|
: container;
|
|
14
14
|
const templateOptions = template
|
|
15
|
-
? (0, designs_1.getTemplate)(template)
|
|
16
|
-
:
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
? (0, designs_1.getTemplate)(template)
|
|
16
|
+
: undefined;
|
|
17
|
+
const mergedThemeConfig = (0, lodash_es_1.merge)({}, templateOptions?.themeConfig, themeConfig);
|
|
18
|
+
const resolvedThemeConfig = theme || themeConfig || templateOptions?.themeConfig
|
|
19
|
+
? parseTheme(theme, mergedThemeConfig)
|
|
20
|
+
: undefined;
|
|
21
|
+
const parsed = {
|
|
21
22
|
container: parsedContainer,
|
|
22
23
|
padding: (0, utils_1.parsePadding)(padding),
|
|
23
|
-
template,
|
|
24
|
-
design: parseDesign({ ...templateDesign, ...design }, options),
|
|
25
|
-
theme,
|
|
26
|
-
themeConfig: parseTheme(theme, (0, lodash_es_1.merge)({ ...restTemplateOptions?.themeConfig }, themeConfig)),
|
|
27
24
|
};
|
|
25
|
+
if (templateOptions) {
|
|
26
|
+
const { design: templateDesign, ...restTemplateOptions } = templateOptions;
|
|
27
|
+
Object.assign(parsed, restTemplateOptions);
|
|
28
|
+
}
|
|
29
|
+
Object.assign(parsed, restOptions);
|
|
30
|
+
if (template)
|
|
31
|
+
parsed.template = template;
|
|
32
|
+
if (templateOptions?.design || design) {
|
|
33
|
+
const parsedDesign = parseDesign({ ...templateOptions?.design, ...design }, resolvedThemeConfig
|
|
34
|
+
? { ...options, themeConfig: resolvedThemeConfig }
|
|
35
|
+
: options);
|
|
36
|
+
if ((0, utils_1.isNonNullableParsedDesignsOptions)(parsedDesign)) {
|
|
37
|
+
parsed.design = parsedDesign;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (theme)
|
|
41
|
+
parsed.theme = theme;
|
|
42
|
+
if (resolvedThemeConfig) {
|
|
43
|
+
parsed.themeConfig = resolvedThemeConfig;
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
28
46
|
}
|
|
29
47
|
function normalizeWithType(obj) {
|
|
30
48
|
if (typeof obj === 'string')
|
|
@@ -47,11 +65,11 @@ function parseDesign(config, options) {
|
|
|
47
65
|
}
|
|
48
66
|
function parseDesignStructure(config) {
|
|
49
67
|
if (!config)
|
|
50
|
-
|
|
68
|
+
return null;
|
|
51
69
|
const { type, ...userProps } = normalizeWithType(config);
|
|
52
70
|
const structure = (0, designs_1.getStructure)(type);
|
|
53
71
|
if (!structure)
|
|
54
|
-
|
|
72
|
+
return null;
|
|
55
73
|
const { component } = structure;
|
|
56
74
|
return {
|
|
57
75
|
...structure,
|
|
@@ -72,11 +90,11 @@ function parseDesignTitle(config, options) {
|
|
|
72
90
|
}
|
|
73
91
|
function parseDesignItem(config, options) {
|
|
74
92
|
if (!config)
|
|
75
|
-
|
|
93
|
+
return null;
|
|
76
94
|
const { type, ...userProps } = normalizeWithType(config);
|
|
77
95
|
const item = (0, designs_1.getItem)(type);
|
|
78
96
|
if (!item)
|
|
79
|
-
|
|
97
|
+
return null;
|
|
80
98
|
const { component, options: itemOptions } = item;
|
|
81
99
|
return {
|
|
82
100
|
...item,
|
|
@@ -23,7 +23,7 @@ function renderItemIcon(svg, node, value, options) {
|
|
|
23
23
|
}
|
|
24
24
|
function createIcon(svg, node, value, attrs) {
|
|
25
25
|
// load async
|
|
26
|
-
(0, resource_1.loadResource)(svg, value);
|
|
26
|
+
(0, resource_1.loadResource)(svg, 'icon', value);
|
|
27
27
|
return (0, utils_1.createIconElement)(value, {
|
|
28
28
|
...(0, utils_1.getAttributes)(node, [
|
|
29
29
|
'id',
|
|
@@ -11,7 +11,7 @@ function renderIllus(svg, node, value) {
|
|
|
11
11
|
return null;
|
|
12
12
|
const id = (0, resource_1.getResourceId)(config);
|
|
13
13
|
const clipPathId = createClipPath(svg, node, id);
|
|
14
|
-
(0, resource_1.loadResource)(svg, config);
|
|
14
|
+
(0, resource_1.loadResource)(svg, 'illus', config);
|
|
15
15
|
const { data, color } = config;
|
|
16
16
|
return createIllusElement(id, {
|
|
17
17
|
...parseIllusBounds(node),
|
package/lib/resource/loader.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ResourceConfig } from './types';
|
|
1
|
+
import type { ResourceConfig, ResourceScene } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* load resource into svg defs
|
|
4
4
|
* @returns resource ref id
|
|
5
5
|
*/
|
|
6
|
-
export declare function loadResource(svg: SVGSVGElement | null, config: string | ResourceConfig): Promise<string | null>;
|
|
6
|
+
export declare function loadResource(svg: SVGSVGElement | null, scene: ResourceScene, config: string | ResourceConfig): Promise<string | null>;
|
package/lib/resource/loader.js
CHANGED
|
@@ -5,19 +5,30 @@ const utils_1 = require("../utils");
|
|
|
5
5
|
const loaders_1 = require("./loaders");
|
|
6
6
|
const registry_1 = require("./registry");
|
|
7
7
|
const utils_2 = require("./utils");
|
|
8
|
-
async function getResource(config) {
|
|
8
|
+
async function getResource(scene, config) {
|
|
9
9
|
const cfg = (0, utils_2.parseResourceConfig)(config);
|
|
10
10
|
if (!cfg)
|
|
11
11
|
return null;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
cfg.scene || (cfg.scene = scene);
|
|
13
|
+
const { source, data, format, encoding } = cfg;
|
|
14
|
+
if (source === 'inline') {
|
|
15
|
+
const isDataURI = data.startsWith('data:');
|
|
16
|
+
if (format === 'svg' && encoding === 'raw') {
|
|
17
|
+
return (0, loaders_1.loadSVGResource)(data);
|
|
18
|
+
}
|
|
19
|
+
if (format === 'svg' && isDataURI) {
|
|
20
|
+
return await (0, loaders_1.loadImageBase64Resource)(data);
|
|
21
|
+
}
|
|
22
|
+
if (isDataURI || format === 'image') {
|
|
23
|
+
return await (0, loaders_1.loadImageBase64Resource)(data);
|
|
24
|
+
}
|
|
17
25
|
return (0, loaders_1.loadSVGResource)(data);
|
|
18
26
|
}
|
|
19
|
-
else if (
|
|
20
|
-
return await (0, loaders_1.loadRemoteResource)(data);
|
|
27
|
+
else if (source === 'remote') {
|
|
28
|
+
return await (0, loaders_1.loadRemoteResource)(data, format);
|
|
29
|
+
}
|
|
30
|
+
else if (source === 'search') {
|
|
31
|
+
return await (0, loaders_1.loadSearchResource)(data, format);
|
|
21
32
|
}
|
|
22
33
|
else {
|
|
23
34
|
const customLoader = (0, registry_1.getCustomResourceLoader)();
|
|
@@ -32,7 +43,7 @@ const RESOURCE_LOAD_MAP = new WeakMap();
|
|
|
32
43
|
* load resource into svg defs
|
|
33
44
|
* @returns resource ref id
|
|
34
45
|
*/
|
|
35
|
-
async function loadResource(svg, config) {
|
|
46
|
+
async function loadResource(svg, scene, config) {
|
|
36
47
|
if (!svg)
|
|
37
48
|
return null;
|
|
38
49
|
const cfg = (0, utils_2.parseResourceConfig)(config);
|
|
@@ -41,7 +52,7 @@ async function loadResource(svg, config) {
|
|
|
41
52
|
const id = (0, utils_2.getResourceId)(cfg);
|
|
42
53
|
const resource = RESOURCE_MAP.has(id)
|
|
43
54
|
? RESOURCE_MAP.get(id) || null
|
|
44
|
-
: await getResource(cfg);
|
|
55
|
+
: await getResource(scene, cfg);
|
|
45
56
|
if (!resource)
|
|
46
57
|
return null;
|
|
47
58
|
if (!RESOURCE_LOAD_MAP.has(svg))
|
|
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./image"), exports);
|
|
18
18
|
__exportStar(require("./remote"), exports);
|
|
19
|
+
__exportStar(require("./search"), exports);
|
|
19
20
|
__exportStar(require("./svg"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function loadRemoteResource(resource: string): Promise<SVGSymbolElement | null>;
|
|
1
|
+
export declare function loadRemoteResource(resource: string, format?: string): Promise<SVGSymbolElement | null>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.loadRemoteResource = loadRemoteResource;
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
4
5
|
const image_1 = require("./image");
|
|
5
6
|
const svg_1 = require("./svg");
|
|
6
7
|
function isRemoteResource(resource) {
|
|
@@ -11,14 +12,22 @@ function isRemoteResource(resource) {
|
|
|
11
12
|
return false;
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
function shouldParseAsSVG(contentType, format) {
|
|
16
|
+
const normalized = contentType.toLowerCase();
|
|
17
|
+
if (normalized.includes('image/svg'))
|
|
18
|
+
return true;
|
|
19
|
+
if (!contentType && format === 'svg')
|
|
20
|
+
return true;
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
async function loadRemoteResource(resource, format) {
|
|
15
24
|
if (!resource || !isRemoteResource(resource))
|
|
16
25
|
return null;
|
|
17
|
-
const response = await
|
|
26
|
+
const response = await (0, utils_1.fetchWithCache)(resource);
|
|
18
27
|
if (!response.ok)
|
|
19
28
|
throw new Error('Failed to load resource');
|
|
20
29
|
const contentType = response.headers.get('Content-Type') || '';
|
|
21
|
-
if (contentType
|
|
30
|
+
if (shouldParseAsSVG(contentType, format)) {
|
|
22
31
|
const svgText = await response.text();
|
|
23
32
|
return (0, svg_1.loadSVGResource)(svgText);
|
|
24
33
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loadSearchResource(query: string, format?: string): Promise<SVGSymbolElement | null>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadSearchResource = loadSearchResource;
|
|
4
|
+
const constants_1 = require("../../constants");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
const image_1 = require("./image");
|
|
7
|
+
const remote_1 = require("./remote");
|
|
8
|
+
const svg_1 = require("./svg");
|
|
9
|
+
const queryIcon = async (query) => {
|
|
10
|
+
try {
|
|
11
|
+
const params = new URLSearchParams({ text: query, topK: '1' });
|
|
12
|
+
const url = `${constants_1.ICON_SERVICE_URL}?${params.toString()}`;
|
|
13
|
+
const response = await (0, utils_1.fetchWithCache)(url);
|
|
14
|
+
if (!response.ok)
|
|
15
|
+
return null;
|
|
16
|
+
const result = await response.json();
|
|
17
|
+
if (!result?.status || !Array.isArray(result.data?.data))
|
|
18
|
+
return null;
|
|
19
|
+
return result.data.data[0] || null;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(`Failed to query icon for "${query}":`, error);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function isDataURI(resource) {
|
|
27
|
+
return resource.startsWith('data:');
|
|
28
|
+
}
|
|
29
|
+
function looksLikeSVG(resource) {
|
|
30
|
+
const str = resource.trim();
|
|
31
|
+
return str.startsWith('<svg') || str.startsWith('<symbol');
|
|
32
|
+
}
|
|
33
|
+
async function loadSearchResource(query, format) {
|
|
34
|
+
if (!query)
|
|
35
|
+
return null;
|
|
36
|
+
const result = await queryIcon(query);
|
|
37
|
+
if (!result)
|
|
38
|
+
return null;
|
|
39
|
+
if (looksLikeSVG(result))
|
|
40
|
+
return (0, svg_1.loadSVGResource)(result);
|
|
41
|
+
if (isDataURI(result)) {
|
|
42
|
+
const mimeType = result.match(/^data:([^;]+)/)?.[1] || '';
|
|
43
|
+
const isBase64 = result.includes(';base64,');
|
|
44
|
+
if (mimeType === 'image/svg+xml' && !isBase64) {
|
|
45
|
+
const commaIndex = result.indexOf(',');
|
|
46
|
+
const svgText = commaIndex >= 0 ? result.slice(commaIndex + 1) : result;
|
|
47
|
+
return (0, svg_1.loadSVGResource)(svgText);
|
|
48
|
+
}
|
|
49
|
+
if (mimeType === 'image/svg+xml' && format === 'svg' && isBase64) {
|
|
50
|
+
return (0, image_1.loadImageBase64Resource)(result);
|
|
51
|
+
}
|
|
52
|
+
return (0, image_1.loadImageBase64Resource)(result);
|
|
53
|
+
}
|
|
54
|
+
return (0, remote_1.loadRemoteResource)(result, format);
|
|
55
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { ResourceScene } from './scene';
|
|
2
|
+
export type ResourceSource = 'inline' | 'remote' | 'search' | 'custom';
|
|
3
|
+
export type ResourceFormat = 'svg' | 'image' | 'json' | 'binary' | string;
|
|
4
|
+
export type ResourceEncoding = 'raw' | 'data-uri' | 'base64' | string;
|
|
1
5
|
export interface ResourceConfig {
|
|
2
|
-
|
|
6
|
+
source: ResourceSource;
|
|
7
|
+
format?: ResourceFormat;
|
|
8
|
+
encoding?: ResourceEncoding;
|
|
3
9
|
data: string;
|
|
10
|
+
scene?: ResourceScene;
|
|
4
11
|
[key: string]: any;
|
|
5
12
|
}
|
|
6
13
|
export type Resource = SVGSymbolElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ResourceScene = 'icon' | 'illus';
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseDataURI = parseDataURI;
|
|
4
4
|
function parseDataURI(resource) {
|
|
5
5
|
if (!resource.startsWith('data:'))
|
|
6
|
-
return
|
|
6
|
+
return null;
|
|
7
7
|
const commaIndex = resource.indexOf(',');
|
|
8
8
|
if (commaIndex === -1)
|
|
9
9
|
return null;
|
|
@@ -11,15 +11,24 @@ function parseDataURI(resource) {
|
|
|
11
11
|
const data = resource.slice(commaIndex + 1);
|
|
12
12
|
const parts = header.split(';');
|
|
13
13
|
const mimeType = parts[0];
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const isBase64 = parts.includes('base64');
|
|
15
|
+
if (mimeType === 'image/svg+xml' && !isBase64) {
|
|
16
|
+
const decoded = data.startsWith('%3C') ? decodeURIComponent(data) : data;
|
|
17
|
+
return {
|
|
18
|
+
source: 'inline',
|
|
19
|
+
format: 'svg',
|
|
20
|
+
encoding: 'raw',
|
|
21
|
+
data: decoded,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (mimeType.startsWith('image/')) {
|
|
25
|
+
const format = mimeType === 'image/svg+xml' ? 'svg' : 'image';
|
|
26
|
+
return {
|
|
27
|
+
source: 'inline',
|
|
28
|
+
format,
|
|
29
|
+
encoding: isBase64 ? 'base64' : 'data-uri',
|
|
30
|
+
data: resource,
|
|
31
|
+
};
|
|
16
32
|
}
|
|
17
|
-
|
|
18
|
-
'text/url': "remote" /* DataURITypeEnum.Remote */,
|
|
19
|
-
'image/svg+xml': "svg" /* DataURITypeEnum.SVG */,
|
|
20
|
-
};
|
|
21
|
-
const type = typeMap[mimeType];
|
|
22
|
-
if (type)
|
|
23
|
-
return { type, data };
|
|
24
|
-
return { type: 'custom', data: resource };
|
|
33
|
+
return null;
|
|
25
34
|
}
|
|
@@ -2,8 +2,99 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseResourceConfig = parseResourceConfig;
|
|
4
4
|
const data_uri_1 = require("./data-uri");
|
|
5
|
+
const KNOWN_FORMATS = new Set(['svg', 'png', 'jpg', 'jpeg', 'webp', 'gif']);
|
|
6
|
+
function looksLikeSVG(resource) {
|
|
7
|
+
const str = resource.trim();
|
|
8
|
+
return str.startsWith('<svg') || str.startsWith('<symbol');
|
|
9
|
+
}
|
|
10
|
+
function inferFormatFromUrl(url) {
|
|
11
|
+
const lower = url.toLowerCase();
|
|
12
|
+
if (lower.endsWith('.svg') || lower.includes('.svg?'))
|
|
13
|
+
return 'svg';
|
|
14
|
+
if (lower.endsWith('.png') ||
|
|
15
|
+
lower.endsWith('.jpg') ||
|
|
16
|
+
lower.endsWith('.jpeg') ||
|
|
17
|
+
lower.endsWith('.webp') ||
|
|
18
|
+
lower.endsWith('.gif')) {
|
|
19
|
+
return 'image';
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
function parseRefResource(resource) {
|
|
24
|
+
if (!resource.startsWith('ref:'))
|
|
25
|
+
return null;
|
|
26
|
+
const rest = resource.slice(4);
|
|
27
|
+
const [source, ...restParts] = rest.split(':');
|
|
28
|
+
if (!source || restParts.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
let format;
|
|
31
|
+
if (restParts.length > 1 && KNOWN_FORMATS.has(restParts[0].toLowerCase())) {
|
|
32
|
+
format = restParts.shift()?.toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
const payload = restParts.join(':');
|
|
35
|
+
if (!payload)
|
|
36
|
+
return null;
|
|
37
|
+
const normalizedSource = source === 'url' ? 'remote' : source;
|
|
38
|
+
if (normalizedSource === 'remote') {
|
|
39
|
+
return {
|
|
40
|
+
source: 'remote',
|
|
41
|
+
format: format || inferFormatFromUrl(payload) || undefined,
|
|
42
|
+
data: payload,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (normalizedSource === 'search') {
|
|
46
|
+
return {
|
|
47
|
+
source: 'search',
|
|
48
|
+
format: format || 'svg',
|
|
49
|
+
data: payload,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (normalizedSource === 'svg') {
|
|
53
|
+
return { source: 'inline', format: 'svg', data: payload, encoding: 'raw' };
|
|
54
|
+
}
|
|
55
|
+
return { source: 'custom', data: resource, format };
|
|
56
|
+
}
|
|
5
57
|
function parseResourceConfig(config) {
|
|
6
58
|
if (!config)
|
|
7
59
|
return null;
|
|
8
|
-
|
|
60
|
+
if (typeof config !== 'string') {
|
|
61
|
+
if (config.source)
|
|
62
|
+
return config;
|
|
63
|
+
const legacy = config;
|
|
64
|
+
if (legacy.type === 'image') {
|
|
65
|
+
return { source: 'inline', format: 'image', data: legacy.data };
|
|
66
|
+
}
|
|
67
|
+
if (legacy.type === 'svg') {
|
|
68
|
+
return {
|
|
69
|
+
source: 'inline',
|
|
70
|
+
format: 'svg',
|
|
71
|
+
encoding: 'raw',
|
|
72
|
+
data: legacy.data,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (legacy.type === 'remote') {
|
|
76
|
+
return { source: 'remote', format: legacy.format, data: legacy.data };
|
|
77
|
+
}
|
|
78
|
+
if (legacy.type === 'search') {
|
|
79
|
+
return {
|
|
80
|
+
source: 'search',
|
|
81
|
+
format: legacy.format || 'svg',
|
|
82
|
+
data: legacy.data,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (legacy.type === 'custom') {
|
|
86
|
+
return { source: 'custom', data: legacy.data };
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
const dataURIConfig = (0, data_uri_1.parseDataURI)(config);
|
|
91
|
+
if (dataURIConfig)
|
|
92
|
+
return dataURIConfig;
|
|
93
|
+
const refConfig = parseRefResource(config);
|
|
94
|
+
if (refConfig)
|
|
95
|
+
return refConfig;
|
|
96
|
+
if (looksLikeSVG(config)) {
|
|
97
|
+
return { source: 'inline', format: 'svg', encoding: 'raw', data: config };
|
|
98
|
+
}
|
|
99
|
+
return { source: 'custom', data: config };
|
|
9
100
|
}
|
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getResourceId = getResourceId;
|
|
4
4
|
exports.getResourceHref = getResourceHref;
|
|
5
5
|
const utils_1 = require("../../utils");
|
|
6
|
-
const
|
|
6
|
+
const parser_1 = require("./parser");
|
|
7
7
|
function getResourceId(config) {
|
|
8
|
-
const cfg = typeof config === 'string' ? (0,
|
|
8
|
+
const cfg = typeof config === 'string' ? (0, parser_1.parseResourceConfig)(config) : config;
|
|
9
9
|
if (!cfg)
|
|
10
10
|
return null;
|
|
11
11
|
return 'rsc-' + (0, utils_1.getSimpleHash)(JSON.stringify(cfg));
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import { type ExportOptions } from '../exporter';
|
|
2
|
-
import { InfographicOptions } from '../options';
|
|
2
|
+
import { InfographicOptions, ParsedInfographicOptions } from '../options';
|
|
3
3
|
export declare class Infographic {
|
|
4
4
|
rendered: boolean;
|
|
5
5
|
private emitter;
|
|
6
6
|
private node;
|
|
7
7
|
private editor?;
|
|
8
|
+
private initialOptions;
|
|
8
9
|
private options;
|
|
9
10
|
private parsedOptions;
|
|
10
|
-
constructor(options: InfographicOptions);
|
|
11
|
-
getOptions(): InfographicOptions
|
|
11
|
+
constructor(options: string | Partial<InfographicOptions>);
|
|
12
|
+
getOptions(): Partial<InfographicOptions>;
|
|
13
|
+
private setOptions;
|
|
12
14
|
/**
|
|
13
15
|
* Render the infographic into the container
|
|
14
16
|
*/
|
|
15
|
-
render(): void;
|
|
17
|
+
render(options?: string | Partial<InfographicOptions>): void;
|
|
18
|
+
update(options: string | Partial<InfographicOptions>): void;
|
|
19
|
+
private performRender;
|
|
16
20
|
/**
|
|
17
21
|
* Compose the SVG template
|
|
18
22
|
*/
|
|
19
|
-
compose(): SVGSVGElement;
|
|
20
|
-
getTypes(): string;
|
|
23
|
+
compose(parsedOptions: ParsedInfographicOptions): SVGSVGElement;
|
|
24
|
+
getTypes(): string | undefined;
|
|
21
25
|
/**
|
|
22
26
|
* Export the infographic to data URL
|
|
23
27
|
* @param options Export option
|
|
@@ -6,12 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Infographic = void 0;
|
|
7
7
|
const jsx_runtime_1 = require("@antv/infographic/jsx-runtime");
|
|
8
8
|
const eventemitter3_1 = __importDefault(require("eventemitter3"));
|
|
9
|
-
const lodash_es_1 = require("lodash-es");
|
|
10
9
|
const editor_1 = require("../editor");
|
|
11
10
|
const exporter_1 = require("../exporter");
|
|
12
11
|
const jsx_1 = require("../jsx");
|
|
13
12
|
const options_1 = require("../options");
|
|
14
13
|
const renderer_1 = require("../renderer");
|
|
14
|
+
const syntax_1 = require("../syntax");
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
16
|
const options_2 = require("./options");
|
|
17
17
|
const utils_2 = require("./utils");
|
|
@@ -20,27 +20,60 @@ class Infographic {
|
|
|
20
20
|
this.rendered = false;
|
|
21
21
|
this.emitter = new eventemitter3_1.default();
|
|
22
22
|
this.node = null;
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
data: (0, lodash_es_1.cloneDeep)(options.data),
|
|
26
|
-
elements: (0, lodash_es_1.cloneDeep)(options.elements || []),
|
|
27
|
-
};
|
|
28
|
-
this.parsedOptions = (0, options_1.parseOptions)((0, utils_2.mergeOptions)(options_2.DEFAULT_OPTIONS, this.options));
|
|
23
|
+
this.initialOptions = {};
|
|
24
|
+
this.setOptions(options, 'replace', true);
|
|
29
25
|
}
|
|
30
26
|
getOptions() {
|
|
31
27
|
return this.options;
|
|
32
28
|
}
|
|
29
|
+
setOptions(options, mode = 'replace', isInitial = false) {
|
|
30
|
+
const { options: parsedOptions, errors, warnings, } = parseSyntaxOptions(options);
|
|
31
|
+
if (isInitial) {
|
|
32
|
+
this.initialOptions = (0, utils_2.cloneOptions)(parsedOptions);
|
|
33
|
+
}
|
|
34
|
+
const base = mode === 'replace'
|
|
35
|
+
? (0, utils_2.mergeOptions)((0, utils_2.cloneOptions)(this.initialOptions || {}), parsedOptions)
|
|
36
|
+
: (0, utils_2.mergeOptions)(this.options || (0, utils_2.cloneOptions)(this.initialOptions || {}), parsedOptions);
|
|
37
|
+
this.options = base;
|
|
38
|
+
this.parsedOptions = (0, options_1.parseOptions)((0, utils_2.mergeOptions)(options_2.DEFAULT_OPTIONS, this.options));
|
|
39
|
+
if (warnings.length) {
|
|
40
|
+
this.emitter.emit('warning', warnings);
|
|
41
|
+
}
|
|
42
|
+
if (errors.length) {
|
|
43
|
+
this.emitter.emit('error', errors);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
33
46
|
/**
|
|
34
47
|
* Render the infographic into the container
|
|
35
48
|
*/
|
|
36
|
-
render() {
|
|
49
|
+
render(options) {
|
|
50
|
+
if (options) {
|
|
51
|
+
this.setOptions(options, 'replace');
|
|
52
|
+
}
|
|
53
|
+
else if (!this.options && this.initialOptions) {
|
|
54
|
+
this.setOptions(this.initialOptions, 'replace');
|
|
55
|
+
}
|
|
56
|
+
this.performRender();
|
|
57
|
+
}
|
|
58
|
+
update(options) {
|
|
59
|
+
this.setOptions(options, 'merge');
|
|
60
|
+
this.performRender();
|
|
61
|
+
}
|
|
62
|
+
performRender() {
|
|
63
|
+
const parsedOptions = this.parsedOptions;
|
|
64
|
+
if (!(0, utils_2.isCompleteParsedInfographicOptions)(parsedOptions)) {
|
|
65
|
+
this.emitter.emit('error', new Error('Incomplete options'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
37
68
|
const { container } = this.parsedOptions;
|
|
38
|
-
const template = this.compose();
|
|
39
|
-
const renderer = new renderer_1.Renderer(
|
|
69
|
+
const template = this.compose(parsedOptions);
|
|
70
|
+
const renderer = new renderer_1.Renderer(parsedOptions, template);
|
|
40
71
|
this.node = renderer.render();
|
|
41
|
-
container
|
|
72
|
+
container?.replaceChildren(this.node);
|
|
73
|
+
this.editor?.destroy();
|
|
74
|
+
this.editor = undefined;
|
|
42
75
|
if (this.options.editable) {
|
|
43
|
-
this.editor = new editor_1.Editor(this.emitter, this.node,
|
|
76
|
+
this.editor = new editor_1.Editor(this.emitter, this.node, parsedOptions);
|
|
44
77
|
}
|
|
45
78
|
this.rendered = true;
|
|
46
79
|
this.emitter.emit('rendered', { node: this.node, options: this.options });
|
|
@@ -48,14 +81,14 @@ class Infographic {
|
|
|
48
81
|
/**
|
|
49
82
|
* Compose the SVG template
|
|
50
83
|
*/
|
|
51
|
-
compose() {
|
|
52
|
-
const { design, data } =
|
|
84
|
+
compose(parsedOptions) {
|
|
85
|
+
const { design, data } = parsedOptions;
|
|
53
86
|
const { title, item, items, structure } = design;
|
|
54
87
|
const { component: Structure, props: structureProps } = structure;
|
|
55
88
|
const Title = title.component;
|
|
56
89
|
const Item = item.component;
|
|
57
90
|
const Items = items.map((it) => it.component);
|
|
58
|
-
const svg = (0, jsx_1.renderSVG)((0, jsx_runtime_1.jsx)(Structure, { data: data, Title: Title, Item: Item, Items: Items, options:
|
|
91
|
+
const svg = (0, jsx_1.renderSVG)((0, jsx_runtime_1.jsx)(Structure, { data: data, Title: Title, Item: Item, Items: Items, options: parsedOptions, ...structureProps }));
|
|
59
92
|
const template = (0, utils_1.parseSVG)(svg);
|
|
60
93
|
if (!template) {
|
|
61
94
|
throw new Error('Failed to parse SVG template');
|
|
@@ -63,7 +96,12 @@ class Infographic {
|
|
|
63
96
|
return template;
|
|
64
97
|
}
|
|
65
98
|
getTypes() {
|
|
66
|
-
const
|
|
99
|
+
const parsedOptions = this.parsedOptions;
|
|
100
|
+
if (!(0, utils_2.isCompleteParsedInfographicOptions)(parsedOptions)) {
|
|
101
|
+
this.emitter.emit('error', new Error('Incomplete options'));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const design = parsedOptions.design;
|
|
67
105
|
const structure = design.structure.composites || [];
|
|
68
106
|
const items = design.items.map((it) => it.composites || []);
|
|
69
107
|
return (0, utils_1.getTypes)({ structure, items });
|
|
@@ -99,3 +137,14 @@ class Infographic {
|
|
|
99
137
|
}
|
|
100
138
|
}
|
|
101
139
|
exports.Infographic = Infographic;
|
|
140
|
+
function parseSyntaxOptions(input) {
|
|
141
|
+
if (typeof input === 'string') {
|
|
142
|
+
const { options, errors, warnings } = (0, syntax_1.parseSyntax)(input);
|
|
143
|
+
return { options, errors, warnings };
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
options: (0, utils_2.cloneOptions)(input),
|
|
147
|
+
errors: [],
|
|
148
|
+
warnings: [],
|
|
149
|
+
};
|
|
150
|
+
}
|
package/lib/runtime/utils.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import { InfographicOptions } from '../options
|
|
2
|
-
export declare function mergeOptions(object: Partial<InfographicOptions>, source: Partial<InfographicOptions>): InfographicOptions
|
|
1
|
+
import type { InfographicOptions, ParsedInfographicOptions } from '../options';
|
|
2
|
+
export declare function mergeOptions(object: Partial<InfographicOptions>, source: Partial<InfographicOptions>): Partial<InfographicOptions>;
|
|
3
|
+
export declare function cloneOptions<T extends Partial<InfographicOptions>>(options: T): T;
|
|
4
|
+
export declare function isCompleteParsedInfographicOptions(options: Partial<ParsedInfographicOptions>): options is ParsedInfographicOptions;
|