@skhema/embed 0.1.6 → 0.1.9
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/components/SkhemaComponent.d.ts +0 -1
- package/dist/components/SkhemaComponent.d.ts.map +1 -1
- package/dist/components/SkhemaElement.d.ts +0 -1
- package/dist/components/SkhemaElement.d.ts.map +1 -1
- package/dist/components/types.d.ts +6 -0
- package/dist/components/types.d.ts.map +1 -1
- package/dist/embed.min.js +1 -1
- package/dist/embed.min.js.map +1 -1
- package/dist/index.cjs +83 -237
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +41 -194
- package/dist/index.es.js.map +1 -1
- package/dist/styles/design-tokens.d.ts +1 -1
- package/dist/styles/design-tokens.d.ts.map +1 -1
- package/dist/tokens.cjs +16 -0
- package/dist/tokens.cjs.map +1 -0
- package/dist/tokens.d.ts +17 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.es.js +16 -0
- package/dist/tokens.es.js.map +1 -0
- package/dist/utils/author-attribution.d.ts +16 -0
- package/dist/utils/author-attribution.d.ts.map +1 -0
- package/dist/validation-CNWaQfh_.cjs +231 -0
- package/dist/validation-CNWaQfh_.cjs.map +1 -0
- package/dist/validation-MSiRF5Wt.js +232 -0
- package/dist/validation-MSiRF5Wt.js.map +1 -0
- package/package.json +10 -4
package/dist/index.es.js
CHANGED
|
@@ -1,115 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
initiatives: {
|
|
14
|
-
bg: "oklch(0.6 0.06 155 / 0.15)",
|
|
15
|
-
text: "oklch(0.6 0.06 155)",
|
|
16
|
-
border: "oklch(0.6 0.06 155 / 0.3)"
|
|
17
|
-
},
|
|
18
|
-
measures: {
|
|
19
|
-
bg: "oklch(0.6 0.06 300 / 0.15)",
|
|
20
|
-
text: "oklch(0.6 0.06 300)",
|
|
21
|
-
border: "oklch(0.6 0.06 300 / 0.3)"
|
|
22
|
-
},
|
|
23
|
-
support: {
|
|
24
|
-
bg: "oklch(0.65 0.06 65 / 0.15)",
|
|
25
|
-
text: "oklch(0.65 0.06 65)",
|
|
26
|
-
border: "oklch(0.65 0.06 65 / 0.3)"
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
const SHARED_CARD_STYLES = `
|
|
30
|
-
/* Monospace acronym badge */
|
|
31
|
-
.skhema-acronym-badge {
|
|
32
|
-
display: inline-flex;
|
|
33
|
-
align-items: center;
|
|
34
|
-
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
|
|
35
|
-
font-size: 10px;
|
|
36
|
-
font-weight: 600;
|
|
37
|
-
padding: 2px 6px;
|
|
38
|
-
border-radius: 2px;
|
|
39
|
-
letter-spacing: 0.02em;
|
|
40
|
-
flex-shrink: 0;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/* Footer attribution tagline */
|
|
44
|
-
.skhema-footer-attribution {
|
|
45
|
-
font-size: 11px;
|
|
46
|
-
color: var(--skhema-text-muted);
|
|
47
|
-
line-height: 1.4;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.skhema-footer-attribution a {
|
|
51
|
-
color: var(--skhema-text-muted);
|
|
52
|
-
text-decoration: underline;
|
|
53
|
-
text-decoration-color: var(--skhema-border);
|
|
54
|
-
text-underline-offset: 2px;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.skhema-footer-attribution a:hover {
|
|
58
|
-
color: var(--skhema-text);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/* Contributor line in footer */
|
|
62
|
-
.skhema-contributor-line {
|
|
63
|
-
display: flex;
|
|
64
|
-
align-items: center;
|
|
65
|
-
gap: 6px;
|
|
66
|
-
font-size: 12px;
|
|
67
|
-
color: var(--skhema-text-muted);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.skhema-contributor-line svg {
|
|
71
|
-
width: 14px;
|
|
72
|
-
height: 14px;
|
|
73
|
-
flex-shrink: 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/* Save button — primary brand color */
|
|
77
|
-
.skhema-save-btn {
|
|
78
|
-
display: inline-flex;
|
|
79
|
-
align-items: center;
|
|
80
|
-
gap: 6px;
|
|
81
|
-
background: var(--skhema-primary);
|
|
82
|
-
color: white;
|
|
83
|
-
border: none;
|
|
84
|
-
padding: 6px 14px;
|
|
85
|
-
border-radius: calc(var(--skhema-radius) + 2px);
|
|
86
|
-
font-size: 12px;
|
|
87
|
-
font-weight: 500;
|
|
88
|
-
text-decoration: none;
|
|
89
|
-
cursor: pointer;
|
|
90
|
-
transition: background 0.15s ease;
|
|
91
|
-
white-space: nowrap;
|
|
1
|
+
import { d as getElementTypeLabel, b as getComponentTypeLabel, i as isValidComponentType, v as validateElementBelongsToComponent, e as getElementTypesForComponent, g as getComponentTypeAcronym, a as COMPONENT_COLORS, S as SHARED_CARD_STYLES, U as USER_ICON_SVG, h as validateAttributes, r as resolveComponentType } from "./validation-MSiRF5Wt.js";
|
|
2
|
+
import { c, f } from "./validation-MSiRF5Wt.js";
|
|
3
|
+
function readAuthorAttribution(element) {
|
|
4
|
+
const authorName = element.getAttribute("author-name") || element.getAttribute("contributor-name");
|
|
5
|
+
if (!authorName?.trim()) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const authorSlug = element.getAttribute("author-slug")?.trim();
|
|
9
|
+
return {
|
|
10
|
+
authorName: authorName.trim(),
|
|
11
|
+
authorSlug: authorSlug || void 0
|
|
12
|
+
};
|
|
92
13
|
}
|
|
93
|
-
|
|
94
|
-
.
|
|
95
|
-
background: var(--skhema-primary-hover);
|
|
14
|
+
function escapeHtml(text) {
|
|
15
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
96
16
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
17
|
+
function formatAuthorAttributionHtml(authorName, authorSlug) {
|
|
18
|
+
const label = `By ${escapeHtml(authorName)}`;
|
|
19
|
+
if (authorSlug) {
|
|
20
|
+
return `<a href="https://skhema.com/contributors/${encodeURIComponent(authorSlug)}" class="skhema-author-link" target="_blank" rel="noopener noreferrer">${label}</a>`;
|
|
21
|
+
}
|
|
22
|
+
return `<span class="skhema-author-text">${label}</span>`;
|
|
100
23
|
}
|
|
101
|
-
|
|
102
|
-
.
|
|
103
|
-
outline: 2px solid var(--skhema-primary);
|
|
104
|
-
outline-offset: 2px;
|
|
24
|
+
function formatContributorIdFallback(contributorId) {
|
|
25
|
+
return contributorId.split(/[_-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
105
26
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
27
|
+
function resolveAuthorFooterHtml(element, contributorId) {
|
|
28
|
+
const attribution = readAuthorAttribution(element);
|
|
29
|
+
if (attribution) {
|
|
30
|
+
return formatAuthorAttributionHtml(
|
|
31
|
+
attribution.authorName,
|
|
32
|
+
attribution.authorSlug
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return `<span class="skhema-author-text">By ${escapeHtml(formatContributorIdFallback(contributorId))}</span>`;
|
|
110
36
|
}
|
|
111
|
-
`;
|
|
112
|
-
const USER_ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>`;
|
|
113
37
|
const ANALYTICS_ENDPOINT = "https://analytics.skhema.com/functions/v1/embed-manage";
|
|
114
38
|
const TRACKING_COOKIE_NAME = "_sk";
|
|
115
39
|
const TRACKING_EXPIRY_HOURS = 24;
|
|
@@ -483,43 +407,6 @@ function shouldTrackAnalytics(element) {
|
|
|
483
407
|
const trackAnalytics = element.getAttribute("track-analytics");
|
|
484
408
|
return trackAnalytics !== "false";
|
|
485
409
|
}
|
|
486
|
-
function isValidComponentType(componentType) {
|
|
487
|
-
const validTypes = Object.values(COMPONENT_TYPES).map((t) => t.value);
|
|
488
|
-
return validTypes.includes(componentType);
|
|
489
|
-
}
|
|
490
|
-
function validateElementBelongsToComponent(elementType, componentType) {
|
|
491
|
-
if (!isValidComponentType(componentType)) return false;
|
|
492
|
-
const validElements = SKHEMA_MAPPING.elementFlow[componentType];
|
|
493
|
-
if (!validElements) return false;
|
|
494
|
-
return validElements.some((e) => e.value === elementType);
|
|
495
|
-
}
|
|
496
|
-
function getComponentTypeLabel(componentType) {
|
|
497
|
-
const type = Object.values(COMPONENT_TYPES).find(
|
|
498
|
-
(t) => t.value === componentType
|
|
499
|
-
);
|
|
500
|
-
return type?.label || componentType;
|
|
501
|
-
}
|
|
502
|
-
function getComponentTypeAcronym(componentType) {
|
|
503
|
-
const type = Object.values(COMPONENT_TYPES).find(
|
|
504
|
-
(t) => t.value === componentType
|
|
505
|
-
);
|
|
506
|
-
return type?.acronym || componentType.substring(0, 2).toUpperCase();
|
|
507
|
-
}
|
|
508
|
-
function resolveComponentType(elementType) {
|
|
509
|
-
for (const [componentValue, elements] of Object.entries(
|
|
510
|
-
SKHEMA_MAPPING.elementFlow
|
|
511
|
-
)) {
|
|
512
|
-
if (elements.some((e) => e.value === elementType)) {
|
|
513
|
-
return componentValue;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
return "diagnosis";
|
|
517
|
-
}
|
|
518
|
-
function getElementTypesForComponent(componentType) {
|
|
519
|
-
if (!isValidComponentType(componentType)) return [];
|
|
520
|
-
const elements = SKHEMA_MAPPING.elementFlow[componentType];
|
|
521
|
-
return elements?.map((e) => e.value) || [];
|
|
522
|
-
}
|
|
523
410
|
function generateContentHash(content) {
|
|
524
411
|
let hash = 0;
|
|
525
412
|
const cleanContent = content.trim().substring(0, 200);
|
|
@@ -608,42 +495,6 @@ function validateContentSecurity(content) {
|
|
|
608
495
|
issues
|
|
609
496
|
};
|
|
610
497
|
}
|
|
611
|
-
function isValidElementType(elementType) {
|
|
612
|
-
const validTypes = Object.values(ELEMENT_TYPES).map((type) => type.value);
|
|
613
|
-
return validTypes.includes(elementType);
|
|
614
|
-
}
|
|
615
|
-
function validateAttributes(element) {
|
|
616
|
-
const errors = [];
|
|
617
|
-
const elementType = element.getAttribute("element-type");
|
|
618
|
-
const contributorId = element.getAttribute("contributor-id");
|
|
619
|
-
if (!elementType) {
|
|
620
|
-
errors.push("Missing required attribute: element-type");
|
|
621
|
-
} else if (!isValidElementType(elementType)) {
|
|
622
|
-
const validTypes = Object.values(ELEMENT_TYPES).map((t) => t.value).join(", ");
|
|
623
|
-
errors.push(
|
|
624
|
-
`Invalid element-type "${elementType}". Valid types: ${validTypes}`
|
|
625
|
-
);
|
|
626
|
-
}
|
|
627
|
-
if (!contributorId) {
|
|
628
|
-
errors.push("Missing required attribute: contributor-id");
|
|
629
|
-
} else if (contributorId.trim().length === 0) {
|
|
630
|
-
errors.push("contributor-id cannot be empty");
|
|
631
|
-
}
|
|
632
|
-
return {
|
|
633
|
-
isValid: errors.length === 0,
|
|
634
|
-
errors,
|
|
635
|
-
elementType: isValidElementType(elementType || "") ? elementType : void 0,
|
|
636
|
-
contributorId: contributorId || void 0
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
function getElementTypeLabel(elementType) {
|
|
640
|
-
const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
641
|
-
return type?.label || elementType;
|
|
642
|
-
}
|
|
643
|
-
function getElementTypeAcronym(elementType) {
|
|
644
|
-
const type = Object.values(ELEMENT_TYPES).find((t) => t.value === elementType);
|
|
645
|
-
return type?.acronym || elementType.substring(0, 2).toUpperCase();
|
|
646
|
-
}
|
|
647
498
|
function generateStructuredData(content, elementType, contributorId, sourceUrl) {
|
|
648
499
|
return {
|
|
649
500
|
"@context": "https://schema.org",
|
|
@@ -1029,6 +880,8 @@ class SkhemaComponent extends HTMLElement {
|
|
|
1029
880
|
return [
|
|
1030
881
|
"component-type",
|
|
1031
882
|
"contributor-id",
|
|
883
|
+
"author-name",
|
|
884
|
+
"author-slug",
|
|
1032
885
|
"contributor-name",
|
|
1033
886
|
"title",
|
|
1034
887
|
"theme",
|
|
@@ -1169,8 +1022,7 @@ class SkhemaComponent extends HTMLElement {
|
|
|
1169
1022
|
const componentLabel = getComponentTypeLabel(component_type);
|
|
1170
1023
|
const acronym = getComponentTypeAcronym(component_type);
|
|
1171
1024
|
const colors = COMPONENT_COLORS[component_type];
|
|
1172
|
-
const
|
|
1173
|
-
const displayName = contributorName || this.formatContributorName(contributor_id);
|
|
1025
|
+
const authorFooterHtml = resolveAuthorFooterHtml(this, contributor_id);
|
|
1174
1026
|
const themeAttribute = this.getAttribute("theme") || "auto";
|
|
1175
1027
|
const actualTheme = this.getActualTheme(themeAttribute);
|
|
1176
1028
|
const redirectUrl = generateComponentRedirectUrl(
|
|
@@ -1219,7 +1071,7 @@ class SkhemaComponent extends HTMLElement {
|
|
|
1219
1071
|
<div class="skhema-footer-row">
|
|
1220
1072
|
<span class="skhema-contributor-line">
|
|
1221
1073
|
${USER_ICON_SVG}
|
|
1222
|
-
${
|
|
1074
|
+
${authorFooterHtml}
|
|
1223
1075
|
</span>
|
|
1224
1076
|
<a href="${redirectUrl}"
|
|
1225
1077
|
class="skhema-save-btn"
|
|
@@ -1283,9 +1135,6 @@ class SkhemaComponent extends HTMLElement {
|
|
|
1283
1135
|
}
|
|
1284
1136
|
return "light";
|
|
1285
1137
|
}
|
|
1286
|
-
formatContributorName(contributorId) {
|
|
1287
|
-
return contributorId.split(/[_-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
1288
|
-
}
|
|
1289
1138
|
addPreconnectHints() {
|
|
1290
1139
|
if (document.querySelector(
|
|
1291
1140
|
'link[rel="preconnect"][href*="analytics.skhema.com"]'
|
|
@@ -1728,6 +1577,8 @@ class SkhemaElement extends HTMLElement {
|
|
|
1728
1577
|
return [
|
|
1729
1578
|
"element-type",
|
|
1730
1579
|
"contributor-id",
|
|
1580
|
+
"author-name",
|
|
1581
|
+
"author-slug",
|
|
1731
1582
|
"contributor-name",
|
|
1732
1583
|
"content",
|
|
1733
1584
|
"source-url",
|
|
@@ -1849,8 +1700,7 @@ class SkhemaElement extends HTMLElement {
|
|
|
1849
1700
|
);
|
|
1850
1701
|
const themeAttribute = this.getAttribute("theme") || "auto";
|
|
1851
1702
|
const actualTheme = this.getActualTheme(themeAttribute);
|
|
1852
|
-
const
|
|
1853
|
-
const displayName = contributorName || this.formatContributorName(contributor_id);
|
|
1703
|
+
const authorFooterHtml = resolveAuthorFooterHtml(this, contributor_id);
|
|
1854
1704
|
const componentType = resolveComponentType(element_type);
|
|
1855
1705
|
const acronym = getComponentTypeAcronym(componentType);
|
|
1856
1706
|
const colors = COMPONENT_COLORS[componentType];
|
|
@@ -1878,7 +1728,7 @@ class SkhemaElement extends HTMLElement {
|
|
|
1878
1728
|
<div class="skhema-footer-row">
|
|
1879
1729
|
<span class="skhema-contributor-line">
|
|
1880
1730
|
${USER_ICON_SVG}
|
|
1881
|
-
${
|
|
1731
|
+
${authorFooterHtml}
|
|
1882
1732
|
</span>
|
|
1883
1733
|
<a href="${redirectUrl}"
|
|
1884
1734
|
class="skhema-save-btn"
|
|
@@ -1925,9 +1775,6 @@ class SkhemaElement extends HTMLElement {
|
|
|
1925
1775
|
}
|
|
1926
1776
|
return "light";
|
|
1927
1777
|
}
|
|
1928
|
-
formatContributorName(contributorId) {
|
|
1929
|
-
return contributorId.split(/[_-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
1930
|
-
}
|
|
1931
1778
|
addPreconnectHints() {
|
|
1932
1779
|
if (document.querySelector(
|
|
1933
1780
|
'link[rel="preconnect"][href*="analytics.skhema.com"]'
|
|
@@ -2134,10 +1981,10 @@ export {
|
|
|
2134
1981
|
generateStructuredData,
|
|
2135
1982
|
getComponentTypeAcronym,
|
|
2136
1983
|
getComponentTypeLabel,
|
|
2137
|
-
getElementTypeAcronym,
|
|
1984
|
+
c as getElementTypeAcronym,
|
|
2138
1985
|
getElementTypeLabel,
|
|
2139
1986
|
isValidComponentType,
|
|
2140
|
-
isValidElementType,
|
|
1987
|
+
f as isValidElementType,
|
|
2141
1988
|
registerSkhemaComponent,
|
|
2142
1989
|
registerSkhemaElement,
|
|
2143
1990
|
resolveComponentType,
|