@myoc/excalidraw 0.20.1 → 0.21.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +253 -0
  2. package/dist/dev/{chunk-VBVJJWUO.js → chunk-A5GXRKT7.js} +24 -2
  3. package/dist/dev/chunk-A5GXRKT7.js.map +7 -0
  4. package/dist/dev/{chunk-6JJSWC4C.js → chunk-ETORD5CS.js} +41 -1
  5. package/dist/dev/{chunk-6JJSWC4C.js.map → chunk-ETORD5CS.js.map} +3 -3
  6. package/dist/dev/{chunk-EYSZ36MK.js → chunk-RCINQZKB.js} +2 -2
  7. package/dist/dev/{chunk-JBD373VY.js → chunk-TYPY4HGC.js} +374 -75
  8. package/dist/dev/chunk-TYPY4HGC.js.map +7 -0
  9. package/dist/dev/data/{image-KRZO2CVW.js → image-LHOOLEDU.js} +3 -3
  10. package/dist/dev/index.css +121 -0
  11. package/dist/dev/index.css.map +2 -2
  12. package/dist/dev/index.js +1911 -1513
  13. package/dist/dev/index.js.map +4 -4
  14. package/dist/dev/locales/{en-V2WTRX5T.js → en-5NWRTZ4G.js} +4 -2
  15. package/dist/dev/subset-shared.chunk.js +4 -2
  16. package/dist/dev/subset-worker.chunk.js +2 -2
  17. package/dist/prod/{chunk-THEEFQ4B.js → chunk-4M4QNZNP.js} +1 -1
  18. package/dist/prod/{chunk-MZBVWY5X.js → chunk-FX6OEDRJ.js} +4 -4
  19. package/dist/prod/chunk-UXMXN2SG.js +4 -0
  20. package/dist/prod/{chunk-Z5NKEFVG.js → chunk-VDR2JODW.js} +10 -10
  21. package/dist/prod/data/image-XO3VLL25.js +1 -0
  22. package/dist/prod/index.css +1 -1
  23. package/dist/prod/index.js +16 -16
  24. package/dist/prod/locales/en-3B3DKM74.js +1 -0
  25. package/dist/prod/subset-shared.chunk.js +1 -1
  26. package/dist/prod/subset-worker.chunk.js +1 -1
  27. package/dist/types/common/src/constants.d.ts +7 -2
  28. package/dist/types/common/src/font-metadata.d.ts +4 -2
  29. package/dist/types/element/src/types.d.ts +2 -2
  30. package/dist/types/excalidraw/appState.d.ts +1 -1
  31. package/dist/types/excalidraw/charts/charts.constants.d.ts +1 -1
  32. package/dist/types/excalidraw/components/FontPicker/FontPicker.d.ts +1 -1
  33. package/dist/types/excalidraw/components/FontPicker/FontPickerList.d.ts +15 -4
  34. package/dist/types/excalidraw/components/FontPicker/FontWeightPicker.d.ts +34 -0
  35. package/dist/types/excalidraw/components/FontPicker/keyboardNavHandlers.d.ts +3 -2
  36. package/dist/types/excalidraw/fonts/ExcalidrawFontFace.d.ts +2 -1
  37. package/dist/types/excalidraw/fonts/Fonts.d.ts +15 -4
  38. package/dist/types/excalidraw/fonts/googleFonts.d.ts +40 -0
  39. package/dist/types/excalidraw/index.d.ts +2 -1
  40. package/dist/types/excalidraw/subset/subset-main.d.ts +1 -0
  41. package/dist/types/excalidraw/subset/subset-shared.chunk.d.ts +1 -0
  42. package/dist/types/excalidraw/subset/woff2/fontMetrics.d.ts +8 -0
  43. package/dist/types/excalidraw/types.d.ts +42 -0
  44. package/package.json +4 -4
  45. package/dist/dev/chunk-JBD373VY.js.map +0 -7
  46. package/dist/dev/chunk-VBVJJWUO.js.map +0 -7
  47. package/dist/prod/chunk-CQHKTNJ6.js +0 -4
  48. package/dist/prod/data/image-3WH4CMOG.js +0 -1
  49. package/dist/prod/locales/en-ALU5NMSJ.js +0 -1
  50. /package/dist/dev/{chunk-EYSZ36MK.js.map → chunk-RCINQZKB.js.map} +0 -0
  51. /package/dist/dev/data/{image-KRZO2CVW.js.map → image-LHOOLEDU.js.map} +0 -0
  52. /package/dist/dev/locales/{en-V2WTRX5T.js.map → en-5NWRTZ4G.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  // <define:import.meta.env>
2
- var define_import_meta_env_default = { MODE: "development", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@myoc/excalidraw", PKG_VERSION: "0.20.0", DEV: true };
2
+ var define_import_meta_env_default = { MODE: "development", VITE_APP_BACKEND_V2_GET_URL: "https://json-dev.excalidraw.com/api/v2/", VITE_APP_BACKEND_V2_POST_URL: "https://json-dev.excalidraw.com/api/v2/post/", VITE_APP_LIBRARY_URL: "https://libraries.excalidraw.com", VITE_APP_LIBRARY_BACKEND: "https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries", VITE_APP_WS_SERVER_URL: "http://localhost:3002", VITE_APP_PLUS_LP: "https://plus.excalidraw.com", VITE_APP_PLUS_APP: "http://localhost:3000", VITE_APP_AI_BACKEND: "http://localhost:3016", VITE_APP_FIREBASE_CONFIG: '{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}', VITE_APP_DEV_DISABLE_LIVE_RELOAD: "", VITE_APP_ENABLE_TRACKING: "true", FAST_REFRESH: "false", VITE_APP_PORT: "3001", VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: "", VITE_APP_COLLAPSE_OVERLAY: "true", VITE_APP_ENABLE_ESLINT: "true", VITE_APP_ENABLE_PWA: "false", VITE_APP_PLUS_EXPORT_PUBLIC_KEY: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2g5T+Rub6Kbf1Mf57t0\n7r2zeHuVg4dla3r5ryXMswtzz6x767octl6oLThn33mQsPSy3GKglFZoCTXJR4ij\nba8SxB04sL/N8eRrKja7TFWjCVtRwTTfyy771NYYNFVJclkxHyE5qw4m27crHF1y\nUNWEjuqNMi/lwAErS9fFa2oJlWyT8U7zzv/5kQREkxZI6y9v0AF3qcbsy2731FnD\ns9ChJvOUW9toIab2gsIdrKW8ZNpu084ZFVKb6LNjvIXI1Se4oMTHeszXzNptzlot\nkdxxjOoaQMAyfljFSot1F1FlU6MQlag7UnFGvFjRHN1JI5q4K+n3a67DX+TMyRqS\nHQIDAQAB", VITE_APP_DISABLE_PREVENT_UNLOAD: "", PKG_NAME: "@myoc/excalidraw", PKG_VERSION: "0.20.1", DEV: true };
3
3
 
4
4
  export {
5
5
  define_import_meta_env_default
6
6
  };
7
- //# sourceMappingURL=chunk-EYSZ36MK.js.map
7
+ //# sourceMappingURL=chunk-RCINQZKB.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  define_import_meta_env_default
3
- } from "./chunk-EYSZ36MK.js";
3
+ } from "./chunk-RCINQZKB.js";
4
4
  import {
5
5
  __publicField
6
6
  } from "./chunk-XDFCUUT6.js";
@@ -866,6 +866,7 @@ import {
866
866
  CJK_HAND_DRAWN_FALLBACK_FONT,
867
867
  WINDOWS_EMOJI_FALLBACK_FONT,
868
868
  getFontFamilyFallbacks,
869
+ isGoogleFontFamily as isGoogleFontFamily2,
869
870
  FONT_SIZES
870
871
  } from "@excalidraw/common";
871
872
  import { getContainerElement } from "@excalidraw/element";
@@ -874,71 +875,14 @@ import { containsCJK } from "@excalidraw/element";
874
875
  import {
875
876
  FONT_METADATA,
876
877
  getFontString,
878
+ registerFontMetadata,
879
+ unregisterFontMetadata,
877
880
  PromisePool,
878
881
  promiseTry as promiseTry3
879
882
  } from "@excalidraw/common";
880
883
  import { ShapeCache } from "@excalidraw/element";
881
884
  import { isTextElement } from "@excalidraw/element";
882
885
 
883
- // fonts/Cascadia/CascadiaCode-Regular.woff2
884
- var CascadiaCode_Regular_default = "./fonts/Cascadia/CascadiaCode-Regular.woff2";
885
-
886
- // fonts/Cascadia/index.ts
887
- var CascadiaFontFaces = [
888
- {
889
- uri: CascadiaCode_Regular_default
890
- }
891
- ];
892
-
893
- // fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2
894
- var ComicShanns_Regular_279a7b317d12eb88de06167bd672b4b4_default = "./fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2";
895
-
896
- // fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2
897
- var ComicShanns_Regular_6e066e8de2ac57ea9283adb9c24d7f0c_default = "./fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2";
898
-
899
- // fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2
900
- var ComicShanns_Regular_dc6a8806fa96795d7b3be5026f989a17_default = "./fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2";
901
-
902
- // fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2
903
- var ComicShanns_Regular_fcb0fc02dcbee4c9846b3e2508668039_default = "./fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2";
904
-
905
- // fonts/ComicShanns/index.ts
906
- var ComicShannsFontFaces = [
907
- {
908
- uri: ComicShanns_Regular_279a7b317d12eb88de06167bd672b4b4_default,
909
- descriptors: {
910
- unicodeRange: "U+20-7e,U+a1-a6,U+a8,U+ab-ac,U+af-b1,U+b4,U+b8,U+bb-bc,U+bf-cf,U+d1-d7,U+d9-de,U+e0-ef,U+f1-f7,U+f9-ff,U+131,U+152-153,U+2c6,U+2da,U+2dc,U+2013-2014,U+2018-201a,U+201c-201d,U+2020-2022,U+2026,U+2039-203a,U+2044,U+20ac,U+2191,U+2193,U+2212"
911
- }
912
- },
913
- {
914
- uri: ComicShanns_Regular_fcb0fc02dcbee4c9846b3e2508668039_default,
915
- descriptors: {
916
- unicodeRange: "U+100-10f,U+112-125,U+128-130,U+134-137,U+139-13c,U+141-148,U+14c-151,U+154-161,U+164-165,U+168-17f,U+1bf,U+1f7,U+218-21b,U+237,U+1e80-1e85,U+1ef2-1ef3,U+a75b"
917
- }
918
- },
919
- {
920
- uri: ComicShanns_Regular_dc6a8806fa96795d7b3be5026f989a17_default,
921
- descriptors: {
922
- unicodeRange: "U+2c7,U+2d8-2d9,U+2db,U+2dd,U+315,U+2190,U+2192,U+2200,U+2203-2204,U+2264-2265,U+f6c3"
923
- }
924
- },
925
- {
926
- uri: ComicShanns_Regular_6e066e8de2ac57ea9283adb9c24d7f0c_default,
927
- descriptors: { unicodeRange: "U+3bb" }
928
- }
929
- ];
930
-
931
- // fonts/Emoji/index.ts
932
- import { LOCAL_FONT_PROTOCOL } from "@excalidraw/common";
933
- var EmojiFontFaces = [
934
- {
935
- uri: LOCAL_FONT_PROTOCOL
936
- }
937
- ];
938
-
939
- // fonts/ExcalidrawFontFace.ts
940
- import { promiseTry as promiseTry2, LOCAL_FONT_PROTOCOL as LOCAL_FONT_PROTOCOL2 } from "@excalidraw/common";
941
-
942
886
  // subset/subset-main.ts
943
887
  import { isServerEnv, promiseTry } from "@excalidraw/common";
944
888
 
@@ -1083,6 +1027,10 @@ var subsetWoff2GlyphsByCodepoints = async (arrayBuffer, codePoints) => {
1083
1027
  }
1084
1028
  });
