@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.
package/dist/dev/index.js CHANGED
@@ -6447,17 +6447,20 @@ var init_groups = __esm({
6447
6447
 
6448
6448
  // data/url.ts
6449
6449
  import { sanitizeUrl } from "@braintree/sanitize-url";
6450
- var normalizeLink, isLocalLink, toValidURL;
6450
+ var sanitizeHTMLAttribute, normalizeLink, isLocalLink, toValidURL;
6451
6451
  var init_url = __esm({
6452
6452
  "data/url.ts"() {
6453
6453
  "use strict";
6454
6454
  init_define_import_meta_env();
6455
+ sanitizeHTMLAttribute = (html) => {
6456
+ return html.replace(/"/g, """);
6457
+ };
6455
6458
  normalizeLink = (link) => {
6456
6459
  link = link.trim();
6457
6460
  if (!link) {
6458
6461
  return link;
6459
6462
  }
6460
- return sanitizeUrl(link);
6463
+ return sanitizeUrl(sanitizeHTMLAttribute(link));
6461
6464
  };
6462
6465
  isLocalLink = (link) => {
6463
6466
  return !!(link?.includes(location.origin) || link?.startsWith("/"));
@@ -6979,15 +6982,16 @@ var init_embeddable = __esm({
6979
6982
  init_newElement();
6980
6983
  init_textElement();
6981
6984
  init_typeChecks();
6985
+ init_url();
6982
6986
  embeddedLinkCache = /* @__PURE__ */ new Map();
6983
6987
  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]*$/;
6984
- RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
6988
+ RE_VIMEO = /^(?:http(?:s)?:\/\/)?(?:(?:w){3}\.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
6985
6989
  RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/;
6986
- RE_GH_GIST = /^https:\/\/gist\.github\.com/;
6987
- RE_GH_GIST_EMBED = /^<script[\s\S]*?\ssrc=["'](https:\/\/gist.github.com\/.*?)\.js["']/i;
6988
- RE_TWITTER = /(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:twitter|x).com/;
6989
- RE_TWITTER_EMBED = /^<blockquote[\s\S]*?\shref=["'](https:\/\/(?:twitter|x).com\/[^"']*)/i;
6990
- RE_VALTOWN = /^https:\/\/(?:www\.)?val.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/;
6990
+ RE_GH_GIST = /^https:\/\/gist\.github\.com\/([\w_-]+)\/([\w_-]+)/;
6991
+ RE_GH_GIST_EMBED = /^<script[\s\S]*?\ssrc=["'](https:\/\/gist\.github\.com\/.*?)\.js["']/i;
6992
+ RE_TWITTER = /(?:https?:\/\/)?(?:(?:w){3}\.)?(?:twitter|x)\.com\/[^/]+\/status\/(\d+)/;
6993
+ RE_TWITTER_EMBED = /^<blockquote[\s\S]*?\shref=["'](https?:\/\/(?:twitter|x)\.com\/[^"']*)/i;
6994
+ RE_VALTOWN = /^https:\/\/(?:www\.)?val\.town\/(v|embed)\/[a-zA-Z_$][0-9a-zA-Z_$]+\.[a-zA-Z_$][0-9a-zA-Z_$]+/;
6991
6995
  RE_GENERIC_EMBED = /^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']*)["'][\s\S]*?>$/i;
6992
6996
  RE_GIPHY = /giphy.com\/(?:clips|embed|gifs)\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;
6993
6997
  ALLOWED_DOMAINS = /* @__PURE__ */ new Set([
@@ -7085,50 +7089,38 @@ var init_embeddable = __esm({
7085
7089
  return { link, intrinsicSize: aspectRatio, type };
7086
7090
  }
7087
7091
  if (RE_TWITTER.test(link)) {
7088
- link = link.replace(/\bx.com\b/, "twitter.com");
7089
- let ret;
7090
- if (/<blockquote/.test(link)) {
7091
- const srcDoc = createSrcDoc(link);
7092
- ret = {
7093
- type: "document",
7094
- srcdoc: () => srcDoc,
7095
- intrinsicSize: { w: 480, h: 480 }
7096
- };
7097
- } else {
7098
- ret = {
7099
- type: "document",
7100
- srcdoc: (theme) => createSrcDoc(
7101
- `<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>`
7102
- ),
7103
- intrinsicSize: { w: 480, h: 480 }
7104
- };
7105
- }
7092
+ const postId = link.match(RE_TWITTER)[1];
7093
+ const safeURL = sanitizeHTMLAttribute(
7094
+ `https://twitter.com/x/status/${postId}`
7095
+ );
7096
+ const ret = {
7097
+ type: "document",
7098
+ srcdoc: (theme) => createSrcDoc(
7099
+ `<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>`
7100
+ ),
7101
+ intrinsicSize: { w: 480, h: 480 },
7102
+ sandbox: { allowSameOrigin: true }
7103
+ };
7106
7104
  embeddedLinkCache.set(originalLink, ret);
7107
7105
  return ret;
7108
7106
  }
7109
7107
  if (RE_GH_GIST.test(link)) {
7110
- let ret;
7111
- if (/<script>/.test(link)) {
7112
- const srcDoc = createSrcDoc(link);
7113
- ret = {
7114
- type: "document",
7115
- srcdoc: () => srcDoc,
7116
- intrinsicSize: { w: 550, h: 720 }
7117
- };
7118
- } else {
7119
- ret = {
7120
- type: "document",
7121
- srcdoc: () => createSrcDoc(`
7122
- <script src="${link}.js"><\/script>
7108
+ const [, user, gistId] = link.match(RE_GH_GIST);
7109
+ const safeURL = sanitizeHTMLAttribute(
7110
+ `https://gist.github.com/${user}/${gistId}`
7111
+ );
7112
+ const ret = {
7113
+ type: "document",
7114
+ srcdoc: () => createSrcDoc(`
7115
+ <script src="${safeURL}.js"><\/script>
7123
7116
  <style type="text/css">
7124
7117
  * { margin: 0px; }
7125
7118
  table, .gist { height: 100%; }
7126
7119
  .gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }
7127
7120
  </style>
7128
7121
  `),
7129
- intrinsicSize: { w: 550, h: 720 }
7130
- };
7131
- }
7122
+ intrinsicSize: { w: 550, h: 720 }
7123
+ };
7132
7124
  embeddedLinkCache.set(link, ret);
7133
7125
  return ret;
7134
7126
  }
@@ -7715,6 +7707,9 @@ var init_staticSvgScene = __esm({
7715
7707
  }
7716
7708
  elements.filter((el) => !isIframeLikeElement(el)).forEach((element) => {
7717
7709
  if (!element.isDeleted) {
7710
+ if (isTextElement(element) && element.containerId && elementsMap.has(element.containerId)) {
7711
+ return;
7712
+ }
7718
7713
  try {
7719
7714
  renderElementToSvg(
7720
7715
  element,
@@ -7726,6 +7721,19 @@ var init_staticSvgScene = __esm({
7726
7721
  element.y + renderConfig.offsetY,
7727
7722
  renderConfig
7728
7723
  );
7724
+ const boundTextElement = getBoundTextElement(element, elementsMap);
7725
+ if (boundTextElement) {
7726
+ renderElementToSvg(
7727
+ boundTextElement,
7728
+ elementsMap,
7729
+ rsvg,
7730
+ svgRoot,
7731
+ files,
7732
+ boundTextElement.x + renderConfig.offsetX,
7733
+ boundTextElement.y + renderConfig.offsetY,
7734
+ renderConfig
7735
+ );
7736
+ }
7729
7737
  } catch (error) {
7730
7738
  console.error(error);
7731
7739
  }
@@ -9061,13 +9069,19 @@ var init_shape = __esm({
9061
9069
  data: polyline
9062
9070
  };
9063
9071
  };
9064
- getClosedCurveShape = (roughShape, startingPoint = [0, 0], angleInRadian, center) => {
9065
- const ops = getCurvePathOps2(roughShape);
9072
+ getClosedCurveShape = (element, roughShape, startingPoint = [0, 0], angleInRadian, center) => {
9066
9073
  const transform = (p) => pointRotate(
9067
9074
  [p[0] + startingPoint[0], p[1] + startingPoint[1]],
9068
9075
  angleToDegrees(angleInRadian),
9069
9076
  center
9070
9077
  );
9078
+ if (element.roundness === null) {
9079
+ return {
9080
+ type: "polygon",
9081
+ data: close(element.points.map((p) => transform(p)))
9082
+ };
9083
+ }
9084
+ const ops = getCurvePathOps2(roughShape);
9071
9085
  const points = [];
9072
9086
  let odd = false;
9073
9087
  for (const operation of ops) {
@@ -9292,6 +9306,7 @@ var init_staticScene = __esm({
9292
9306
  init_helpers();
9293
9307
  init_helpers2();
9294
9308
  init_utils();
9309
+ init_textElement();
9295
9310
  strokeGrid = (context, gridSize, scrollX, scrollY, zoom, width, height) => {
9296
9311
  const BOLD_LINE_FREQUENCY = 5;
9297
9312
  let GridLineColor;
@@ -9446,8 +9461,11 @@ var init_staticScene = __esm({
9446
9461
  visibleElements.filter((el) => !isIframeLikeElement(el)).forEach((element) => {
9447
9462
  try {
9448
9463
  const frameId = element.frameId || appState.frameToHighlight?.id;
9464
+ if (isTextElement(element) && element.containerId && elementsMap.has(element.containerId)) {
9465
+ return;
9466
+ }
9467
+ context.save();
9449
9468
  if (frameId && appState.frameRendering.enabled && appState.frameRendering.clip) {
9450
- context.save();
9451
9469
  const frame = getTargetFrame(element, elementsMap, appState);
9452
9470
  if (frame && isElementInFrame(element, elementsMap, appState)) {
9453
9471
  frameClip(frame, context, renderConfig, appState);
@@ -9461,7 +9479,6 @@ var init_staticScene = __esm({
9461
9479
  renderConfig,
9462
9480
  appState
9463
9481
  );
9464
- context.restore();
9465
9482
  } else {
9466
9483
  renderElement(
9467
9484
  element,
@@ -9473,6 +9490,19 @@ var init_staticScene = __esm({
9473
9490
  appState
9474
9491
  );
9475
9492
  }
9493
+ const boundTextElement = getBoundTextElement(element, allElementsMap);
9494
+ if (boundTextElement) {
9495
+ renderElement(
9496
+ boundTextElement,
9497
+ elementsMap,
9498
+ allElementsMap,
9499
+ rc,
9500
+ context,
9501
+ renderConfig,
9502
+ appState
9503
+ );
9504
+ }
9505
+ context.restore();
9476
9506
  if (!isExporting) {
9477
9507
  renderLinkIcon(element, context, appState, elementsMap);
9478
9508
  }
@@ -37371,7 +37401,7 @@ var App = class _App extends React38.Component {
37371
37401
  title: "Excalidraw Embedded Content",
37372
37402
  allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
37373
37403
  allowFullScreen: true,
37374
- sandbox: "allow-same-origin allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads"
37404
+ sandbox: `${src?.sandbox?.allowSameOrigin ? "allow-same-origin" : ""} allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-presentation allow-downloads`
37375
37405
  }
37376
37406
  )
37377
37407
  }
@@ -39794,6 +39824,7 @@ var App = class _App extends React38.Component {
39794
39824
  this.scene.getNonDeletedElementsMap()
39795
39825
  );
39796
39826
  return shouldTestInside(element) ? getClosedCurveShape(
39827
+ element,
39797
39828
  roughShape,
39798
39829
  [element.x, element.y],
39799
39830
  element.angle,