@vishu1301/script-writing 0.5.1 → 0.5.2

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/index.cjs CHANGED
@@ -337,7 +337,7 @@ function ScreenplayEditorView({
337
337
  const link = document.createElement("link");
338
338
  link.id = fontId;
339
339
  link.rel = "stylesheet";
340
- link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap";
340
+ link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap";
341
341
  document.head.appendChild(link);
342
342
  }
343
343
  }, []);
@@ -385,7 +385,7 @@ function ScreenplayEditorView({
385
385
  {
386
386
  className: "relative bg-[#fdfdfc] shadow-2xl shadow-zinc-300/60 border border-zinc-100 rounded-sm md:rounded-md pl-[1.5in] py-[1in] pr-[1in] flex flex-col w-[210mm] min-h-[297mm] shrink-0",
387
387
  style: {
388
- fontFamily: "'Courier Prime', 'Courier New', Courier, monospace",
388
+ fontFamily: "var(--font-courier-prime, 'Courier Prime', 'Courier New', Courier, monospace)",
389
389
  paddingLeft: "1.5in",
390
390
  paddingRight: "1in",
391
391
  paddingTop: "1in",
@@ -949,7 +949,7 @@ function setCaretPosition(element, offset) {
949
949
  sel.removeAllRanges();
950
950
  sel.addRange(range);
951
951
  }
952
- function useScreenplayEditor() {
952
+ function useScreenplayEditor(options) {
953
953
  const [blocks, setBlocks] = react.useState(initialBlocks);
954
954
  const refs = react.useRef({});
955
955
  const [focusedBlockId, setFocusedBlockId] = react.useState(
@@ -959,6 +959,7 @@ function useScreenplayEditor() {
959
959
  const [showSuggestions, setShowSuggestions] = react.useState(false);
960
960
  const [showExtensionSuggestions, setShowExtensionSuggestions] = react.useState(false);
961
961
  const blurTimeout = react.useRef(null);
962
+ const loadedUrlRef = react.useRef(null);
962
963
  const characterExtensions = react.useMemo(
963
964
  () => ["(V.O.)", "(O.S.)", "(O.C.)", "(SUBTITLE)", "(CONT'D)"],
964
965
  []
@@ -1388,6 +1389,92 @@ function useScreenplayEditor() {
1388
1389
  setShowExtensionSuggestions(false);
1389
1390
  }, 200);
1390
1391
  }, []);
1392
+ const loadFromUrl = react.useCallback(
1393
+ async (url, fetchOptions = {}) => {
1394
+ var _a;
1395
+ try {
1396
+ const response = await fetch(url, fetchOptions);
1397
+ if (!response.ok) {
1398
+ throw new Error(
1399
+ `[useScreenplayEditor] Failed to fetch script. HTTP Status: ${response.status}`
1400
+ );
1401
+ }
1402
+ let text = await response.text();
1403
+ let preParsedBlocks = void 0;
1404
+ let scriptContent = text;
1405
+ if (text.includes('class="divtype') || url.toLowerCase().includes(".sbx")) {
1406
+ if (text.includes("<div")) {
1407
+ const textarea = document.createElement("textarea");
1408
+ textarea.innerHTML = text;
1409
+ text = textarea.value;
1410
+ }
1411
+ const parser = new DOMParser();
1412
+ const doc = parser.parseFromString(text, "text/html");
1413
+ const divs = Array.from(doc.querySelectorAll("div"));
1414
+ const parsed = [];
1415
+ const typeMap = {
1416
+ divtype0: "SCENE_HEADING",
1417
+ divtype2: "ACTION",
1418
+ divtype3: "CHARACTER",
1419
+ divtype4: "PARENTHETICAL",
1420
+ divtype5: "DIALOGUE",
1421
+ divtype6: "TRANSITION"
1422
+ };
1423
+ divs.forEach((div) => {
1424
+ var _a2;
1425
+ let divText = ((_a2 = div.textContent) == null ? void 0 : _a2.trim()) || "";
1426
+ if (!divText) return;
1427
+ let type = "ACTION";
1428
+ for (const className of Array.from(div.classList)) {
1429
+ if (typeMap[className]) {
1430
+ type = typeMap[className];
1431
+ break;
1432
+ }
1433
+ }
1434
+ const block = { type, text: divText };
1435
+ if (type === "SCENE_HEADING") {
1436
+ const sceneNum = div.getAttribute("data-scene");
1437
+ if (sceneNum) block.sceneNumber = sceneNum;
1438
+ let parsedText = divText;
1439
+ const typeMatch = parsedText.match(/^(INT\/EXT|INT|EXT)\.?\s+/i);
1440
+ if (typeMatch) {
1441
+ let sType = typeMatch[1].toUpperCase();
1442
+ if (!sType.endsWith(".")) sType += ".";
1443
+ block.sceneType = sType;
1444
+ parsedText = parsedText.substring(typeMatch[0].length).trim();
1445
+ }
1446
+ const timeMatch = parsedText.match(/\s+-\s+([^-]+)$/);
1447
+ if (timeMatch) {
1448
+ block.timeOfDay = timeMatch[1].trim().toUpperCase();
1449
+ parsedText = parsedText.substring(0, timeMatch.index).trim();
1450
+ }
1451
+ block.text = parsedText;
1452
+ }
1453
+ parsed.push(block);
1454
+ });
1455
+ if (parsed.length > 0) {
1456
+ preParsedBlocks = parsed;
1457
+ scriptContent = "";
1458
+ }
1459
+ }
1460
+ const filename = ((_a = url.split("/").pop()) == null ? void 0 : _a.replace(/\.sbx$/i, "")) || "Imported from URL";
1461
+ handleScriptImport(filename, scriptContent, preParsedBlocks);
1462
+ } catch (error) {
1463
+ console.error(
1464
+ "[useScreenplayEditor] Error loading script from URL:",
1465
+ error
1466
+ );
1467
+ throw error;
1468
+ }
1469
+ },
1470
+ [handleScriptImport]
1471
+ );
1472
+ react.useEffect(() => {
1473
+ if ((options == null ? void 0 : options.initialUrl) && options.initialUrl !== loadedUrlRef.current) {
1474
+ loadedUrlRef.current = options.initialUrl;
1475
+ loadFromUrl(options.initialUrl, options.fetchOptions);
1476
+ }
1477
+ }, [options == null ? void 0 : options.initialUrl, options == null ? void 0 : options.fetchOptions, loadFromUrl]);
1391
1478
  return {
1392
1479
  blocks,
1393
1480
  refs,
@@ -1407,7 +1494,8 @@ function useScreenplayEditor() {
1407
1494
  handleScriptImport,
1408
1495
  handleSceneNumberChange,
1409
1496
  handleFocus,
1410
- handleBlur
1497
+ handleBlur,
1498
+ loadFromUrl
1411
1499
  };
1412
1500
  }
1413
1501
  var handleSaveAsPdf = (blocks, sceneNumbers) => {