@allurereport/web-commons 3.1.0 → 3.3.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.
@@ -0,0 +1,5 @@
1
+ import type { AllureChartsStoreData, StatusAgePyramidChartData, StatusAgePyramidChartOptions } from "@allurereport/charts-api";
2
+ export declare const generateStatusAgePyramid: (props: {
3
+ options: StatusAgePyramidChartOptions;
4
+ storeData: AllureChartsStoreData;
5
+ }) => StatusAgePyramidChartData;
@@ -1,15 +1,14 @@
1
1
  import { ChartType, DEFAULT_CHART_HISTORY_LIMIT } from "@allurereport/charts-api";
2
- import { htrsByTr } from "@allurereport/core-api";
3
2
  import { limitHistoryDataPoints } from "./chart-utils.js";
4
- const createEmptyStats = (statuses) => {
5
- return statuses.reduce((acc, status) => {
3
+ const createEmptyStats = () => {
4
+ return STATUSES.reduce((acc, status) => {
6
5
  acc[status] = 0;
7
6
  return acc;
8
7
  }, {});
9
8
  };
10
9
  const STATUSES = ["failed", "broken", "skipped", "unknown"];
11
10
  const isFBSUStatus = (status) => STATUSES.includes(status);
12
- export const generateFBSUAgePyramid = (props) => {
11
+ export const generateStatusAgePyramid = (props) => {
13
12
  const { options, storeData } = props;
14
13
  const { limit = DEFAULT_CHART_HISTORY_LIMIT } = options;
15
14
  const { historyDataPoints, testResults } = storeData;
@@ -17,23 +16,35 @@ export const generateFBSUAgePyramid = (props) => {
17
16
  const limitedHistoryPoints = limitHistoryDataPoints(historyDataPoints, limit).sort((a, b) => a.timestamp - b.timestamp);
18
17
  if (limitedHistoryPoints.length === 0) {
19
18
  return {
20
- type: ChartType.FBSUAgePyramid,
19
+ type: ChartType.StatusAgePyramid,
21
20
  title: options.title,
22
21
  data: [
23
22
  {
24
23
  id: "current",
25
24
  timestamp: currentReportTimestamp,
26
- ...createEmptyStats(STATUSES),
25
+ ...createEmptyStats(),
27
26
  },
28
27
  ],
29
28
  statuses: STATUSES,
30
29
  };
31
30
  }
32
- const [earliestHdp, ...hdps] = limitedHistoryPoints;
31
+ const hdps = limitedHistoryPoints.map((datapoint) => ({
32
+ ...datapoint,
33
+ testResults: Object.values(datapoint.testResults).reduce((acc, testResult) => {
34
+ if (!testResult.historyId) {
35
+ return acc;
36
+ }
37
+ const isInCurrentRun = testResults.findIndex((tr) => tr.historyId === testResult.historyId) !== -1;
38
+ if (isInCurrentRun) {
39
+ acc[testResult.historyId] = testResult;
40
+ }
41
+ return acc;
42
+ }, {}),
43
+ }));
33
44
  const dataPoints = [
34
45
  ...hdps.map((hdp) => ({
35
46
  ...hdp,
36
- ...createEmptyStats(STATUSES),
47
+ ...createEmptyStats(),
37
48
  })),
38
49
  {
39
50
  testResults: testResults.reduce((acc, testResult) => {
@@ -42,22 +53,23 @@ export const generateFBSUAgePyramid = (props) => {
42
53
  }, {}),
43
54
  uuid: "current",
44
55
  timestamp: currentReportTimestamp,
45
- ...createEmptyStats(STATUSES),
56
+ ...createEmptyStats(),
46
57
  },
47
58
  ];
48
- dataPoints.forEach((dp, index, dataPointsAscending) => {
59
+ dataPoints.forEach((dp, index, dps) => {
49
60
  const { testResults: trs } = dp;
50
- const isFirst = index === 0;
51
- const hpsPriorToCurrent = isFirst ? [earliestHdp] : dataPointsAscending.slice(0, index);
61
+ const historyAfter = dps.slice(index, dps.length - 1);
52
62
  const currentTrs = Object.values(trs);
53
63
  for (const cTr of currentTrs) {
54
- if (!isFBSUStatus(cTr.status)) {
64
+ const currentTrStatus = cTr.status;
65
+ if (!isFBSUStatus(currentTrStatus)) {
55
66
  continue;
56
67
  }
57
- const htrsPriortoCurr = htrsByTr(hpsPriorToCurrent, cTr);
58
- if (htrsPriortoCurr.length === 0) {
59
- dp[cTr.status]++;
68
+ const historyAfterTrsStatuses = historyAfter.map((hdp) => hdp.testResults[cTr.historyId]?.status ?? undefined);
69
+ if (historyAfterTrsStatuses.some((status) => status !== currentTrStatus)) {
70
+ continue;
60
71
  }
72
+ dp[currentTrStatus]++;
61
73
  }
62
74
  });
63
75
  const data = dataPoints.map(({ uuid, timestamp, ...stats }) => ({
@@ -69,7 +81,7 @@ export const generateFBSUAgePyramid = (props) => {
69
81
  unknown: stats.unknown ?? 0,
70
82
  }));
71
83
  return {
72
- type: ChartType.FBSUAgePyramid,
84
+ type: ChartType.StatusAgePyramid,
73
85
  title: options.title,
74
86
  data: data,
75
87
  statuses: STATUSES,
@@ -1,4 +1,5 @@
1
1
  import { type ChartOptions, type GeneratedChartsData } from "@allurereport/charts-api";
2
+ import type { TestResult } from "@allurereport/core-api";
2
3
  import { type AllureStore } from "@allurereport/plugin-api";
3
4
  type ChartsWidgetData = {
4
5
  general: GeneratedChartsData;
@@ -6,5 +7,5 @@ type ChartsWidgetData = {
6
7
  [env: string]: GeneratedChartsData;
7
8
  };
8
9
  };
9
- export declare const generateCharts: (chartsOptions: ChartOptions[], store: AllureStore, reportName: string, generateUuid: () => string) => Promise<ChartsWidgetData>;
10
+ export declare const generateCharts: (chartsOptions: ChartOptions[], store: AllureStore, reportName: string, generateUuid: () => string, filter?: (testResult: TestResult) => boolean) => Promise<ChartsWidgetData>;
10
11
  export {};
@@ -3,8 +3,8 @@ import { DEFAULT_ENVIRONMENT } from "@allurereport/core-api";
3
3
  import { generateCurrentStatusChart } from "./generateCurrentStatusChart.js";
4
4
  import { generateDurationDynamicsChart } from "./generateDurationDynamicsChart.js";
5
5
  import { generateDurationsChart } from "./generateDurationsChart.js";
6
- import { generateFBSUAgePyramid } from "./generateFBSUAgePyramid.js";
7
6
  import { generateStabilityDistributionChart } from "./generateStabilityDistributionChart.js";
7
+ import { generateStatusAgePyramid } from "./generateStatusAgePyramid.js";
8
8
  import { generateStatusDynamicsChart } from "./generateStatusDynamicsChart.js";
9
9
  import { generateStatusTransitionsChart } from "./generateStatusTransitionsChart.js";
10
10
  import { generateTestBaseGrowthDynamicsChart } from "./generateTestBaseGrowthDynamicsChart.js";
@@ -13,12 +13,61 @@ import { generateTrSeveritiesChart } from "./generateTrSeveritiesChart.js";
13
13
  import { generateHeatMapChart } from "./heatMap.js";
14
14
  import { generateTreeMapChart } from "./treeMap.js";
15
15
  const generateChartData = async (props) => {
16
- const { env, chartsOptions, store, reportName, generateUuid } = props;
16
+ const { env, chartsOptions, store, generateUuid, filter } = props;
17
17
  const result = {};
18
+ const getTrs = async () => {
19
+ let trs = [];
20
+ if (env) {
21
+ trs = await store.testResultsByEnvironment(env);
22
+ }
23
+ else {
24
+ trs = await store.allTestResults();
25
+ }
26
+ if (filter) {
27
+ trs = trs.filter(filter);
28
+ }
29
+ return trs;
30
+ };
31
+ const getHistoryDataPoints = async () => {
32
+ let historyDataPoints = [];
33
+ if (env) {
34
+ historyDataPoints = await store.allHistoryDataPointsByEnvironment(env);
35
+ }
36
+ historyDataPoints = await store.allHistoryDataPoints();
37
+ if (typeof filter === "function") {
38
+ historyDataPoints = historyDataPoints.map((hdp) => {
39
+ const trsEntries = Object.entries(hdp.testResults);
40
+ const filteredTrsEntries = trsEntries.filter(([, tr]) => {
41
+ try {
42
+ return filter(tr);
43
+ }
44
+ catch (error) {
45
+ return false;
46
+ }
47
+ });
48
+ return {
49
+ ...hdp,
50
+ testResults: Object.fromEntries(filteredTrsEntries),
51
+ };
52
+ });
53
+ }
54
+ return historyDataPoints;
55
+ };
56
+ const getStatistic = () => {
57
+ return store.testsStatistic((tr) => {
58
+ if (env && tr.environment !== env) {
59
+ return false;
60
+ }
61
+ if (typeof filter === "function" && !filter(tr)) {
62
+ return false;
63
+ }
64
+ return true;
65
+ });
66
+ };
18
67
  const storeData = await Promise.all([
19
- env ? await store.allHistoryDataPointsByEnvironment(env) : await store.allHistoryDataPoints(),
20
- env ? await store.testResultsByEnvironment(env) : await store.allTestResults(),
21
- env ? await store.testsStatistic((tr) => tr.environment === env) : await store.testsStatistic(),
68
+ await getHistoryDataPoints(),
69
+ await getTrs(),
70
+ await getStatistic(),
22
71
  ]).then(([historyDataPoints, testResults, statistic]) => ({
23
72
  historyDataPoints,
24
73
  testResults,
@@ -48,8 +97,8 @@ const generateChartData = async (props) => {
48
97
  case ChartType.TestBaseGrowthDynamics:
49
98
  result[chartId] = generateTestBaseGrowthDynamicsChart({ options: chartOption, storeData });
50
99
  break;
51
- case ChartType.FBSUAgePyramid:
52
- result[chartId] = generateFBSUAgePyramid({ options: chartOption, storeData });
100
+ case ChartType.StatusAgePyramid:
101
+ result[chartId] = generateStatusAgePyramid({ options: chartOption, storeData });
53
102
  break;
54
103
  case ChartType.TrSeverities:
55
104
  result[chartId] = generateTrSeveritiesChart({ options: chartOption, storeData });
@@ -75,10 +124,10 @@ const generateChartData = async (props) => {
75
124
  const hasOnlyDefaultEnvironment = (environments) => {
76
125
  return environments.length === 1 && environments[0] === DEFAULT_ENVIRONMENT;
77
126
  };
78
- export const generateCharts = async (chartsOptions, store, reportName, generateUuid) => {
127
+ export const generateCharts = async (chartsOptions, store, reportName, generateUuid, filter) => {
79
128
  const environments = await store.allEnvironments();
80
129
  const chartsData = {
81
- general: await generateChartData({ chartsOptions, store, reportName, generateUuid }),
130
+ general: await generateChartData({ chartsOptions, store, reportName, generateUuid, filter }),
82
131
  byEnv: {},
83
132
  };
84
133
  if (hasOnlyDefaultEnvironment(environments)) {
@@ -91,6 +140,7 @@ export const generateCharts = async (chartsOptions, store, reportName, generateU
91
140
  reportName,
92
141
  env: environment,
93
142
  generateUuid,
143
+ filter,
94
144
  });
95
145
  }
96
146
  return chartsData;
@@ -1,4 +1,4 @@
1
- import type { ChartId, ChartType, DurationDynamicsChartData, DurationsChartData, FBSUAgePyramidChartData, HeatMapSerie, StabilityDistributionChartData, StatusTransitionsChartData, TestBaseGrowthDynamicsChartData, TestingPyramidChartData, TrSeveritiesChartData, TreeMapNode } from "@allurereport/charts-api";
1
+ import type { ChartId, ChartType, DurationDynamicsChartData, DurationsChartData, HeatMapSerie, StabilityDistributionChartData, StatusAgePyramidChartData, StatusTransitionsChartData, TestBaseGrowthDynamicsChartData, TestingPyramidChartData, TrSeveritiesChartData, TreeMapNode } from "@allurereport/charts-api";
2
2
  import type { Statistic, TestStatus } from "@allurereport/core-api";
3
3
  export type TreeMapTooltipAccessor = <T>(node: T) => string[];
4
4
  export interface Point {
@@ -58,8 +58,8 @@ export interface UITreeMapChartData extends ResponseTreeMapChartData {
58
58
  export interface UIHeatMapChartData extends ResponseHeatMapChartData {
59
59
  colors: (value: number, domain?: number[]) => string;
60
60
  }
61
- export type ChartData = CurrentStatusChartData | StatusDynamicsChartData | StatusTransitionsChartData | DurationsChartData | StabilityDistributionChartData | ResponseTreeMapChartData | ResponseHeatMapChartData | TestBaseGrowthDynamicsChartData | FBSUAgePyramidChartData | TrSeveritiesChartData | DurationDynamicsChartData | TestingPyramidChartData;
62
- export type UIChartData = UICurrentStatusChartData | UIStatusDynamicsChartData | UITreeMapChartData | UIHeatMapChartData | UIStatusTransitionsChartData | UIDurationsChartData | TestBaseGrowthDynamicsChartData | FBSUAgePyramidChartData | StabilityDistributionChartData | TrSeveritiesChartData | DurationDynamicsChartData | TestingPyramidChartData;
61
+ export type ChartData = CurrentStatusChartData | StatusDynamicsChartData | StatusTransitionsChartData | DurationsChartData | StabilityDistributionChartData | ResponseTreeMapChartData | ResponseHeatMapChartData | TestBaseGrowthDynamicsChartData | StatusAgePyramidChartData | TrSeveritiesChartData | DurationDynamicsChartData | TestingPyramidChartData;
62
+ export type UIChartData = UICurrentStatusChartData | UIStatusDynamicsChartData | UITreeMapChartData | UIHeatMapChartData | UIStatusTransitionsChartData | UIDurationsChartData | TestBaseGrowthDynamicsChartData | StatusAgePyramidChartData | StabilityDistributionChartData | TrSeveritiesChartData | DurationDynamicsChartData | TestingPyramidChartData;
63
63
  export type ChartsData = Record<ChartId, ChartData>;
64
64
  export type ChartsDataWithEnvs = {
65
65
  general: Record<ChartId, ChartData>;
@@ -107,7 +107,7 @@ export const createCharts = (res) => {
107
107
  else if (chart.type === ChartType.TestBaseGrowthDynamics) {
108
108
  acc[chartId] = res[chartId];
109
109
  }
110
- else if (chart.type === ChartType.FBSUAgePyramid) {
110
+ else if (chart.type === ChartType.StatusAgePyramid) {
111
111
  acc[chartId] = res[chartId];
112
112
  }
113
113
  else if (chart.type === ChartType.TrSeverities) {
package/dist/i18n.d.ts CHANGED
@@ -1,6 +1,15 @@
1
- export declare const AVAILABLE_LOCALES: readonly ["en", "ru", "ua", "pl", "es", "pt", "de", "hy", "az", "fr", "it", "ja", "he", "ka", "kr", "nl", "sv", "tr", "zh"];
1
+ export declare const AVAILABLE_LOCALES: readonly ["en", "en-iso", "ru", "uk", "pl", "es", "pt", "de", "hy", "az", "fr", "it", "ja", "he", "ka", "kr", "nl", "sv", "tr", "zh"];
2
2
  export declare const DEFAULT_LOCALE = "en";
3
3
  export type LangLocale = (typeof AVAILABLE_LOCALES)[number];
4
+ export type DateTimeFormatKind = "date" | "dateTime" | "dateTimeNoSeconds";
5
+ export type DateTimeFormatOverride = {
6
+ locale?: string;
7
+ options?: Intl.DateTimeFormatOptions;
8
+ includeAtSeparator?: boolean;
9
+ stripComma?: boolean;
10
+ };
11
+ export declare const LOCALE_DATE_TIME_OVERRIDES: Record<string, Partial<Record<DateTimeFormatKind, DateTimeFormatOverride>>>;
12
+ export declare const getLocaleDateTimeOverride: (locale: string, kind: DateTimeFormatKind) => DateTimeFormatOverride | undefined;
4
13
  export declare const LANG_LOCALE: Record<LangLocale, {
5
14
  short: string;
6
15
  full: string;
package/dist/i18n.js CHANGED
@@ -1,7 +1,8 @@
1
1
  export const AVAILABLE_LOCALES = [
2
2
  "en",
3
+ "en-iso",
3
4
  "ru",
4
- "ua",
5
+ "uk",
5
6
  "pl",
6
7
  "es",
7
8
  "pt",
@@ -20,98 +21,146 @@ export const AVAILABLE_LOCALES = [
20
21
  "zh",
21
22
  ];
22
23
  export const DEFAULT_LOCALE = "en";
24
+ export const LOCALE_DATE_TIME_OVERRIDES = {
25
+ "en-iso": {
26
+ date: {
27
+ locale: "en-CA",
28
+ options: {
29
+ year: "numeric",
30
+ month: "2-digit",
31
+ day: "2-digit",
32
+ },
33
+ stripComma: true,
34
+ },
35
+ dateTime: {
36
+ locale: "en-CA",
37
+ options: {
38
+ year: "numeric",
39
+ month: "2-digit",
40
+ day: "2-digit",
41
+ hour: "2-digit",
42
+ minute: "2-digit",
43
+ second: "2-digit",
44
+ hour12: false,
45
+ },
46
+ includeAtSeparator: false,
47
+ stripComma: true,
48
+ },
49
+ dateTimeNoSeconds: {
50
+ locale: "en-CA",
51
+ options: {
52
+ year: "numeric",
53
+ month: "2-digit",
54
+ day: "2-digit",
55
+ hour: "2-digit",
56
+ minute: "2-digit",
57
+ hour12: false,
58
+ },
59
+ includeAtSeparator: false,
60
+ stripComma: true,
61
+ },
62
+ },
63
+ };
64
+ export const getLocaleDateTimeOverride = (locale, kind) => {
65
+ return LOCALE_DATE_TIME_OVERRIDES[locale]?.[kind];
66
+ };
23
67
  export const LANG_LOCALE = {
24
- en: {
68
+ "en": {
25
69
  short: "Eng",
26
70
  full: "English",
27
71
  iso: "en-US",
28
72
  },
29
- ru: {
73
+ "en-iso": {
74
+ short: "En ISO",
75
+ full: "English (ISO-8601)",
76
+ iso: "en-CA",
77
+ },
78
+ "ru": {
30
79
  short: "Ру",
31
80
  full: "Русский",
32
81
  iso: "ru-RU",
33
82
  },
34
- ua: {
83
+ "uk": {
35
84
  short: "Ук",
36
85
  full: "Українська",
37
86
  iso: "uk-UA",
38
87
  },
39
- pl: {
88
+ "pl": {
40
89
  short: "Pl",
41
90
  full: "Polski",
42
91
  iso: "pl-PL",
43
92
  },
44
- es: {
93
+ "es": {
45
94
  short: "Es",
46
95
  full: "Español",
47
96
  iso: "es-ES",
48
97
  },
49
- pt: {
98
+ "pt": {
50
99
  short: "Pt",
51
100
  full: "Português",
52
101
  iso: "pt-PT",
53
102
  },
54
- de: {
103
+ "de": {
55
104
  short: "De",
56
105
  full: "Deutsch",
57
106
  iso: "de-DE",
58
107
  },
59
- hy: {
108
+ "hy": {
60
109
  short: "Hy",
61
110
  full: "Հայերեն",
62
111
  iso: "hy-AM",
63
112
  },
64
- az: {
113
+ "az": {
65
114
  short: "Az",
66
115
  full: "Azərbaycan",
67
116
  iso: "az-AZ",
68
117
  },
69
- fr: {
118
+ "fr": {
70
119
  short: "Fr",
71
120
  full: "Français",
72
121
  iso: "fr-FR",
73
122
  },
74
- it: {
123
+ "it": {
75
124
  short: "It",
76
125
  full: "Italiano",
77
126
  iso: "it-IT",
78
127
  },
79
- ja: {
128
+ "ja": {
80
129
  short: "Ja",
81
130
  full: "日本語",
82
131
  iso: "ja-JP",
83
132
  },
84
- he: {
133
+ "he": {
85
134
  short: "He",
86
135
  full: "עברית",
87
136
  iso: "he-IL",
88
137
  },
89
- ka: {
138
+ "ka": {
90
139
  short: "Ka",
91
140
  full: "ქართული",
92
141
  iso: "ka-GE",
93
142
  },
94
- kr: {
143
+ "kr": {
95
144
  short: "Kr",
96
145
  full: "한국어",
97
146
  iso: "kr-KR",
98
147
  },
99
- nl: {
148
+ "nl": {
100
149
  short: "Nl",
101
150
  full: "Nederlands",
102
151
  iso: "nl-NL",
103
152
  },
104
- sv: {
153
+ "sv": {
105
154
  short: "Sv",
106
155
  full: "Svenska",
107
156
  iso: "sv-SE",
108
157
  },
109
- tr: {
158
+ "tr": {
110
159
  short: "Tr",
111
160
  full: "Türkçe",
112
161
  iso: "tr-TR",
113
162
  },
114
- zh: {
163
+ "zh": {
115
164
  short: "Zh",
116
165
  full: "中文",
117
166
  iso: "zh-CN",
package/dist/index.d.ts CHANGED
@@ -11,3 +11,4 @@ export * from "./stores/theme/index.js";
11
11
  export * from "./stores/loadableStore/index.js";
12
12
  export * from "./stores/persister/index.js";
13
13
  export * from "./utils.js";
14
+ export * from "./prose.js";
package/dist/index.js CHANGED
@@ -11,3 +11,4 @@ export * from "./stores/theme/index.js";
11
11
  export * from "./stores/loadableStore/index.js";
12
12
  export * from "./stores/persister/index.js";
13
13
  export * from "./utils.js";
14
+ export * from "./prose.js";
@@ -0,0 +1,2 @@
1
+ export declare const proseStyles = "\nhtml, body {\n margin: 0;\n padding: 0;\n overflow-x: hidden;\n overflow-y: hidden;\n background: var(--bg-base-primary);\n}\n\nbody {\n color: var(--on-text-primary);\n font-family: var(--font-family);\n font-size: var(--font-size-m);\n line-height: var(--line-height-m);\n}\n\np {\n margin-bottom: 10px;\n}\n\np:last-child {\n margin-bottom: 0;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-weight: var(--font-weight-bold) !important;\n line-height: var(--line-height-l) !important;\n margin: 16px 0 10px;\n}\n\nh1:first-child,\nh2:first-child,\nh3:first-child,\nh4:first-child,\nh5:first-child,\nh6:first-child {\n margin-top: 0;\n}\n\nh1 {\n font-size: var(--font-size-xl) !important;\n}\n\nh2,\nh3 {\n font-size: var(--font-size-l) !important;\n}\n\nh4 {\n font-size: var(--font-size-m) !important;\n}\n\nh5,\nh6 {\n font-size: var(--font-size-s) !important;\n}\n\nh6 {\n color: var(--on-text-secondary);\n}\n\nstrong,\nb {\n font-weight: var(--font-weight-bold) !important;\n}\n\nem,\ni {\n font-style: italic !important;\n}\n\ndel,\ns {\n text-decoration: line-through;\n}\n\na {\n color: var(--on-text-primary);\n text-decoration: underline;\n}\n\na:hover {\n color: var(--on-text-secondary);\n}\n\ncode {\n font-family: var(--font-family-mono) !important;\n font-size: var(--font-size-m-code) !important;\n padding: 0.2em 0.4em;\n background: var(--bg-control-secondary);\n border-radius: 4px;\n}\n\npre {\n font-family: var(--font-family-mono) !important;\n font-size: var(--font-size-s) !important;\n line-height: 1.45 !important;\n padding: 16px;\n overflow: auto;\n background: var(--bg-control-secondary);\n border-radius: 6px;\n margin-bottom: 16px;\n}\n\npre code {\n padding: 0;\n background: transparent;\n font-size: inherit !important;\n border-radius: 0;\n}\n\nblockquote {\n padding: 0 1em;\n border-left: 0.25em solid var(--on-border-primary);\n color: var(--on-text-secondary);\n margin-bottom: 16px;\n}\n\nul,\nol {\n padding-left: 2em;\n margin-bottom: 10px;\n}\n\nul {\n list-style: disc !important;\n}\n\nol {\n list-style: decimal !important;\n}\n\nli + li {\n margin-top: 0.25em;\n}\n\nhr {\n height: 0.25em;\n padding: 0;\n margin: 24px 0;\n background-color: var(--on-border-primary);\n border: 0 !important;\n}\n\ntable {\n border-spacing: 0;\n border-collapse: collapse;\n margin-bottom: 16px;\n display: block;\n width: max-content;\n max-width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n transform: translateZ(0);\n contain: layout paint;\n}\n\nth,\ntd {\n padding: 6px 13px;\n border: 1px solid var(--on-border-primary) !important;\n white-space: nowrap;\n}\n\nth {\n font-weight: var(--font-weight-bold) !important;\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--bg-base-primary);\n}\n\ntr:nth-child(2n) {\n background: var(--bg-control-secondary);\n}\n\nimg {\n max-width: 100% !important;\n height: auto !important;\n display: inline-block !important;\n vertical-align: middle !important;\n}\n\nabbr,\nabbr[title] {\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: none;\n}\n\nkbd {\n display: inline-block;\n padding: 3px 5px;\n font-family: var(--font-family-mono) !important;\n font-size: 11px;\n line-height: 10px;\n color: var(--on-text-primary);\n vertical-align: middle;\n background-color: var(--bg-control-secondary);\n border: solid 1px var(--on-border-medium);\n border-bottom-color: var(--on-border-medium);\n border-radius: 6px;\n box-shadow: inset 0 -1px 0 var(--on-border-medium);\n}\n\nsamp {\n font-family: var(--font-family-mono) !important;\n font-size: 85% !important;\n}\n\nvar {\n font-family: var(--font-family-mono) !important;\n font-style: italic !important;\n font-weight: var(--font-weight-bold) !important;\n}\n\nmark {\n background-color: var(--bg-support-aldebaran);\n color: var(--on-text-primary);\n padding: 0.1em 0.2em;\n border-radius: 2px;\n}\n\nsmall {\n font-size: 85% !important;\n}\n\nsub,\nsup {\n font-size: 75% !important;\n line-height: 0 !important;\n position: relative !important;\n vertical-align: baseline !important;\n}\n\nsub {\n bottom: -0.25em !important;\n}\n\nsup {\n top: -0.5em !important;\n}\n\nins {\n text-decoration: underline;\n background-color: var(--bg-support-gliese);\n color: var(--on-text-primary);\n text-decoration-color: var(--on-support-gliese);\n}\n\ndfn {\n font-style: italic !important;\n font-weight: var(--font-weight-bold) !important;\n}\n\ncite {\n font-style: italic !important;\n}\n\nq {\n font-style: italic !important;\n}\n\nq::before {\n content: open-quote;\n}\n\nq::after {\n content: close-quote;\n}\n\ntime {\n font-variant-numeric: tabular-nums;\n}\n\ndl {\n padding: 0;\n margin-bottom: 16px;\n}\n\ndt {\n padding: 0;\n margin-top: 16px;\n font-size: 1em;\n font-style: italic;\n font-weight: var(--font-weight-bold) !important;\n}\n\ndt:first-child {\n margin-top: 0;\n}\n\ndd {\n padding: 0 0 0 16px;\n margin-left: 0;\n margin-bottom: 16px;\n}\n\nfigure {\n margin: 16px 0;\n display: block;\n}\n\nfigcaption {\n margin-top: 8px;\n font-size: var(--font-size-s) !important;\n color: var(--on-text-secondary);\n font-style: italic;\n text-align: center;\n}\n\ndetails {\n display: block;\n margin-bottom: 16px;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n font-weight: var(--font-weight-bold) !important;\n margin-bottom: 8px;\n}\n\nsummary:hover {\n color: var(--on-text-secondary);\n}\n\nsummary::marker {\n color: var(--on-text-secondary);\n}\n\ndetails[open] summary {\n margin-bottom: 16px;\n}\n\narticle,\nsection,\naside,\nnav {\n display: block;\n margin-bottom: 16px;\n}\n\nheader,\nfooter {\n display: block;\n margin-bottom: 16px;\n}\n\naddress {\n display: block;\n font-style: italic;\n margin-bottom: 16px;\n}\n";
2
+ export declare const resolveCssVarDeclarations: (cssText: string) => string;
package/dist/prose.js ADDED
@@ -0,0 +1,390 @@
1
+ export const proseStyles = `
2
+ html, body {
3
+ margin: 0;
4
+ padding: 0;
5
+ overflow-x: hidden;
6
+ overflow-y: hidden;
7
+ background: var(--bg-base-primary);
8
+ }
9
+
10
+ body {
11
+ color: var(--on-text-primary);
12
+ font-family: var(--font-family);
13
+ font-size: var(--font-size-m);
14
+ line-height: var(--line-height-m);
15
+ }
16
+
17
+ p {
18
+ margin-bottom: 10px;
19
+ }
20
+
21
+ p:last-child {
22
+ margin-bottom: 0;
23
+ }
24
+
25
+ h1,
26
+ h2,
27
+ h3,
28
+ h4,
29
+ h5,
30
+ h6 {
31
+ font-weight: var(--font-weight-bold) !important;
32
+ line-height: var(--line-height-l) !important;
33
+ margin: 16px 0 10px;
34
+ }
35
+
36
+ h1:first-child,
37
+ h2:first-child,
38
+ h3:first-child,
39
+ h4:first-child,
40
+ h5:first-child,
41
+ h6:first-child {
42
+ margin-top: 0;
43
+ }
44
+
45
+ h1 {
46
+ font-size: var(--font-size-xl) !important;
47
+ }
48
+
49
+ h2,
50
+ h3 {
51
+ font-size: var(--font-size-l) !important;
52
+ }
53
+
54
+ h4 {
55
+ font-size: var(--font-size-m) !important;
56
+ }
57
+
58
+ h5,
59
+ h6 {
60
+ font-size: var(--font-size-s) !important;
61
+ }
62
+
63
+ h6 {
64
+ color: var(--on-text-secondary);
65
+ }
66
+
67
+ strong,
68
+ b {
69
+ font-weight: var(--font-weight-bold) !important;
70
+ }
71
+
72
+ em,
73
+ i {
74
+ font-style: italic !important;
75
+ }
76
+
77
+ del,
78
+ s {
79
+ text-decoration: line-through;
80
+ }
81
+
82
+ a {
83
+ color: var(--on-text-primary);
84
+ text-decoration: underline;
85
+ }
86
+
87
+ a:hover {
88
+ color: var(--on-text-secondary);
89
+ }
90
+
91
+ code {
92
+ font-family: var(--font-family-mono) !important;
93
+ font-size: var(--font-size-m-code) !important;
94
+ padding: 0.2em 0.4em;
95
+ background: var(--bg-control-secondary);
96
+ border-radius: 4px;
97
+ }
98
+
99
+ pre {
100
+ font-family: var(--font-family-mono) !important;
101
+ font-size: var(--font-size-s) !important;
102
+ line-height: 1.45 !important;
103
+ padding: 16px;
104
+ overflow: auto;
105
+ background: var(--bg-control-secondary);
106
+ border-radius: 6px;
107
+ margin-bottom: 16px;
108
+ }
109
+
110
+ pre code {
111
+ padding: 0;
112
+ background: transparent;
113
+ font-size: inherit !important;
114
+ border-radius: 0;
115
+ }
116
+
117
+ blockquote {
118
+ padding: 0 1em;
119
+ border-left: 0.25em solid var(--on-border-primary);
120
+ color: var(--on-text-secondary);
121
+ margin-bottom: 16px;
122
+ }
123
+
124
+ ul,
125
+ ol {
126
+ padding-left: 2em;
127
+ margin-bottom: 10px;
128
+ }
129
+
130
+ ul {
131
+ list-style: disc !important;
132
+ }
133
+
134
+ ol {
135
+ list-style: decimal !important;
136
+ }
137
+
138
+ li + li {
139
+ margin-top: 0.25em;
140
+ }
141
+
142
+ hr {
143
+ height: 0.25em;
144
+ padding: 0;
145
+ margin: 24px 0;
146
+ background-color: var(--on-border-primary);
147
+ border: 0 !important;
148
+ }
149
+
150
+ table {
151
+ border-spacing: 0;
152
+ border-collapse: collapse;
153
+ margin-bottom: 16px;
154
+ display: block;
155
+ width: max-content;
156
+ max-width: 100%;
157
+ overflow-x: auto;
158
+ overflow-y: hidden;
159
+ transform: translateZ(0);
160
+ contain: layout paint;
161
+ }
162
+
163
+ th,
164
+ td {
165
+ padding: 6px 13px;
166
+ border: 1px solid var(--on-border-primary) !important;
167
+ white-space: nowrap;
168
+ }
169
+
170
+ th {
171
+ font-weight: var(--font-weight-bold) !important;
172
+ position: sticky;
173
+ top: 0;
174
+ z-index: 1;
175
+ background: var(--bg-base-primary);
176
+ }
177
+
178
+ tr:nth-child(2n) {
179
+ background: var(--bg-control-secondary);
180
+ }
181
+
182
+ img {
183
+ max-width: 100% !important;
184
+ height: auto !important;
185
+ display: inline-block !important;
186
+ vertical-align: middle !important;
187
+ }
188
+
189
+ abbr,
190
+ abbr[title] {
191
+ text-decoration: underline dotted;
192
+ cursor: help;
193
+ border-bottom: none;
194
+ }
195
+
196
+ kbd {
197
+ display: inline-block;
198
+ padding: 3px 5px;
199
+ font-family: var(--font-family-mono) !important;
200
+ font-size: 11px;
201
+ line-height: 10px;
202
+ color: var(--on-text-primary);
203
+ vertical-align: middle;
204
+ background-color: var(--bg-control-secondary);
205
+ border: solid 1px var(--on-border-medium);
206
+ border-bottom-color: var(--on-border-medium);
207
+ border-radius: 6px;
208
+ box-shadow: inset 0 -1px 0 var(--on-border-medium);
209
+ }
210
+
211
+ samp {
212
+ font-family: var(--font-family-mono) !important;
213
+ font-size: 85% !important;
214
+ }
215
+
216
+ var {
217
+ font-family: var(--font-family-mono) !important;
218
+ font-style: italic !important;
219
+ font-weight: var(--font-weight-bold) !important;
220
+ }
221
+
222
+ mark {
223
+ background-color: var(--bg-support-aldebaran);
224
+ color: var(--on-text-primary);
225
+ padding: 0.1em 0.2em;
226
+ border-radius: 2px;
227
+ }
228
+
229
+ small {
230
+ font-size: 85% !important;
231
+ }
232
+
233
+ sub,
234
+ sup {
235
+ font-size: 75% !important;
236
+ line-height: 0 !important;
237
+ position: relative !important;
238
+ vertical-align: baseline !important;
239
+ }
240
+
241
+ sub {
242
+ bottom: -0.25em !important;
243
+ }
244
+
245
+ sup {
246
+ top: -0.5em !important;
247
+ }
248
+
249
+ ins {
250
+ text-decoration: underline;
251
+ background-color: var(--bg-support-gliese);
252
+ color: var(--on-text-primary);
253
+ text-decoration-color: var(--on-support-gliese);
254
+ }
255
+
256
+ dfn {
257
+ font-style: italic !important;
258
+ font-weight: var(--font-weight-bold) !important;
259
+ }
260
+
261
+ cite {
262
+ font-style: italic !important;
263
+ }
264
+
265
+ q {
266
+ font-style: italic !important;
267
+ }
268
+
269
+ q::before {
270
+ content: open-quote;
271
+ }
272
+
273
+ q::after {
274
+ content: close-quote;
275
+ }
276
+
277
+ time {
278
+ font-variant-numeric: tabular-nums;
279
+ }
280
+
281
+ dl {
282
+ padding: 0;
283
+ margin-bottom: 16px;
284
+ }
285
+
286
+ dt {
287
+ padding: 0;
288
+ margin-top: 16px;
289
+ font-size: 1em;
290
+ font-style: italic;
291
+ font-weight: var(--font-weight-bold) !important;
292
+ }
293
+
294
+ dt:first-child {
295
+ margin-top: 0;
296
+ }
297
+
298
+ dd {
299
+ padding: 0 0 0 16px;
300
+ margin-left: 0;
301
+ margin-bottom: 16px;
302
+ }
303
+
304
+ figure {
305
+ margin: 16px 0;
306
+ display: block;
307
+ }
308
+
309
+ figcaption {
310
+ margin-top: 8px;
311
+ font-size: var(--font-size-s) !important;
312
+ color: var(--on-text-secondary);
313
+ font-style: italic;
314
+ text-align: center;
315
+ }
316
+
317
+ details {
318
+ display: block;
319
+ margin-bottom: 16px;
320
+ }
321
+
322
+ summary {
323
+ display: list-item;
324
+ cursor: pointer;
325
+ font-weight: var(--font-weight-bold) !important;
326
+ margin-bottom: 8px;
327
+ }
328
+
329
+ summary:hover {
330
+ color: var(--on-text-secondary);
331
+ }
332
+
333
+ summary::marker {
334
+ color: var(--on-text-secondary);
335
+ }
336
+
337
+ details[open] summary {
338
+ margin-bottom: 16px;
339
+ }
340
+
341
+ article,
342
+ section,
343
+ aside,
344
+ nav {
345
+ display: block;
346
+ margin-bottom: 16px;
347
+ }
348
+
349
+ header,
350
+ footer {
351
+ display: block;
352
+ margin-bottom: 16px;
353
+ }
354
+
355
+ address {
356
+ display: block;
357
+ font-style: italic;
358
+ margin-bottom: 16px;
359
+ }
360
+ `;
361
+ const CSS_VAR_PATTERN = /var\(\s*(--[\w-]+)\s*(?:,\s*([^)]+))?\)/g;
362
+ const resolveCssValue = (value, rootStyles, visitedVars) => {
363
+ return value.replace(CSS_VAR_PATTERN, (_, variableName, fallback) => {
364
+ if (visitedVars.has(variableName)) {
365
+ return fallback ? resolveCssValue(fallback.trim(), rootStyles, visitedVars) : "";
366
+ }
367
+ const nextVisited = new Set(visitedVars);
368
+ nextVisited.add(variableName);
369
+ const variableValue = rootStyles.getPropertyValue(variableName).trim();
370
+ if (variableValue) {
371
+ return resolveCssValue(variableValue, rootStyles, nextVisited);
372
+ }
373
+ return fallback ? resolveCssValue(fallback.trim(), rootStyles, nextVisited) : "";
374
+ });
375
+ };
376
+ export const resolveCssVarDeclarations = (cssText) => {
377
+ if (typeof globalThis === "undefined" || !globalThis.document) {
378
+ return "";
379
+ }
380
+ const rootStyles = globalThis.getComputedStyle(globalThis.document.documentElement);
381
+ const variableNames = Array.from(new Set(cssText.match(/--[\w-]+/g) ?? []));
382
+ return variableNames
383
+ .map((name) => {
384
+ const rawValue = rootStyles.getPropertyValue(name).trim();
385
+ const value = resolveCssValue(rawValue, rootStyles, new Set([name])).trim();
386
+ return value ? `${name}: ${value};` : "";
387
+ })
388
+ .filter(Boolean)
389
+ .join("\n");
390
+ };
@@ -1 +1,2 @@
1
1
  export declare const sanitize: (html: string, config?: Record<string, any>) => string;
2
+ export declare const sanitizeIframeHtml: (html: string) => string;
package/dist/sanitize.js CHANGED
@@ -1,2 +1,6 @@
1
1
  import DOMPurify from "dompurify";
2
2
  export const sanitize = (html, config) => DOMPurify.sanitize(html, config);
3
+ const IFRAME_SANITIZE_CONFIG = {
4
+ USE_PROFILES: { html: true },
5
+ };
6
+ export const sanitizeIframeHtml = (html) => sanitize(html, IFRAME_SANITIZE_CONFIG);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/web-commons",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Collection of utilities used across the web Allure reports",
5
5
  "keywords": [
6
6
  "allure",
@@ -24,10 +24,10 @@
24
24
  "test": "vitest run"
25
25
  },
26
26
  "dependencies": {
27
- "@allurereport/aql": "3.1.0",
28
- "@allurereport/charts-api": "3.1.0",
29
- "@allurereport/core-api": "3.1.0",
30
- "@allurereport/plugin-api": "3.1.0",
27
+ "@allurereport/aql": "3.3.0",
28
+ "@allurereport/charts-api": "3.3.0",
29
+ "@allurereport/core-api": "3.3.0",
30
+ "@allurereport/plugin-api": "3.3.0",
31
31
  "@preact/signals": "^2.6.1",
32
32
  "@preact/signals-core": "^1.12.2",
33
33
  "ansi-to-html": "^0.7.2",
@@ -1,5 +0,0 @@
1
- import type { AllureChartsStoreData, FBSUAgePyramidChartData, FBSUAgePyramidChartOptions } from "@allurereport/charts-api";
2
- export declare const generateFBSUAgePyramid: (props: {
3
- options: FBSUAgePyramidChartOptions;
4
- storeData: AllureChartsStoreData;
5
- }) => FBSUAgePyramidChartData;