@excalidraw/excalidraw 0.17.1-f597bd3 → 0.17.1-f59b4f6

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.
@@ -13561,12 +13561,15 @@ init_define_import_meta_env();
13561
13561
  // data/url.ts
13562
13562
  init_define_import_meta_env();
13563
13563
  var import_sanitize_url = __toESM(require_dist(), 1);
13564
+ var sanitizeHTMLAttribute = (html) => {
13565
+ return html.replace(/"/g, """);
13566
+ };
13564
13567
  var normalizeLink = (link) => {
13565
13568
  link = link.trim();
13566
13569
  if (!link) {
13567
13570
  return link;
13568
13571
  }
13569
- return (0, import_sanitize_url.sanitizeUrl)(link);
13572
+ return (0, import_sanitize_url.sanitizeUrl)(sanitizeHTMLAttribute(link));
13570
13573
  };
13571
13574
  var isLocalLink = (link) => {
13572
13575
  return !!(link?.includes(location.origin) || link?.startsWith("/"));
@@ -14060,13 +14063,13 @@ var duplicateElements = (elements, opts) => {
14060
14063
  // element/embeddable.ts
14061
14064
  var embeddedLinkCache = /* @__PURE__ */ new Map();
14062
14065
  var RE_YOUTUBE = /^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/;
14063
- var RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
14066
+ var RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}\.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
14064
14067
  var RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/;
14065
- var RE_GH_GIST = /^https:\/\/gist\.github\.com/;
14066
- var RE_GH_GIST_EMBED = /^<script[\s\S]*?\ssrc=["'](https:\/\/gist.github.com\/.*?)\.js["']/i;
14067
- var RE_TWITTER = /(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:twitter|x).com/;
14068
- var RE_TWITTER_EMBED = /^<blockquote[\s\S]*?\shref=["'](https:\/\/(?:twitter|x).com\/[^"']*)/i;
14069
- var RE_VALTOWN = /^https:\/\/(?:www\.)?val.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/;
14068
+ var RE_GH_GIST = /^https:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)/;
14069
+ var RE_GH_GIST_EMBED = /^<script[\s\S]*?\ssrc=["'](https:\/\/gist\.github\.com\/.*?)\.js["']/i;
14070
+ var RE_TWITTER = /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com\/[^/]+\/status\/(\d+)/;
14071
+ var RE_TWITTER_EMBED = /^<blockquote[\s\S]*?\shref=["'](https?:\/\/(?:twitter|x)\.com\/[^"']*)/i;
14072
+ var RE_VALTOWN = /^https:\/\/(?:www\.)?val\.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/;
14070
14073
  var RE_GENERIC_EMBED = /^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']*)["'][\s\S]*?>$/i;
14071
14074
  var RE_GIPHY = /giphy.com\/(?:clips|embed|gifs)\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;
14072
14075
  var ALLOWED_DOMAINS = /* @__PURE__ */ new Set([
@@ -14164,50 +14167,38 @@ var getEmbedLink = (link) => {
14164
14167
  return { link, intrinsicSize: aspectRatio, type };
14165
14168
  }
14166
14169
  if (RE_TWITTER.test(link)) {
14167
- link = link.replace(/\bx.com\b/, "twitter.com");
14168
- let ret;
14169
- if (/<blockquote/.test(link)) {
14170
- const srcDoc = createSrcDoc(link);
14171
- ret = {
14172
- type: "document",
14173
- srcdoc: () => srcDoc,
14174
- intrinsicSize: { w: 480, h: 480 }
14175
- };
14176
- } else {
14177
- ret = {
14178
- type: "document",
14179
- srcdoc: (theme) => createSrcDoc(
14180
- `<blockquote class="twitter-tweet" data-dnt="true" data-theme="${theme}"><a href="${link}"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"><\/script>`
14181
- ),
14182
- intrinsicSize: { w: 480, h: 480 }
14183
- };
14184
- }
14170
+ const postId = link.match(RE_TWITTER)[1];
14171
+ const safeURL = sanitizeHTMLAttribute(
14172
+ `https://twitter.com/x/status/${postId}`
14173
+ );
14174
+ const ret = {
14175
+ type: "document",
14176
+ srcdoc: (theme) => createSrcDoc(
14177
+ `<blockquote class="twitter-tweet" data-dnt="true" data-theme="${theme}"><a href="${safeURL}"></a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"><\/script>`
14178
+ ),
14179
+ intrinsicSize: { w: 480, h: 480 },
14180
+ sandbox: { allowSameOrigin: true }
14181
+ };
14185
14182
  embeddedLinkCache.set(originalLink, ret);
14186
14183
  return ret;
14187
14184
  }
14188
14185
  if (RE_GH_GIST.test(link)) {
14189
- let ret;
14190
- if (/<script>/.test(link)) {
14191
- const srcDoc = createSrcDoc(link);
14192
- ret = {
14193
- type: "document",
14194
- srcdoc: () => srcDoc,
14195
- intrinsicSize: { w: 550, h: 720 }
14196
- };
14197
- } else {
14198
- ret = {
14199
- type: "document",
14200
- srcdoc: () => createSrcDoc(`
14201
- <script src="${link}.js"><\/script>
14186
+ const [, user, gistId] = link.match(RE_GH_GIST);
14187
+ const safeURL = sanitizeHTMLAttribute(
14188
+ `https://gist.github.com/${user}/${gistId}`
14189
+ );
14190
+ const ret = {
14191
+ type: "document",
14192
+ srcdoc: () => createSrcDoc(`
14193
+ <script src="${safeURL}.js"><\/script>
14202
14194
  <style type="text/css">
14203
14195
  * { margin: 0px; }
14204
14196
  table, .gist { height: 100%; }
14205
14197
  .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }
14206
14198
  </style>
14207
14199
  `),
14208
- intrinsicSize: { w: 550, h: 720 }
14209
- };
14210
- }
14200
+ intrinsicSize: { w: 550, h: 720 }
14201
+ };
14211
14202
  embeddedLinkCache.set(link, ret);
14212
14203
  return ret;
14213
14204
  }
@@ -14775,6 +14766,9 @@ var renderSceneToSvg = (elements, elementsMap, rsvg, svgRoot, files, renderConfi
14775
14766
  }
14776
14767
  elements.filter((el) => !isIframeLikeElement(el)).forEach((element) => {
14777
14768
  if (!element.isDeleted) {
14769
+ if (isTextElement(element) && element.containerId && elementsMap.has(element.containerId)) {
14770
+ return;
14771
+ }
14778
14772
  try {
14779
14773
  renderElementToSvg(
14780
14774
  element,
@@ -14786,6 +14780,19 @@ var renderSceneToSvg = (elements, elementsMap, rsvg, svgRoot, files, renderConfi
14786
14780
  element.y + renderConfig.offsetY,
14787
14781
  renderConfig
14788
14782
  );
14783
+ const boundTextElement = getBoundTextElement(element, elementsMap);
14784
+ if (boundTextElement) {
14785
+ renderElementToSvg(
14786
+ boundTextElement,
14787
+ elementsMap,
14788
+ rsvg,
14789
+ svgRoot,
14790
+ files,
14791
+ boundTextElement.x + renderConfig.offsetX,
14792
+ boundTextElement.y + renderConfig.offsetY,
14793
+ renderConfig
14794
+ );
14795
+ }
14789
14796
  } catch (error) {
14790
14797
  console.error(error);
14791
14798
  }
@@ -15578,13 +15585,19 @@ var getFreedrawShape = (element, center, isClosed2 = false) => {
15578
15585
  data: polyline
15579
15586
  };
15580
15587
  };
15581
- var getClosedCurveShape = (roughShape, startingPoint = [0, 0], angleInRadian, center) => {
15582
- const ops = getCurvePathOps2(roughShape);
15588
+ var getClosedCurveShape = (element, roughShape, startingPoint = [0, 0], angleInRadian, center) => {
15583
15589
  const transform = (p) => pointRotate(
15584
15590
  [p[0] + startingPoint[0], p[1] + startingPoint[1]],
15585
15591
  angleToDegrees(angleInRadian),
15586
15592
  center
15587
15593
  );
15594
+ if (element.roundness === null) {
15595
+ return {
15596
+ type: "polygon",
15597
+ data: close(element.points.map((p) => transform(p)))
15598
+ };
15599
+ }
15600
+ const ops = getCurvePathOps2(roughShape);
15588
15601
  const points = [];
15589
15602
  let odd = false;
15590
15603
  for (const operation of ops) {
@@ -15916,8 +15929,11 @@ var _renderStaticScene = ({
15916
15929
  visibleElements.filter((el) => !isIframeLikeElement(el)).forEach((element) => {
15917
15930
  try {
15918
15931
  const frameId = element.frameId || appState.frameToHighlight?.id;
15932
+ if (isTextElement(element) && element.containerId && elementsMap.has(element.containerId)) {
15933
+ return;
15934
+ }
15935
+ context.save();
15919
15936
  if (frameId && appState.frameRendering.enabled && appState.frameRendering.clip) {
15920
- context.save();
15921
15937
  const frame = getTargetFrame(element, elementsMap, appState);
15922
15938
  if (frame && isElementInFrame(element, elementsMap, appState)) {
15923
15939
  frameClip(frame, context, renderConfig, appState);
@@ -15931,7 +15947,6 @@ var _renderStaticScene = ({
15931
15947
  renderConfig,
15932
15948
  appState
15933
15949
  );
15934
- context.restore();
15935
15950
  } else {
15936
15951
  renderElement(
15937
15952
  element,
@@ -15943,6 +15958,19 @@ var _renderStaticScene = ({
15943
15958
  appState
15944
15959
  );
15945
15960
  }
15961
+ const boundTextElement = getBoundTextElement(element, allElementsMap);
15962
+ if (boundTextElement) {
15963
+ renderElement(
15964
+ boundTextElement,
15965
+ elementsMap,
15966
+ allElementsMap,
15967
+ rc,
15968
+ context,
15969
+ renderConfig,
15970
+ appState
15971
+ );
15972
+ }
15973
+ context.restore();
15946
15974
  if (!isExporting) {
15947
15975
  renderLinkIcon(element, context, appState, elementsMap);
15948
15976
  }
@@ -16187,7 +16215,7 @@ var exportToSvg = async (elements, appState, files, opts) => {
16187
16215
  let metadata = "";
16188
16216
  if (exportEmbedScene) {
16189
16217
  try {
16190
- metadata = await (await import("./image-CAYW6EUH.js")).encodeSvgMetadata({
16218
+ metadata = await (await import("./image-F7EVY5ZQ.js")).encodeSvgMetadata({
16191
16219
  // when embedding scene, we want to embed the origionally supplied
16192
16220
  // elements which don't contain the temp frame labels.
16193
16221
  // But it also requires that the exportToSvg is being supplied with
@@ -19711,7 +19739,7 @@ var parseFileContents = async (blob) => {
19711
19739
  let contents;
19712
19740
  if (blob.type === MIME_TYPES.png) {
19713
19741
  try {
19714
- return await (await import("./image-CAYW6EUH.js")).decodePngMetadata(blob);
19742
+ return await (await import("./image-F7EVY5ZQ.js")).decodePngMetadata(blob);
19715
19743
  } catch (error) {
19716
19744
  if (error.message === "INVALID") {
19717
19745
  throw new ImageSceneDataError(
@@ -19738,7 +19766,7 @@ var parseFileContents = async (blob) => {
19738
19766
  }
19739
19767
  if (blob.type === MIME_TYPES.svg) {
19740
19768
  try {
19741
- return await (await import("./image-CAYW6EUH.js")).decodeSvgMetadata({
19769
+ return await (await import("./image-F7EVY5ZQ.js")).decodeSvgMetadata({
19742
19770
  svg: contents
19743
19771
  });
19744
19772
  } catch (error) {
@@ -20606,4 +20634,4 @@ export {
20606
20634
  getNormalizedZoom,
20607
20635
  getStateForZoom
20608
20636
  };
20609
- //# sourceMappingURL=chunk-R7HUEHN5.js.map
20637
+ //# sourceMappingURL=chunk-O74FSJNG.js.map