1085
1029
  };
1030
+ var getWoff2FontMetrics = async (arrayBuffer) => {
1031
+ const { getWoff2FontMetrics: getWoff2FontMetrics2 } = await lazyLoadSharedSubsetChunk();
1032
+ return getWoff2FontMetrics2(arrayBuffer);
1033
+ };
1086
1034
  var subsetWorker = null;
1087
1035
  var subsetShared = null;
1088
1036
  var lazyLoadWorkerSubsetChunk = async () => {
@@ -1109,11 +1057,70 @@ var getOrCreateWorkerPool = () => {
1109
1057
  return workerPool;
1110
1058
  };
1111
1059
 
1060
+ // fonts/Cascadia/CascadiaCode-Regular.woff2
1061
+ var CascadiaCode_Regular_default = "./fonts/Cascadia/CascadiaCode-Regular.woff2";
1062
+
1063
+ // fonts/Cascadia/index.ts
1064
+ var CascadiaFontFaces = [
1065
+ {
1066
+ uri: CascadiaCode_Regular_default
1067
+ }
1068
+ ];
1069
+
1070
+ // fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2
1071
+ var ComicShanns_Regular_279a7b317d12eb88de06167bd672b4b4_default = "./fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2";
1072
+
1073
+ // fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2
1074
+ var ComicShanns_Regular_6e066e8de2ac57ea9283adb9c24d7f0c_default = "./fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2";
1075
+
1076
+ // fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2
1077
+ var ComicShanns_Regular_dc6a8806fa96795d7b3be5026f989a17_default = "./fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2";
1078
+
1079
+ // fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2
1080
+ var ComicShanns_Regular_fcb0fc02dcbee4c9846b3e2508668039_default = "./fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2";
1081
+
1082
+ // fonts/ComicShanns/index.ts
1083
+ var ComicShannsFontFaces = [
1084
+ {
1085
+ uri: ComicShanns_Regular_279a7b317d12eb88de06167bd672b4b4_default,
1086
+ descriptors: {
1087
+ unicodeRange: "U+20-7e,U+a1-a6,U+a8,U+ab-ac,U+af-b1,U+b4,U+b8,U+bb-bc,U+bf-cf,U+d1-d7,U+d9-de,U+e0-ef,U+f1-f7,U+f9-ff,U+131,U+152-153,U+2c6,U+2da,U+2dc,U+2013-2014,U+2018-201a,U+201c-201d,U+2020-2022,U+2026,U+2039-203a,U+2044,U+20ac,U+2191,U+2193,U+2212"
1088
+ }
1089
+ },
1090
+ {
1091
+ uri: ComicShanns_Regular_fcb0fc02dcbee4c9846b3e2508668039_default,
1092
+ descriptors: {
1093
+ unicodeRange: "U+100-10f,U+112-125,U+128-130,U+134-137,U+139-13c,U+141-148,U+14c-151,U+154-161,U+164-165,U+168-17f,U+1bf,U+1f7,U+218-21b,U+237,U+1e80-1e85,U+1ef2-1ef3,U+a75b"
1094
+ }
1095
+ },
1096
+ {
1097
+ uri: ComicShanns_Regular_dc6a8806fa96795d7b3be5026f989a17_default,
1098
+ descriptors: {
1099
+ unicodeRange: "U+2c7,U+2d8-2d9,U+2db,U+2dd,U+315,U+2190,U+2192,U+2200,U+2203-2204,U+2264-2265,U+f6c3"
1100
+ }
1101
+ },
1102
+ {
1103
+ uri: ComicShanns_Regular_6e066e8de2ac57ea9283adb9c24d7f0c_default,
1104
+ descriptors: { unicodeRange: "U+3bb" }
1105
+ }
1106
+ ];
1107
+
1108
+ // fonts/Emoji/index.ts
1109
+ import { LOCAL_FONT_PROTOCOL } from "@excalidraw/common";
1110
+ var EmojiFontFaces = [
1111
+ {
1112
+ uri: LOCAL_FONT_PROTOCOL
1113
+ }
1114
+ ];
1115
+
1112
1116
  // fonts/ExcalidrawFontFace.ts
1117
+ import { promiseTry as promiseTry2, LOCAL_FONT_PROTOCOL as LOCAL_FONT_PROTOCOL2 } from "@excalidraw/common";
1113
1118
  var _ExcalidrawFontFace = class _ExcalidrawFontFace {
1114
- constructor(family, uri, descriptors) {
1119
+ constructor(family, uri, descriptors, mustEmbed = false) {
1115
1120
  __publicField(this, "urls");
1116
1121
  __publicField(this, "fontFace");
1122
+ __publicField(this, "mustEmbed");
1123
+ this.mustEmbed = mustEmbed;
1117
1124
  this.urls = _ExcalidrawFontFace.createUrls(uri);
1118
1125
  const sources = this.urls.map((url) => `url(${url}) ${_ExcalidrawFontFace.getFormat(url)}`).join(", ");
1119
1126
  this.fontFace = new FontFace(family, sources, {
@@ -1135,9 +1142,12 @@ var _ExcalidrawFontFace = class _ExcalidrawFontFace {
1135
1142
  const codepoints = Array.from(characters).map(
1136
1143
  (char) => char.codePointAt(0)
1137
1144
  );
1138
- return this.getContent(codepoints).then(
1139
- (content) => `@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`
1140
- );
1145
+ return this.getContent(codepoints).then((content) => {
1146
+ if (!content) {
1147
+ return "";
1148
+ }
1149
+ return `@font-face { font-family: ${this.fontFace.family}; src: url(${content}); }`;
1150
+ });
1141
1151
  }
1142
1152
  /**
1143
1153
  * Tries to fetch woff2 content, based on the registered urls (from first to last, treated as fallbacks).
@@ -1165,6 +1175,9 @@ var _ExcalidrawFontFace = class _ExcalidrawFontFace {
1165
1175
  `Failed to fetch font family "${this.fontFace.family}"`,
1166
1176
  JSON.stringify(errorMessages, void 0, 2)
1167
1177
  );
1178
+ if (this.mustEmbed) {
1179
+ return "";
1180
+ }
1168
1181
  return this.urls.length ? this.urls[this.urls.length - 1].toString() : "";
1169
1182
  }
1170
1183
  fetchFont(url) {
@@ -2980,6 +2993,150 @@ var XiaolaiFontFaces = [
2980
2993
  }
2981
2994
  ];
2982
2995
 
2996
+ // fonts/googleFonts.ts
2997
+ import {
2998
+ getGoogleFontFamilyName,
2999
+ isGoogleFontFamily,
3000
+ toGoogleFontFamily
3001
+ } from "@excalidraw/common";
3002
+ var GOOGLE_FONTS_CSS_URL = "https://fonts.googleapis.com/css2";
3003
+ var DEFAULT_GOOGLE_FONT_WEIGHT = 400;
3004
+ var parseGoogleFontId = (fontId) => {
3005
+ if (!isGoogleFontFamily(fontId)) {
3006
+ return null;
3007
+ }
3008
+ const name = getGoogleFontFamilyName(fontId);
3009
+ const match = name.match(/^(.+)@(\d{1,4})$/);
3010
+ if (!match) {
3011
+ return { family: name, weight: DEFAULT_GOOGLE_FONT_WEIGHT };
3012
+ }
3013
+ return { family: match[1], weight: Number(match[2]) };
3014
+ };
3015
+ var formatGoogleFontId = (family, weight = DEFAULT_GOOGLE_FONT_WEIGHT) => toGoogleFontFamily(
3016
+ weight === DEFAULT_GOOGLE_FONT_WEIGHT ? family : `${family}@${weight}`
3017
+ );
3018
+ var cssSources;
3019
+ var failedCssSources = /* @__PURE__ */ new Set();
3020
+ var setGoogleFontCssSources = (sources) => {
3021
+ cssSources = sources;
3022
+ };
3023
+ var getCssSources = (family) => {
3024
+ const sources = cssSources?.(family);
3025
+ return sources?.length ? sources : [GOOGLE_FONTS_CSS_URL];
3026
+ };
3027
+ var getAvailableCssSources = (family) => {
3028
+ const sources = getCssSources(family);
3029
+ const available = sources.filter((source) => !failedCssSources.has(source));
3030
+ return available.length ? available : sources;
3031
+ };
3032
+ var markGoogleFontSourceFailed = (family, source) => {
3033
+ failedCssSources.add(source);
3034
+ return getCssSources(family).some((x) => !failedCssSources.has(x));
3035
+ };
3036
+ var getGoogleFontCssUrl = (family, weight = DEFAULT_GOOGLE_FONT_WEIGHT, source = GOOGLE_FONTS_CSS_URL) => {
3037
+ const url = new URL(source);
3038
+ url.searchParams.set("family", `${family}:wght@${weight}`);
3039
+ url.searchParams.set("display", "swap");
3040
+ return url;
3041
+ };
3042
+ var getCssProperty = (css, property) => {
3043
+ const match = css.match(
3044
+ new RegExp(`(?:^|;)\\s*${property}\\s*:\\s*([^;]+)`, "i")
3045
+ );
3046
+ return match?.[1]?.trim();
3047
+ };
3048
+ var resolveWoff2Url = (src, base) => {
3049
+ try {
3050
+ const url = new URL(src, base);
3051
+ if (url.protocol !== "https:" && url.protocol !== "http:" || !url.pathname.endsWith(".woff2")) {
3052
+ return null;
3053
+ }
3054
+ return url.href;
3055
+ } catch {
3056
+ return null;
3057
+ }
3058
+ };
3059
+ var parseGoogleFontFaceCss = (css, base) => {
3060
+ const descriptors = [];
3061
+ const fontFaceRegex = /@font-face\s*\{([^}]+)\}/gi;
3062
+ let match;
3063
+ while (match = fontFaceRegex.exec(css)) {
3064
+ const body = match[1];
3065
+ const src = getCssProperty(body, "src");
3066
+ const rawUrl = src?.match(/url\((['"]?)([^'")]+)\1\)/i)?.[2];
3067
+ const url = rawUrl && resolveWoff2Url(rawUrl, base);
3068
+ if (!url) {
3069
+ continue;
3070
+ }
3071
+ const weight = getCssProperty(body, "font-weight") || "400";
3072
+ const style = getCssProperty(body, "font-style") || "normal";
3073
+ const unicodeRange = getCssProperty(body, "unicode-range");
3074
+ descriptors.push({
3075
+ uri: url,
3076
+ mustEmbed: true,
3077
+ descriptors: {
3078
+ weight,
3079
+ style,
3080
+ ...unicodeRange ? { unicodeRange } : {}
3081
+ }
3082
+ });
3083
+ }
3084
+ return descriptors;
3085
+ };
3086
+ var getInternalCssFamily = (fontId) => {
3087
+ const name = getGoogleFontFamilyName(fontId);
3088
+ return /^[\p{L}\p{N}_ -]+$/u.test(name) ? name : JSON.stringify(name);
3089
+ };
3090
+ var SourceFailure = class extends Error {
3091
+ };
3092
+ var fetchGoogleFontFaces = async (fontId, family, weight, source) => {
3093
+ const cssUrl = getGoogleFontCssUrl(family, weight, source);
3094
+ let response;
3095
+ try {
3096
+ response = await fetch(cssUrl, {
3097
+ cache: "force-cache",
3098
+ headers: { Accept: "text/css" }
3099
+ });
3100
+ } catch (error) {
3101
+ throw new SourceFailure(String(error), { cause: error });
3102
+ }
3103
+ if (!response.ok) {
3104
+ const ErrorType = response.status >= 500 || response.status === 429 ? SourceFailure : Error;
3105
+ throw new ErrorType(
3106
+ `Google Fonts CSS request failed for "${fontId}": ${response.status} ${response.statusText}`
3107
+ );
3108
+ }
3109
+ const descriptors = parseGoogleFontFaceCss(await response.text(), cssUrl);
3110
+ if (!descriptors.length) {
3111
+ throw new Error(`Google Fonts returned no WOFF2 faces for "${fontId}"`);
3112
+ }
3113
+ const cssFamily = getInternalCssFamily(fontId);
3114
+ return descriptors.map(
3115
+ ({ uri, descriptors: descriptors2, mustEmbed }) => new ExcalidrawFontFace(cssFamily, uri, descriptors2, mustEmbed)
3116
+ );
3117
+ };
3118
+ var loadGoogleFontFaces = async (fontId) => {
3119
+ const { family, weight } = parseGoogleFontId(fontId);
3120
+ let lastError;
3121
+ for (const source of getAvailableCssSources(family)) {
3122
+ try {
3123
+ const fontFaces = await fetchGoogleFontFaces(
3124
+ fontId,
3125
+ family,
3126
+ weight,
3127
+ source
3128
+ );
3129
+ return { fontFaces, source };
3130
+ } catch (error) {
3131
+ lastError = error;
3132
+ if (error instanceof SourceFailure) {
3133
+ failedCssSources.add(source);
3134
+ }
3135
+ }
3136
+ }
3137
+ throw lastError;
3138
+ };
3139
+
2983
3140
  // fonts/Fonts.ts
2984
3141
  var _Fonts = class _Fonts {
2985
3142
  constructor(scene) {
@@ -3037,6 +3194,15 @@ var _Fonts = class _Fonts {
3037
3194
  );
3038
3195
  return _Fonts.loadFontFaces(sceneFamilies, charsPerFamily);
3039
3196
  });
3197
+ /** Load a family for picker previews and invalidate text rendered with a fallback. */
3198
+ __publicField(this, "loadFontFamily", async (fontFamily, characters) => {
3199
+ const charsPerFamily = /* @__PURE__ */ new Map([
3200
+ [fontFamily, new Set(Array.from(characters))]
3201
+ ]);
3202
+ const fontFaces = await _Fonts.loadFontFaces([fontFamily], charsPerFamily);
3203
+ this.onLoaded(fontFaces);
3204
+ return fontFaces;
3205
+ });
3040
3206
  this.scene = scene;
3041
3207
  }
3042
3208
  static get registered() {
@@ -3066,16 +3232,29 @@ var _Fonts = class _Fonts {
3066
3232
  const characters = _Fonts.getCharacters(charsPerFamily, familyWithCJK);
3067
3233
  if (containsCJK(characters)) {
3068
3234
  const family = FONT_FAMILY_FALLBACKS[CJK_HAND_DRAWN_FALLBACK_FONT];
3069
- charsPerFamily[family] = new Set(characters);
3235
+ charsPerFamily.set(family, new Set(characters));
3070
3236
  families.unshift(FONT_FAMILY_FALLBACKS[CJK_HAND_DRAWN_FALLBACK_FONT]);
3071
3237
  }
3072
3238
  }
3239
+ await _Fonts.loadFontFaces(families, charsPerFamily);
3073
3240
  const iterator = _Fonts.fontFacesStylesGenerator(families, charsPerFamily);
3074
3241
  const concurrency = 3;
3075
3242
  const fontFaces = await new PromisePool(iterator, concurrency).all();
3076
3243
  return Array.from(new Set(fontFaces));
3077
3244
  }
3078
3245
  static async loadFontFaces(fontFamilies, charsPerFamily) {
3246
+ await Promise.all(
3247
+ fontFamilies.filter(isGoogleFontFamily2).map(async (fontFamily) => {
3248
+ try {
3249
+ await _Fonts.registerGoogleFont(fontFamily);
3250
+ } catch (error) {
3251
+ console.error(
3252
+ `Failed to register Google Font "${fontFamily}"`,
3253
+ error
3254
+ );
3255
+ }
3256
+ })
3257
+ );
3079
3258
  for (const { fontFaces: fontFaces2, metadata } of _Fonts.registered.values()) {
3080
3259
  if (metadata.local) {
3081
3260
  continue;
@@ -3101,9 +3280,16 @@ var _Fonts = class _Fonts {
3101
3280
  if (!window.document.fonts.check(font, text)) {
3102
3281
  yield promiseTry3(async () => {
3103
3282
  try {
3104
- const fontFaces = await window.document.fonts.load(font, text);
3105
- return [index, fontFaces];
3283
+ return await _Fonts.loadFontFacesForFamily(
3284
+ fontFamily,
3285
+ font,
3286
+ text,
3287
+ index
3288
+ );
3106
3289
  } catch (e) {
3290
+ if (isGoogleFontFamily2(fontFamily)) {
3291
+ _Fonts.resetGoogleFont(fontFamily);
3292
+ }
3107
3293
  console.error(
3108
3294
  `Failed to load font "${font}" from urls "${_Fonts.registered.get(fontFamily)?.fontFaces.map((x) => x.urls)}"`,
3109
3295
  e
@@ -3113,6 +3299,28 @@ var _Fonts = class _Fonts {
3113
3299
  }
3114
3300
  }
3115
3301
  }
3302
+ static async loadFontFacesForFamily(fontFamily, font, text, index) {
3303
+ while (true) {
3304
+ try {
3305
+ const fontFaces = await window.document.fonts.load(font, text);
3306
+ if (isGoogleFontFamily2(fontFamily)) {
3307
+ await _Fonts.loadGoogleFontMetrics(fontFamily, fontFaces);
3308
+ }
3309
+ return [index, fontFaces];
3310
+ } catch (error) {
3311
+ const source = _Fonts.googleFontSources.get(fontFamily);
3312
+ const parsed = parseGoogleFontId(fontFamily);
3313
+ if (!parsed || !source || !markGoogleFontSourceFailed(parsed.family, source)) {
3314
+ throw error;
3315
+ }
3316
+ _Fonts.resetGoogleFont(fontFamily);
3317
+ await _Fonts.registerGoogleFont(fontFamily);
3318
+ for (const { fontFace } of _Fonts.registered.get(fontFamily)?.fontFaces ?? []) {
3319
+ window.document.fonts.add(fontFace);
3320
+ }
3321
+ }
3322
+ }
3323
+ }
3116
3324
  static *fontFacesStylesGenerator(families, charsPerFamily) {
3117
3325
  for (const [familyIndex, family] of families.entries()) {
3118
3326
  const { fontFaces, metadata } = _Fonts.registered.get(family) ?? {};
@@ -3161,7 +3369,7 @@ var _Fonts = class _Fonts {
3161
3369
  this.registered.set(fontFamily, {
3162
3370
  metadata,
3163
3371
  fontFaces: fontFacesDecriptors.map(
3164
- ({ uri, descriptors }) => new ExcalidrawFontFace(family, uri, descriptors)
3372
+ ({ uri, descriptors, mustEmbed }) => new ExcalidrawFontFace(family, uri, descriptors, mustEmbed)
3165
3373
  )
3166
3374
  });
3167
3375
  }
@@ -3209,16 +3417,16 @@ var _Fonts = class _Fonts {
3209
3417
  * Get all the unique characters per font family for the given scene.
3210
3418
  */
3211
3419
  static getCharsPerFamily(elements) {
3212
- const charsPerFamily = {};
3420
+ const charsPerFamily = /* @__PURE__ */ new Map();
3213
3421
  for (const element of elements) {
3214
3422
  if (!isTextElement(element)) {
3215
3423
  continue;
3216
3424
  }
3217
3425
  for (const char of element.originalText) {
3218
- if (!charsPerFamily[element.fontFamily]) {
3219
- charsPerFamily[element.fontFamily] = /* @__PURE__ */ new Set();
3426
+ if (!charsPerFamily.has(element.fontFamily)) {
3427
+ charsPerFamily.set(element.fontFamily, /* @__PURE__ */ new Set());
3220
3428
  }
3221
- charsPerFamily[element.fontFamily].add(char);
3429
+ charsPerFamily.get(element.fontFamily).add(char);
3222
3430
  }
3223
3431
  }
3224
3432
  return charsPerFamily;
@@ -3227,7 +3435,7 @@ var _Fonts = class _Fonts {
3227
3435
  * Get characters for a given family.
3228
3436
  */
3229
3437
  static getCharacters(charsPerFamily, family) {
3230
- return charsPerFamily[family] ? Array.from(charsPerFamily[family]).join("") : "";
3438
+ return charsPerFamily.get(family) ? Array.from(charsPerFamily.get(family)).join("") : "";
3231
3439
  }
3232
3440
  /**
3233
3441
  * Get all registered font families.
@@ -3239,6 +3447,10 @@ var _Fonts = class _Fonts {
3239
3447
  // it's ok to track fonts across multiple instances only once, so let's use
3240
3448
  // a static member to reduce memory footprint
3241
3449
  __publicField(_Fonts, "loadedFontsCache", /* @__PURE__ */ new Set());
3450
+ __publicField(_Fonts, "googleFontPromises", /* @__PURE__ */ new Map());
3451
+ __publicField(_Fonts, "googleFontMetrics", /* @__PURE__ */ new Set());
3452
+ /** CSS source each registered Google font was loaded from. */
3453
+ __publicField(_Fonts, "googleFontSources", /* @__PURE__ */ new Map());
3242
3454
  __publicField(_Fonts, "_registered");
3243
3455
  __publicField(_Fonts, "_initialized", false);
3244
3456
  /**
@@ -3249,6 +3461,88 @@ __publicField(_Fonts, "loadElementsFonts", async (elements) => {
3249
3461
  const charsPerFamily = _Fonts.getCharsPerFamily(elements);
3250
3462
  return _Fonts.loadFontFaces(fontFamilies, charsPerFamily);
3251
3463
  });
3464
+ __publicField(_Fonts, "registerGoogleFont", async (fontFamily) => {
3465
+ if (!isGoogleFontFamily2(fontFamily) || _Fonts.registered.has(fontFamily)) {
3466
+ return;
3467
+ }
3468
+ let promise = _Fonts.googleFontPromises.get(fontFamily);
3469
+ if (!promise) {
3470
+ promise = loadGoogleFontFaces(fontFamily).then(
3471
+ ({ fontFaces, source }) => {
3472
+ if (!fontFaces.length) {
3473
+ throw new Error(
3474
+ `Google Fonts returned no font faces for "${fontFamily}"`
3475
+ );
3476
+ }
3477
+ _Fonts.registered.set(fontFamily, {
3478
+ metadata: FONT_METADATA[FONT_FAMILY.Excalifont],
3479
+ fontFaces
3480
+ });
3481
+ _Fonts.googleFontSources.set(fontFamily, source);
3482
+ }
3483
+ );
3484
+ _Fonts.googleFontPromises.set(fontFamily, promise);
3485
+ }
3486
+ try {
3487
+ await promise;
3488
+ } catch (error) {
3489
+ if (_Fonts.googleFontPromises.get(fontFamily) === promise) {
3490
+ _Fonts.googleFontPromises.delete(fontFamily);
3491
+ }
3492
+ throw error;
3493
+ }
3494
+ });
3495
+ __publicField(_Fonts, "resetGoogleFont", (fontFamily) => {
3496
+ if (!isGoogleFontFamily2(fontFamily)) {
3497
+ return;
3498
+ }
3499
+ const registered = _Fonts.registered.get(fontFamily);
3500
+ if (registered) {
3501
+ for (const { fontFace } of registered.fontFaces) {
3502
+ window.document.fonts.delete(fontFace);
3503
+ _Fonts.loadedFontsCache.delete(
3504
+ `${fontFace.family}-${fontFace.style}-${fontFace.weight}-${fontFace.unicodeRange}`
3505
+ );
3506
+ }
3507
+ _Fonts.registered.delete(fontFamily);
3508
+ }
3509
+ _Fonts.googleFontPromises.delete(fontFamily);
3510
+ _Fonts.googleFontMetrics.delete(fontFamily);
3511
+ _Fonts.googleFontSources.delete(fontFamily);
3512
+ unregisterFontMetadata(fontFamily);
3513
+ });
3514
+ __publicField(_Fonts, "loadGoogleFontMetrics", async (fontFamily, loadedFaces) => {
3515
+ if (!isGoogleFontFamily2(fontFamily) || _Fonts.googleFontMetrics.has(fontFamily)) {
3516
+ return;
3517
+ }
3518
+ const registered = _Fonts.registered.get(fontFamily);
3519
+ const loadedFace = registered?.fontFaces.find(
3520
+ (candidate) => loadedFaces.includes(candidate.fontFace)
3521
+ );
3522
+ const url = loadedFace?.urls.find((candidate) => candidate instanceof URL);
3523
+ if (!registered || !loadedFace || !(url instanceof URL)) {
3524
+ return;
3525
+ }
3526
+ try {
3527
+ const metrics = await getWoff2FontMetrics(
3528
+ await loadedFace.fetchFont(url)
3529
+ );
3530
+ const metadata = {
3531
+ ...registered.metadata,
3532
+ metrics: {
3533
+ unitsPerEm: metrics.unitsPerEm,
3534
+ ascender: metrics.ascender,
3535
+ descender: metrics.descender,
3536
+ lineHeight: metrics.lineHeight
3537
+ }
3538
+ };
3539
+ registered.metadata = metadata;
3540
+ registerFontMetadata(fontFamily, metadata);
3541
+ _Fonts.googleFontMetrics.add(fontFamily);
3542
+ } catch (error) {
3543
+ console.error(`Failed to parse metrics for "${fontFamily}"`, error);
3544
+ }
3545
+ });
3252
3546
  var Fonts = _Fonts;
3253
3547
 
3254
3548
  // renderer/staticScene.ts
@@ -5455,7 +5749,7 @@ var parseFileContents = async (blob) => {
5455
5749
  let contents;
5456
5750
  if (blob.type === MIME_TYPES6.png) {
5457
5751
  try {
5458
- return await (await import("./data/image-KRZO2CVW.js")).decodePngMetadata(blob);
5752
+ return await (await import("./data/image-LHOOLEDU.js")).decodePngMetadata(blob);
5459
5753
  } catch (error) {
5460
5754
  if (error.message === "INVALID") {
5461
5755
  throw new ImageSceneDataError(
@@ -5858,6 +6152,11 @@ export {
5858
6152
  ImageSceneDataError,
5859
6153
  UnsupportedImageFileTypeError,
5860
6154
  ExcalidrawError,
6155
+ DEFAULT_GOOGLE_FONT_WEIGHT,
6156
+ parseGoogleFontId,
6157
+ formatGoogleFontId,
6158
+ setGoogleFontCssSources,
6159
+ parseGoogleFontFaceCss,
5861
6160
  Fonts,
5862
6161
  getDefaultAppState,
5863
6162
  isEraserActive,
@@ -5906,4 +6205,4 @@ export {
5906
6205
  createFile,
5907
6206
  normalizeFile
5908
6207
  };
5909
- //# sourceMappingURL=chunk-JBD373VY.js.map
6208
+ //# sourceMappingURL=chunk-TYPY4HGC.js.map