@lukso/web-components 1.180.1 → 1.182.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.
@@ -682,6 +682,15 @@ exports.LuksoIcon = class LuksoIcon extends index.TailwindStyledElement(style) {
682
682
  }
683
683
  }
684
684
  }
685
+ /**
686
+ * Wrap a color token so --lukso-icon-color (or --lukso-icon-secondary-color)
687
+ * takes precedence when set, falling back to the original token.
688
+ * Icon SVGs render: var(--<returned string>)
689
+ * Result: var(--lukso-icon-color, var(--neutral-20))
690
+ */
691
+ wrapColor(token, cssVar) {
692
+ return `${cssVar}, var(--${token})`;
693
+ }
685
694
  render() {
686
695
  if (!this.color) {
687
696
  this.color = DEFAULT_COLOR;
@@ -694,6 +703,8 @@ exports.LuksoIcon = class LuksoIcon extends index.TailwindStyledElement(style) {
694
703
  console.warn(`Size ${this.size} not found`);
695
704
  return lit.html``;
696
705
  }
706
+ const color = this.wrapColor(this.color, "lukso-icon-color");
707
+ const secondaryColor = this.secondaryColor ? this.wrapColor(this.secondaryColor, "lukso-icon-secondary-color") : void 0;
697
708
  if (this.pack === "vuesax") {
698
709
  if (!this.svgContent) {
699
710
  if (!this.failedLoadAttempt) {
@@ -721,9 +732,9 @@ exports.LuksoIcon = class LuksoIcon extends index.TailwindStyledElement(style) {
721
732
  ${icon({
722
733
  width: size.width,
723
734
  height: size.height,
724
- color: this.color,
735
+ color,
725
736
  strokeWidth: size.strokeWidth,
726
- secondaryColor: this.secondaryColor
737
+ secondaryColor
727
738
  })}
728
739
  `;
729
740
  }
@@ -33,6 +33,13 @@ export declare class LuksoIcon extends LuksoIcon_base {
33
33
  private processVuesaxSvg;
34
34
  willUpdate(changedProperties: PropertyValueMap<this>): void;
35
35
  updated(changedProperties: PropertyValueMap<this>): Promise<void>;
36
+ /**
37
+ * Wrap a color token so --lukso-icon-color (or --lukso-icon-secondary-color)
38
+ * takes precedence when set, falling back to the original token.
39
+ * Icon SVGs render: var(--<returned string>)
40
+ * Result: var(--lukso-icon-color, var(--neutral-20))
41
+ */
42
+ private wrapColor;
36
43
  render(): import('lit-html').TemplateResult<1>;
37
44
  }
38
45
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/lukso-icon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAiQjD,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,UAAU,CAAA;AAEd,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3C,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,MAAM,GACN,SAAS,GACT,QAAQ,GACR,MAAM,GACN,SAAS,CAAA;;AA2Qb,qBACa,SAAU,SAAQ,cAA4B;IAEzD,IAAI,MAAY;IAGhB,IAAI,EAAE,QAAQ,CAAe;IAG7B,KAAK,SAAgB;IAGrB,cAAc,MAAY;IAG1B,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAY;IAGtC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAY;IAG5C,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAQ;IAEjC,OAAO,CAAC,KAAK,CA+BZ;IAID,OAAO,CAAC,UAAU,CAGhB;IAEF;;;;;;;;OAQG;YACW,OAAO;IAsCrB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAmExB,UAAU,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAS9C,OAAO,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,IAAI,CAAC;IA8CvD,MAAM;CAkEP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAA;KACxB;CACF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/lukso-icon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAiQjD,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,UAAU,CAAA;AAEd,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3C,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,MAAM,GACN,SAAS,GACT,QAAQ,GACR,MAAM,GACN,SAAS,CAAA;;AA2Qb,qBACa,SAAU,SAAQ,cAA4B;IAEzD,IAAI,MAAY;IAGhB,IAAI,EAAE,QAAQ,CAAe;IAG7B,KAAK,SAAgB;IAGrB,cAAc,MAAY;IAG1B,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAY;IAGtC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAY;IAG5C,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAQ;IAEjC,OAAO,CAAC,KAAK,CA+BZ;IAID,OAAO,CAAC,UAAU,CAGhB;IAEF;;;;;;;;OAQG;YACW,OAAO;IAsCrB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAmExB,UAAU,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,IAAI,CAAC;IAS9C,OAAO,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,IAAI,CAAC;IA8CvD;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAMjB,MAAM;CAyEP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAA;KACxB;CACF"}
@@ -676,6 +676,15 @@ let LuksoIcon = class extends TailwindStyledElement(style) {
676
676
  }
677
677
  }
678
678
  }
679
+ /**
680
+ * Wrap a color token so --lukso-icon-color (or --lukso-icon-secondary-color)
681
+ * takes precedence when set, falling back to the original token.
682
+ * Icon SVGs render: var(--<returned string>)
683
+ * Result: var(--lukso-icon-color, var(--neutral-20))
684
+ */
685
+ wrapColor(token, cssVar) {
686
+ return `${cssVar}, var(--${token})`;
687
+ }
679
688
  render() {
680
689
  if (!this.color) {
681
690
  this.color = DEFAULT_COLOR;
@@ -688,6 +697,8 @@ let LuksoIcon = class extends TailwindStyledElement(style) {
688
697
  console.warn(`Size ${this.size} not found`);
689
698
  return html``;
690
699
  }
700
+ const color = this.wrapColor(this.color, "lukso-icon-color");
701
+ const secondaryColor = this.secondaryColor ? this.wrapColor(this.secondaryColor, "lukso-icon-secondary-color") : void 0;
691
702
  if (this.pack === "vuesax") {
692
703
  if (!this.svgContent) {
693
704
  if (!this.failedLoadAttempt) {
@@ -715,9 +726,9 @@ let LuksoIcon = class extends TailwindStyledElement(style) {
715
726
  ${icon({
716
727
  width: size.width,
717
728
  height: size.height,
718
- color: this.color,
729
+ color,
719
730
  strokeWidth: size.strokeWidth,
720
- secondaryColor: this.secondaryColor
731
+ secondaryColor
721
732
  })}
722
733
  `;
723
734
  }
@@ -43,4 +43,6 @@ export declare const VuesaxBoldIcon: StoryObj;
43
43
  export declare const VuesaxColoredIcon: StoryObj;
44
44
  /** Test story for Vuesax large icon */
45
45
  export declare const VuesaxLargeIcon: StoryObj;
46
+ /** Test story for CSS variable override on lukso pack icon */
47
+ export declare const CSSVariableOverride: StoryObj;
46
48
  //# sourceMappingURL=lukso-icon.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lukso-icon.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/lukso-icon/lukso-icon.stories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,SAAS,CAAA;AAEhB;;;GAGG;AACH,QAAA,MAAM,IAAI,EAAE,IA8FX,CAAA;AAED,eAAe,IAAI,CAAA;AAqBnB,yFAAyF;AACzF,eAAO,MAAM,WAAW,KAAoB,CAAA;AAE5C,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAoB,CAAA;AAK3C,iDAAiD;AACjD,eAAO,MAAM,SAAS,KAAoB,CAAA;AAK1C,iDAAiD;AACjD,eAAO,MAAM,SAAS,KAAoB,CAAA;AAK1C,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAoB,CAAA;AAK3C,oDAAoD;AACpD,eAAO,MAAM,WAAW,KAAoB,CAAA;AAK5C,0EAA0E;AAC1E,eAAO,MAAM,eAAe,KAAoB,CAAA;AAKhD,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,KAAoB,CAAA;AAOnD,qHAAqH;AACrH,eAAO,MAAM,WAAW,KAAoB,CAAA;AAK5C,uKAAuK;AACvK,eAAO,MAAM,YAAY,KAAoB,CAAA;AAO7C,6CAA6C;AAC7C,eAAO,MAAM,cAAc,KAAoB,CAAA;AAO/C,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,4CAS9B,CAAA;AACD,yCAAyC;AACzC,eAAO,MAAM,QAAQ,EAAE,QAsBtB,CAAA;AAED,4CAA4C;AAC5C,eAAO,MAAM,eAAe,EAAE,QAuB7B,CAAA;AAED,0CAA0C;AAC1C,eAAO,MAAM,aAAa,EAAE,QAuB3B,CAAA;AAED,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,EAAE,QAuB9B,CAAA;AAED,sCAAsC;AACtC,eAAO,MAAM,cAAc,EAAE,QAwB5B,CAAA;AAED,yCAAyC;AACzC,eAAO,MAAM,iBAAiB,EAAE,QAwB/B,CAAA;AAED,uCAAuC;AACvC,eAAO,MAAM,eAAe,EAAE,QAwB7B,CAAA"}
1
+ {"version":3,"file":"lukso-icon.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/lukso-icon/lukso-icon.stories.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AAEpE,OAAO,SAAS,CAAA;AAEhB;;;GAGG;AACH,QAAA,MAAM,IAAI,EAAE,IA8FX,CAAA;AAED,eAAe,IAAI,CAAA;AAqBnB,yFAAyF;AACzF,eAAO,MAAM,WAAW,KAAoB,CAAA;AAE5C,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAoB,CAAA;AAK3C,iDAAiD;AACjD,eAAO,MAAM,SAAS,KAAoB,CAAA;AAK1C,iDAAiD;AACjD,eAAO,MAAM,SAAS,KAAoB,CAAA;AAK1C,mDAAmD;AACnD,eAAO,MAAM,UAAU,KAAoB,CAAA;AAK3C,oDAAoD;AACpD,eAAO,MAAM,WAAW,KAAoB,CAAA;AAK5C,0EAA0E;AAC1E,eAAO,MAAM,eAAe,KAAoB,CAAA;AAKhD,0FAA0F;AAC1F,eAAO,MAAM,kBAAkB,KAAoB,CAAA;AAOnD,qHAAqH;AACrH,eAAO,MAAM,WAAW,KAAoB,CAAA;AAK5C,uKAAuK;AACvK,eAAO,MAAM,YAAY,KAAoB,CAAA;AAO7C,6CAA6C;AAC7C,eAAO,MAAM,cAAc,KAAoB,CAAA;AAO/C,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,4CAS9B,CAAA;AACD,yCAAyC;AACzC,eAAO,MAAM,QAAQ,EAAE,QAsBtB,CAAA;AAED,4CAA4C;AAC5C,eAAO,MAAM,eAAe,EAAE,QAuB7B,CAAA;AAED,0CAA0C;AAC1C,eAAO,MAAM,aAAa,EAAE,QAuB3B,CAAA;AAED,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,EAAE,QAuB9B,CAAA;AAED,sCAAsC;AACtC,eAAO,MAAM,cAAc,EAAE,QAwB5B,CAAA;AAED,yCAAyC;AACzC,eAAO,MAAM,iBAAiB,EAAE,QAwB/B,CAAA;AAED,uCAAuC;AACvC,eAAO,MAAM,eAAe,EAAE,QAwB7B,CAAA;AAED,8DAA8D;AAC9D,eAAO,MAAM,mBAAmB,EAAE,QAqBjC,CAAA"}
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const style = "/**\n * backdrop-filter must be applied at :host level (Light DOM) because it cannot blur content\n * across the Shadow DOM boundary. pointer-events: none allows backdrop clicks while children remain interactive.\n */\n:host([is-open]) {\n position: fixed !important;\n inset: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n z-index: 1011 !important;\n backdrop-filter: blur(8px) !important;\n background: rgb(196 202 206 / 60%) !important;\n pointer-events: none !important;\n}\n\n/* Light theme backdrop */\n:host([is-open]:not([theme='dark'])) {\n background: rgb(196 202 206 / 60%) !important;\n}\n\n/* Dark theme backdrop with reduced opacity */\n:host([is-open][theme='dark']) {\n background: rgb(196 202 206 / 10%) !important;\n}\n\n/* Re-enable pointer events for modal content */\n:host([is-open]) > * {\n pointer-events: auto !important;\n}\n\n/* Dialog panel custom properties — defaults are inlined as var() fallbacks\n so inherited values from parent elements are not blocked by :host. */\n:host(:not([theme='dark'])) {\n --lukso-modal-resolved-bg: var(--lukso-modal-bg, #f8fafb); /* neutral-98 */\n}\n\n:host([theme='dark']) {\n --lukso-modal-resolved-bg: var(\n --lukso-modal-dark-bg,\n #121b21\n ); /* neutral-10 */\n}\n";
3
+ const style = "/**\n * backdrop-filter must be applied at :host level (Light DOM) because it cannot blur content\n * across the Shadow DOM boundary. pointer-events: none allows backdrop clicks while children remain interactive.\n */\n:host([is-open]) {\n position: fixed !important;\n inset: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n z-index: 1011 !important;\n backdrop-filter: blur(8px) !important;\n background: rgb(196 202 206 / 60%) !important;\n pointer-events: none !important;\n}\n\n/* Light theme backdrop */\n:host([is-open]:not([theme='dark'])) {\n background: rgb(196 202 206 / 60%) !important;\n}\n\n/* Dark theme backdrop with reduced opacity */\n:host([is-open][theme='dark']) {\n background: rgb(196 202 206 / 10%) !important;\n}\n\n/* Re-enable pointer events for modal content */\n:host([is-open]) > * {\n pointer-events: auto !important;\n}\n\n/* Dialog panel custom properties — defaults are inlined as var() fallbacks\n so inherited values from parent elements are not blocked by :host. */\n:host(:not([theme='dark'])) {\n --lukso-modal-resolved-bg: var(--lukso-modal-bg, #f8fafb); /* neutral-98 */\n}\n\n:host([theme='dark']) {\n --lukso-modal-resolved-bg: var(\n --lukso-modal-dark-bg,\n var(--lukso-modal-bg, #121b21)\n ); /* neutral-10 */\n}\n";
4
4
 
5
5
  module.exports = style;
@@ -1,3 +1,3 @@
1
- const style = "/**\n * backdrop-filter must be applied at :host level (Light DOM) because it cannot blur content\n * across the Shadow DOM boundary. pointer-events: none allows backdrop clicks while children remain interactive.\n */\n:host([is-open]) {\n position: fixed !important;\n inset: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n z-index: 1011 !important;\n backdrop-filter: blur(8px) !important;\n background: rgb(196 202 206 / 60%) !important;\n pointer-events: none !important;\n}\n\n/* Light theme backdrop */\n:host([is-open]:not([theme='dark'])) {\n background: rgb(196 202 206 / 60%) !important;\n}\n\n/* Dark theme backdrop with reduced opacity */\n:host([is-open][theme='dark']) {\n background: rgb(196 202 206 / 10%) !important;\n}\n\n/* Re-enable pointer events for modal content */\n:host([is-open]) > * {\n pointer-events: auto !important;\n}\n\n/* Dialog panel custom properties — defaults are inlined as var() fallbacks\n so inherited values from parent elements are not blocked by :host. */\n:host(:not([theme='dark'])) {\n --lukso-modal-resolved-bg: var(--lukso-modal-bg, #f8fafb); /* neutral-98 */\n}\n\n:host([theme='dark']) {\n --lukso-modal-resolved-bg: var(\n --lukso-modal-dark-bg,\n #121b21\n ); /* neutral-10 */\n}\n";
1
+ const style = "/**\n * backdrop-filter must be applied at :host level (Light DOM) because it cannot blur content\n * across the Shadow DOM boundary. pointer-events: none allows backdrop clicks while children remain interactive.\n */\n:host([is-open]) {\n position: fixed !important;\n inset: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n z-index: 1011 !important;\n backdrop-filter: blur(8px) !important;\n background: rgb(196 202 206 / 60%) !important;\n pointer-events: none !important;\n}\n\n/* Light theme backdrop */\n:host([is-open]:not([theme='dark'])) {\n background: rgb(196 202 206 / 60%) !important;\n}\n\n/* Dark theme backdrop with reduced opacity */\n:host([is-open][theme='dark']) {\n background: rgb(196 202 206 / 10%) !important;\n}\n\n/* Re-enable pointer events for modal content */\n:host([is-open]) > * {\n pointer-events: auto !important;\n}\n\n/* Dialog panel custom properties — defaults are inlined as var() fallbacks\n so inherited values from parent elements are not blocked by :host. */\n:host(:not([theme='dark'])) {\n --lukso-modal-resolved-bg: var(--lukso-modal-bg, #f8fafb); /* neutral-98 */\n}\n\n:host([theme='dark']) {\n --lukso-modal-resolved-bg: var(\n --lukso-modal-dark-bg,\n var(--lukso-modal-bg, #121b21)\n ); /* neutral-10 */\n}\n";
2
2
 
3
3
  export { style as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukso/web-components",
3
- "version": "1.180.1",
3
+ "version": "1.182.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -1,8 +1,98 @@
1
1
  /**
2
- * Detect social media from a given URL
2
+ * Social media detection with profile vs post classification.
3
3
  *
4
- * @param url
5
- * @returns
4
+ * Each platform has a list of domains and an optional `postPattern` regex
5
+ * that matches the URL pathname for individual content (posts, videos, etc.).
6
+ * If the pathname matches `postPattern`, type is 'post'; otherwise 'profile'.
7
+ *
8
+ * Post patterns per platform:
9
+ *
10
+ * | Platform | Post patterns | Example post URL |
11
+ * |-------------|--------------------------------------------------------|-------------------------------------------|
12
+ * | Instagram | /p/<id>, /reel/<id>, /stories/<user>/<id> | instagram.com/p/ABC123 |
13
+ * | YouTube | /watch, /shorts/<id>, /live/<id>, /embed/<id>, | youtube.com/watch?v=xyz |
14
+ * | | youtu.be/<videoId> | youtu.be/dQw4w9WgXcQ |
15
+ * | X/Twitter | /<user>/status/<id> | x.com/user/status/123 |
16
+ * | Facebook | /photo, /video, /posts/<id>, /watch, /reel, /share | facebook.com/user/posts/123 |
17
+ * | TikTok | /<user>/video/<id> | tiktok.com/@user/video/123 |
18
+ * | LinkedIn | /posts/<id>, /pulse/<slug>, /feed/update/ | linkedin.com/posts/user_123 |
19
+ * | Medium | path ending with -<12+ hex chars> | medium.com/@user/article-abc123def456 |
20
+ * | GitHub | /<user>/<repo> (2+ path segments) | github.com/lukso-network/tools |
21
+ * | Warpcast | /<user>/0x<hash> | warpcast.com/user/0xabc |
22
+ * | Spotify | /track/, /episode/, /album/ | open.spotify.com/track/xyz |
23
+ * | SoundCloud | /<user>/<track> (2 segments) | soundcloud.com/artist/song |
24
+ */
25
+ declare const SOCIAL_MEDIA: {
26
+ facebook: {
27
+ domains: string[];
28
+ postPattern: RegExp;
29
+ };
30
+ x: {
31
+ domains: string[];
32
+ postPattern: RegExp;
33
+ };
34
+ instagram: {
35
+ domains: string[];
36
+ postPattern: RegExp;
37
+ };
38
+ medium: {
39
+ domains: string[];
40
+ postPattern: RegExp;
41
+ };
42
+ discord: {
43
+ domains: string[];
44
+ };
45
+ snapchat: {
46
+ domains: string[];
47
+ };
48
+ whatsapp: {
49
+ domains: string[];
50
+ };
51
+ telegram: {
52
+ domains: string[];
53
+ };
54
+ linkedin: {
55
+ domains: string[];
56
+ postPattern: RegExp;
57
+ };
58
+ github: {
59
+ domains: string[];
60
+ postPattern: RegExp;
61
+ };
62
+ 'universal-page': {
63
+ domains: string[];
64
+ };
65
+ youtube: {
66
+ domains: string[];
67
+ postPattern: (host: string, pathname: string) => boolean;
68
+ };
69
+ spotify: {
70
+ domains: string[];
71
+ postPattern: RegExp;
72
+ };
73
+ soundcloud: {
74
+ domains: string[];
75
+ postPattern: RegExp;
76
+ };
77
+ warpcast: {
78
+ domains: string[];
79
+ postPattern: RegExp;
80
+ };
81
+ tiktok: {
82
+ domains: string[];
83
+ postPattern: RegExp;
84
+ };
85
+ };
86
+ /**
87
+ * Detect social media from a given URL and classify as profile or post.
88
+ *
89
+ * @param url - The URL to check
90
+ * @returns Object with `platform` and `type` ('profile' | 'post'), or undefined
6
91
  */
7
- export declare const detectSocialMedia: (url?: string) => string;
92
+ type SocialMediaPlatform = keyof typeof SOCIAL_MEDIA;
93
+ export declare const detectSocialMedia: (url?: string) => {
94
+ platform: SocialMediaPlatform;
95
+ type: "profile" | "post";
96
+ } | undefined;
97
+ export {};
8
98
  //# sourceMappingURL=detect-social-media.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detect-social-media.d.ts","sourceRoot":"","sources":["../../src/shared/tools/detect-social-media.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,WAqB7C,CAAA"}
1
+ {"version":3,"file":"detect-social-media.d.ts","sourceRoot":"","sources":["../../src/shared/tools/detect-social-media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA0CM,MAAM,YAAY,MAAM;;;;;;;;;;;;;;;;;;CAqBJ,CAAA;AAE5C;;;;;GAKG;AACH,KAAK,mBAAmB,GAAG,MAAM,OAAO,YAAY,CAAA;AAEpD,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,KACX;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAA;CAAE,GAAG,SA2BhE,CAAA"}
package/tools/index.cjs CHANGED
@@ -24,36 +24,82 @@ const sliceAddress = (address, startSliceBy = 6, endSliceBy) => {
24
24
  };
25
25
 
26
26
  const SOCIAL_MEDIA = {
27
- facebook: ["facebook.com", "messenger.com", "fb.com", "fb.me"],
28
- x: ["x.com", "twitter.com", "t.co"],
29
- instagram: ["instagram.com"],
30
- medium: ["medium.com"],
31
- discord: ["discord.com", "discordapp.com", "discord.gg"],
32
- snapchat: ["snapchat.com"],
33
- whatsapp: ["whatsapp.com", "wa.me"],
34
- telegram: ["telegram.com", "t.me", "telegram.org"],
35
- linkedin: ["linkedin.com"],
36
- github: ["github.com"],
37
- "universal-page": ["universal.page"],
38
- youtube: ["youtube.com", "youtu.be", "youtube-nocookie.com"],
39
- spotify: ["spotify.com", "open.spotify.com"],
40
- soundcloud: ["soundcloud.com"],
41
- warpcast: ["warpcast.com"],
42
- tiktok: ["tiktok.com"]
27
+ facebook: {
28
+ domains: ["facebook.com", "messenger.com", "fb.com", "fb.me"],
29
+ postPattern: /^\/(photo|video|watch|reel|share|.+\/posts\/|.+\/videos\/)/i
30
+ },
31
+ x: {
32
+ domains: ["x.com", "twitter.com", "t.co"],
33
+ postPattern: /^\/[^/]+\/status\//i
34
+ },
35
+ instagram: {
36
+ domains: ["instagram.com"],
37
+ postPattern: /^\/(p|reel|stories)\//i
38
+ },
39
+ medium: {
40
+ domains: ["medium.com"],
41
+ postPattern: /\/.*-[0-9a-f]{12,}/i
42
+ },
43
+ discord: {
44
+ domains: ["discord.com", "discordapp.com", "discord.gg"]
45
+ },
46
+ snapchat: {
47
+ domains: ["snapchat.com"]
48
+ },
49
+ whatsapp: {
50
+ domains: ["whatsapp.com", "wa.me"]
51
+ },
52
+ telegram: {
53
+ domains: ["telegram.com", "t.me", "telegram.org"]
54
+ },
55
+ linkedin: {
56
+ domains: ["linkedin.com"],
57
+ postPattern: /^\/(posts|pulse|feed\/update)\//i
58
+ },
59
+ github: {
60
+ domains: ["github.com"],
61
+ postPattern: /^\/[^/]+\/[^/]+/i
62
+ },
63
+ "universal-page": {
64
+ domains: ["universal.page"]
65
+ },
66
+ youtube: {
67
+ domains: ["youtube.com", "youtu.be", "youtube-nocookie.com"],
68
+ postPattern: (host, pathname) => host === "youtu.be" ? /^\/[A-Za-z0-9_-]+/.test(pathname) : /^\/(watch|shorts\/|live\/|embed\/)/i.test(pathname)
69
+ },
70
+ spotify: {
71
+ domains: ["spotify.com"],
72
+ postPattern: /^\/(track|episode|album)\//i
73
+ },
74
+ soundcloud: {
75
+ domains: ["soundcloud.com"],
76
+ postPattern: /^\/[^/]+\/[^/]+/i
77
+ },
78
+ warpcast: {
79
+ domains: ["warpcast.com"],
80
+ postPattern: /^\/[^/]+\/0x/i
81
+ },
82
+ tiktok: {
83
+ domains: ["tiktok.com"],
84
+ postPattern: /^\/@[^/]+\/video\//i
85
+ }
43
86
  };
44
87
  const detectSocialMedia = (url) => {
45
88
  if (!url) {
46
89
  return;
47
90
  }
48
91
  try {
49
- const hostname = new URL(url).hostname;
50
- for (const [key, domains] of Object.entries(SOCIAL_MEDIA)) {
51
- const hostnameFormatted = hostname.replace("www.", "");
92
+ const { hostname, pathname } = new URL(url);
93
+ const host = hostname.replace(/^www\./, "");
94
+ for (const [platform, { domains, postPattern }] of Object.entries(
95
+ SOCIAL_MEDIA
96
+ )) {
52
97
  const match = domains.some(
53
- (domain) => new RegExp(`\\b${domain}\\b`, "i").test(hostnameFormatted)
98
+ (domain) => host === domain || host.endsWith(`.${domain}`)
54
99
  );
55
100
  if (match) {
56
- return key;
101
+ const isPost = typeof postPattern === "function" ? postPattern(host, pathname) : postPattern?.test(pathname);
102
+ return { platform, type: isPost ? "post" : "profile" };
57
103
  }
58
104
  }
59
105
  } catch {
package/tools/index.js CHANGED
@@ -20,36 +20,82 @@ const sliceAddress = (address, startSliceBy = 6, endSliceBy) => {
20
20
  };
21
21
 
22
22
  const SOCIAL_MEDIA = {
23
- facebook: ["facebook.com", "messenger.com", "fb.com", "fb.me"],
24
- x: ["x.com", "twitter.com", "t.co"],
25
- instagram: ["instagram.com"],
26
- medium: ["medium.com"],
27
- discord: ["discord.com", "discordapp.com", "discord.gg"],
28
- snapchat: ["snapchat.com"],
29
- whatsapp: ["whatsapp.com", "wa.me"],
30
- telegram: ["telegram.com", "t.me", "telegram.org"],
31
- linkedin: ["linkedin.com"],
32
- github: ["github.com"],
33
- "universal-page": ["universal.page"],
34
- youtube: ["youtube.com", "youtu.be", "youtube-nocookie.com"],
35
- spotify: ["spotify.com", "open.spotify.com"],
36
- soundcloud: ["soundcloud.com"],
37
- warpcast: ["warpcast.com"],
38
- tiktok: ["tiktok.com"]
23
+ facebook: {
24
+ domains: ["facebook.com", "messenger.com", "fb.com", "fb.me"],
25
+ postPattern: /^\/(photo|video|watch|reel|share|.+\/posts\/|.+\/videos\/)/i
26
+ },
27
+ x: {
28
+ domains: ["x.com", "twitter.com", "t.co"],
29
+ postPattern: /^\/[^/]+\/status\//i
30
+ },
31
+ instagram: {
32
+ domains: ["instagram.com"],
33
+ postPattern: /^\/(p|reel|stories)\//i
34
+ },
35
+ medium: {
36
+ domains: ["medium.com"],
37
+ postPattern: /\/.*-[0-9a-f]{12,}/i
38
+ },
39
+ discord: {
40
+ domains: ["discord.com", "discordapp.com", "discord.gg"]
41
+ },
42
+ snapchat: {
43
+ domains: ["snapchat.com"]
44
+ },
45
+ whatsapp: {
46
+ domains: ["whatsapp.com", "wa.me"]
47
+ },
48
+ telegram: {
49
+ domains: ["telegram.com", "t.me", "telegram.org"]
50
+ },
51
+ linkedin: {
52
+ domains: ["linkedin.com"],
53
+ postPattern: /^\/(posts|pulse|feed\/update)\//i
54
+ },
55
+ github: {
56
+ domains: ["github.com"],
57
+ postPattern: /^\/[^/]+\/[^/]+/i
58
+ },
59
+ "universal-page": {
60
+ domains: ["universal.page"]
61
+ },
62
+ youtube: {
63
+ domains: ["youtube.com", "youtu.be", "youtube-nocookie.com"],
64
+ postPattern: (host, pathname) => host === "youtu.be" ? /^\/[A-Za-z0-9_-]+/.test(pathname) : /^\/(watch|shorts\/|live\/|embed\/)/i.test(pathname)
65
+ },
66
+ spotify: {
67
+ domains: ["spotify.com"],
68
+ postPattern: /^\/(track|episode|album)\//i
69
+ },
70
+ soundcloud: {
71
+ domains: ["soundcloud.com"],
72
+ postPattern: /^\/[^/]+\/[^/]+/i
73
+ },
74
+ warpcast: {
75
+ domains: ["warpcast.com"],
76
+ postPattern: /^\/[^/]+\/0x/i
77
+ },
78
+ tiktok: {
79
+ domains: ["tiktok.com"],
80
+ postPattern: /^\/@[^/]+\/video\//i
81
+ }
39
82
  };
40
83
  const detectSocialMedia = (url) => {
41
84
  if (!url) {
42
85
  return;
43
86
  }
44
87
  try {
45
- const hostname = new URL(url).hostname;
46
- for (const [key, domains] of Object.entries(SOCIAL_MEDIA)) {
47
- const hostnameFormatted = hostname.replace("www.", "");
88
+ const { hostname, pathname } = new URL(url);
89
+ const host = hostname.replace(/^www\./, "");
90
+ for (const [platform, { domains, postPattern }] of Object.entries(
91
+ SOCIAL_MEDIA
92
+ )) {
48
93
  const match = domains.some(
49
- (domain) => new RegExp(`\\b${domain}\\b`, "i").test(hostnameFormatted)
94
+ (domain) => host === domain || host.endsWith(`.${domain}`)
50
95
  );
51
96
  if (match) {
52
- return key;
97
+ const isPost = typeof postPattern === "function" ? postPattern(host, pathname) : postPattern?.test(pathname);
98
+ return { platform, type: isPost ? "post" : "profile" };
53
99
  }
54
100
  }
55
101
  } catch {