@gooddata/sdk-ui-vis-commons 11.42.0-alpha.0 → 11.42.0-alpha.2
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/esm/customTooltip/markdownToHtml.d.ts +1 -0
- package/esm/customTooltip/markdownToHtml.d.ts.map +1 -1
- package/esm/customTooltip/markdownToHtml.js +13 -8
- package/esm/customTooltip/referenceResolver.d.ts.map +1 -1
- package/esm/customTooltip/referenceResolver.js +23 -7
- package/package.json +11 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdownToHtml.d.ts","sourceRoot":"","sources":["../../src/customTooltip/markdownToHtml.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"markdownToHtml.d.ts","sourceRoot":"","sources":["../../src/customTooltip/markdownToHtml.ts"],"names":[],"mappings":"AA8CA,eAAO,MAAM,WAAW,iCAAiC,CAAC;AA2F1D;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuBvD"}
|
|
@@ -37,10 +37,13 @@ function isSafeLinkUrl(url) {
|
|
|
37
37
|
return /^https?:\/\//i.test(url);
|
|
38
38
|
}
|
|
39
39
|
// URL pattern allowing one level of balanced parens, e.g.
|
|
40
|
-
// https://en.wikipedia.org/wiki/Page_(name)
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
40
|
+
// https://en.wikipedia.org/wiki/Page_(name). Shared with `referenceResolver`
|
|
41
|
+
// so blanking applies exactly where this renderer sees an image/link.
|
|
42
|
+
export const URL_PATTERN = "(?:[^()\\s]|\\([^)\\n]*\\))+";
|
|
43
|
+
// URL is optional: a data reference that resolved to no data is blanked upstream
|
|
44
|
+
// (see `referenceResolver`), leaving `![alt]()` / `[text]()` to render here.
|
|
45
|
+
const IMAGE_REGEX = new RegExp(`!\\[([^\\]]*)\\]\\((${URL_PATTERN})?\\)`, "g");
|
|
46
|
+
const LINK_REGEX = new RegExp(`\\[([^\\]]+)\\]\\((${URL_PATTERN})?\\)`, "g");
|
|
44
47
|
// Italic content must have non-whitespace at both inner boundaries. This keeps
|
|
45
48
|
// arithmetic-style text (e.g. `5 * 3 * 2`) from being misread as italics.
|
|
46
49
|
const ITALIC_ASTERISK_REGEX = /\*([^\s*][^*]*[^\s*]|[^\s*])\*/g;
|
|
@@ -48,19 +51,21 @@ const ITALIC_UNDERSCORE_REGEX = /(?<!\w)_([^\s_][^_]*[^\s_]|[^\s_])_(?!\w)/g;
|
|
|
48
51
|
function processInlineMarkdown(text) {
|
|
49
52
|
let result = escapeHtml(text);
|
|
50
53
|
// Inline style as fallback since the tooltip renders outside the normal DOM tree.
|
|
51
|
-
result = result.replace(IMAGE_REGEX, (_match, alt, url) => {
|
|
52
|
-
if (!isSafeImageUrl(url)) {
|
|
54
|
+
result = result.replace(IMAGE_REGEX, (_match, alt, url = "") => {
|
|
55
|
+
if (url && !isSafeImageUrl(url)) {
|
|
53
56
|
return `${alt}`;
|
|
54
57
|
}
|
|
58
|
+
// Empty URL → broken image keeping the alt (RichText parity).
|
|
55
59
|
return `<img src="${url}" alt="${alt}" style="max-width: 100%; display: block; margin: 4px 0;" />`;
|
|
56
60
|
});
|
|
57
61
|
// Always emit a `target="_blank"` anchor for http(s) URLs; whether the user
|
|
58
62
|
// can practically reach it depends on the tooltip mode's lifecycle (the
|
|
59
63
|
// tooltip needs to stay open long enough to mouse over the link).
|
|
60
|
-
result = result.replace(LINK_REGEX, (_match, linkText, url) => {
|
|
61
|
-
if (!isSafeLinkUrl(url)) {
|
|
64
|
+
result = result.replace(LINK_REGEX, (_match, linkText, url = "") => {
|
|
65
|
+
if (url && !isSafeLinkUrl(url)) {
|
|
62
66
|
return linkText;
|
|
63
67
|
}
|
|
68
|
+
// Empty URL → anchor with empty href, like RichText (points at the current page).
|
|
64
69
|
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${linkText}</a>`;
|
|
65
70
|
});
|
|
66
71
|
// Bold-italic: ***text*** — must run before bold and italic so the triple
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"referenceResolver.d.ts","sourceRoot":"","sources":["../../src/customTooltip/referenceResolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"referenceResolver.d.ts","sourceRoot":"","sources":["../../src/customTooltip/referenceResolver.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAIhC,MAAM,YAAY,CAAC;AAuEpB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE,wBAAwB,GAClC,MAAM,CAWR"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// (C) 2026 GoodData Corporation
|
|
2
2
|
import { REFERENCE_REGEX_MATCH } from "@gooddata/sdk-ui-kit";
|
|
3
|
+
import { URL_PATTERN } from "./markdownToHtml.js";
|
|
3
4
|
import { labelKey, metricKey, } from "./types.js";
|
|
4
5
|
// Markdown metacharacters that, if present in a substituted value, would be
|
|
5
6
|
// reinterpreted as formatting by `markdownToHtml`. Backslash-escape them so the
|
|
@@ -28,6 +29,26 @@ function renderReference(ref, strings) {
|
|
|
28
29
|
return strings.noFetch;
|
|
29
30
|
}
|
|
30
31
|
}
|
|
32
|
+
// Prefix is matched case-insensitively (`metric` | `label`); LDM identifiers are case-sensitive.
|
|
33
|
+
function lookupRef(values, prefix, identifier) {
|
|
34
|
+
return values[prefix.toLowerCase() === "metric" ? metricKey(identifier) : labelKey(identifier)];
|
|
35
|
+
}
|
|
36
|
+
// In image/link URL targets a no-data reference must collapse to empty rather than
|
|
37
|
+
// the "(No data)" placeholder, which would break markdown parsing and leak the raw
|
|
38
|
+
// `` syntax. Blanking yields a broken image / empty-href link, matching
|
|
39
|
+
// RichText. Image alt is blanked too; link text keeps the normal placeholder.
|
|
40
|
+
// Slot grammar mirrors `markdownToHtml` (shared URL_PATTERN, single-line slots),
|
|
41
|
+
// so blanking applies only where the renderer will actually see an image/link.
|
|
42
|
+
const IMAGE_CONSTRUCT_REGEX = new RegExp(`!\\[([^\\]\\n]*)\\]\\((${URL_PATTERN})?\\)`, "g");
|
|
43
|
+
const LINK_CONSTRUCT_REGEX = new RegExp(`(?<!!)\\[([^\\]\\n]+)\\]\\((${URL_PATTERN})?\\)`, "g");
|
|
44
|
+
function blankNonValueRefs(slot, values) {
|
|
45
|
+
return slot.replace(REFERENCE_REGEX_MATCH, (fullMatch, _wrapped, _key, prefix, identifier) => lookupRef(values, prefix, identifier)?.kind === "value" ? fullMatch : "");
|
|
46
|
+
}
|
|
47
|
+
function blankNonValueTargets(content, values) {
|
|
48
|
+
return content
|
|
49
|
+
.replace(IMAGE_CONSTRUCT_REGEX, (_match, alt, url = "") => `})`)
|
|
50
|
+
.replace(LINK_CONSTRUCT_REGEX, (_match, text, url = "") => `[${text}](${blankNonValueRefs(url, values)})`);
|
|
51
|
+
}
|
|
31
52
|
/**
|
|
32
53
|
* Substitutes `{metric/id}` and `{label/id}` references in markdown content
|
|
33
54
|
* with resolved values from the lookup table.
|
|
@@ -49,11 +70,6 @@ export function resolveReferences(content, values, strings) {
|
|
|
49
70
|
if (!content) {
|
|
50
71
|
return "";
|
|
51
72
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// route through the key helpers so the lookup format stays single-sourced
|
|
55
|
-
// with the write sites. LDM identifiers stay as-is — they are case-sensitive.
|
|
56
|
-
const key = prefix.toLowerCase() === "metric" ? metricKey(identifier) : labelKey(identifier);
|
|
57
|
-
return escapeMarkdownMetachars(renderReference(values[key], strings));
|
|
58
|
-
});
|
|
73
|
+
// Blank no-data image/link targets first, before they reach substitution.
|
|
74
|
+
return blankNonValueTargets(content, values).replace(REFERENCE_REGEX_MATCH, (_fullMatch, _wrapped, _key, prefix, identifier) => escapeMarkdownMetachars(renderReference(lookupRef(values, prefix, identifier), strings)));
|
|
59
75
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-vis-commons",
|
|
3
|
-
"version": "11.42.0-alpha.
|
|
3
|
+
"version": "11.42.0-alpha.2",
|
|
4
4
|
"description": "GoodData.UI SDK - common functionality for different types of visualizations",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"react-intl": "7.1.11",
|
|
37
37
|
"react-measure": "^2.5.2",
|
|
38
38
|
"tslib": "2.8.1",
|
|
39
|
-
"@gooddata/sdk-backend-spi": "11.42.0-alpha.
|
|
40
|
-
"@gooddata/sdk-model": "11.42.0-alpha.
|
|
41
|
-
"@gooddata/sdk-ui": "11.42.0-alpha.
|
|
42
|
-
"@gooddata/sdk-ui-
|
|
43
|
-
"@gooddata/sdk-ui-
|
|
39
|
+
"@gooddata/sdk-backend-spi": "11.42.0-alpha.2",
|
|
40
|
+
"@gooddata/sdk-model": "11.42.0-alpha.2",
|
|
41
|
+
"@gooddata/sdk-ui": "11.42.0-alpha.2",
|
|
42
|
+
"@gooddata/sdk-ui-kit": "11.42.0-alpha.2",
|
|
43
|
+
"@gooddata/sdk-ui-theme-provider": "11.42.0-alpha.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -81,11 +81,11 @@
|
|
|
81
81
|
"typescript": "5.9.3",
|
|
82
82
|
"vitest": "4.1.8",
|
|
83
83
|
"vitest-dom": "0.1.1",
|
|
84
|
-
"@gooddata/eslint-config": "11.42.0-alpha.
|
|
85
|
-
"@gooddata/oxlint-config": "11.42.0-alpha.
|
|
86
|
-
"@gooddata/sdk-backend-mockingbird": "11.42.0-alpha.
|
|
87
|
-
"@gooddata/reference-workspace": "11.42.0-alpha.
|
|
88
|
-
"@gooddata/stylelint-config": "11.42.0-alpha.
|
|
84
|
+
"@gooddata/eslint-config": "11.42.0-alpha.2",
|
|
85
|
+
"@gooddata/oxlint-config": "11.42.0-alpha.2",
|
|
86
|
+
"@gooddata/sdk-backend-mockingbird": "11.42.0-alpha.2",
|
|
87
|
+
"@gooddata/reference-workspace": "11.42.0-alpha.2",
|
|
88
|
+
"@gooddata/stylelint-config": "11.42.0-alpha.2"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
91
|
"react": "^18.0.0 || ^19.0.0",
|