@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 +92 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +92 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -21,7 +21,11 @@ declare const blockStyles: Record<BlockType, {
|
|
|
21
21
|
inputStyle: React.CSSProperties;
|
|
22
22
|
}>;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
interface UseScreenplayEditorOptions {
|
|
25
|
+
initialUrl?: string;
|
|
26
|
+
fetchOptions?: RequestInit;
|
|
27
|
+
}
|
|
28
|
+
declare function useScreenplayEditor(options?: UseScreenplayEditorOptions): {
|
|
25
29
|
blocks: Block[];
|
|
26
30
|
refs: React.RefObject<Record<string, HTMLDivElement | null>>;
|
|
27
31
|
focusedBlockId: string;
|
|
@@ -41,6 +45,7 @@ declare function useScreenplayEditor(): {
|
|
|
41
45
|
handleSceneNumberChange: (id: string, newNumber: string) => void;
|
|
42
46
|
handleFocus: (id: string) => void;
|
|
43
47
|
handleBlur: (id: string) => void;
|
|
48
|
+
loadFromUrl: (url: string, fetchOptions?: RequestInit) => Promise<void>;
|
|
44
49
|
};
|
|
45
50
|
|
|
46
51
|
type ScreenplayEditorViewProps = ReturnType<typeof useScreenplayEditor> & {
|
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,11 @@ declare const blockStyles: Record<BlockType, {
|
|
|
21
21
|
inputStyle: React.CSSProperties;
|
|
22
22
|
}>;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
interface UseScreenplayEditorOptions {
|
|
25
|
+
initialUrl?: string;
|
|
26
|
+
fetchOptions?: RequestInit;
|
|
27
|
+
}
|
|
28
|
+
declare function useScreenplayEditor(options?: UseScreenplayEditorOptions): {
|
|
25
29
|
blocks: Block[];
|
|
26
30
|
refs: React.RefObject<Record<string, HTMLDivElement | null>>;
|
|
27
31
|
focusedBlockId: string;
|
|
@@ -41,6 +45,7 @@ declare function useScreenplayEditor(): {
|
|
|
41
45
|
handleSceneNumberChange: (id: string, newNumber: string) => void;
|
|
42
46
|
handleFocus: (id: string) => void;
|
|
43
47
|
handleBlur: (id: string) => void;
|
|
48
|
+
loadFromUrl: (url: string, fetchOptions?: RequestInit) => Promise<void>;
|
|
44
49
|
};
|
|
45
50
|
|
|
46
51
|
type ScreenplayEditorViewProps = ReturnType<typeof useScreenplayEditor> & {
|
package/dist/index.js
CHANGED
|
@@ -312,7 +312,7 @@ function ScreenplayEditorView({
|
|
|
312
312
|
const link = document.createElement("link");
|
|
313
313
|
link.id = fontId;
|
|
314
314
|
link.rel = "stylesheet";
|
|
315
|
-
link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime&display=swap";
|
|
315
|
+
link.href = "https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap";
|
|
316
316
|
document.head.appendChild(link);
|
|
317
317
|
}
|
|
318
318
|
}, []);
|
|
@@ -360,7 +360,7 @@ function ScreenplayEditorView({
|
|
|
360
360
|
{
|
|
361
361
|
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",
|
|
362
362
|
style: {
|
|
363
|
-
fontFamily: "'Courier Prime', 'Courier New', Courier, monospace",
|
|
363
|
+
fontFamily: "var(--font-courier-prime, 'Courier Prime', 'Courier New', Courier, monospace)",
|
|
364
364
|
paddingLeft: "1.5in",
|
|
365
365
|
paddingRight: "1in",
|
|
366
366
|
paddingTop: "1in",
|
|
@@ -924,7 +924,7 @@ function setCaretPosition(element, offset) {
|
|
|
924
924
|
sel.removeAllRanges();
|
|
925
925
|
sel.addRange(range);
|
|
926
926
|
}
|
|
927
|
-
function useScreenplayEditor() {
|
|
927
|
+
function useScreenplayEditor(options) {
|
|
928
928
|
const [blocks, setBlocks] = useState(initialBlocks);
|
|
929
929
|
const refs = useRef({});
|
|
930
930
|
const [focusedBlockId, setFocusedBlockId] = useState(
|
|
@@ -934,6 +934,7 @@ function useScreenplayEditor() {
|
|
|
934
934
|
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
935
935
|
const [showExtensionSuggestions, setShowExtensionSuggestions] = useState(false);
|
|
936
936
|
const blurTimeout = useRef(null);
|
|
937
|
+
const loadedUrlRef = useRef(null);
|
|
937
938
|
const characterExtensions = useMemo(
|
|
938
939
|
() => ["(V.O.)", "(O.S.)", "(O.C.)", "(SUBTITLE)", "(CONT'D)"],
|
|
939
940
|
[]
|
|
@@ -1363,6 +1364,92 @@ function useScreenplayEditor() {
|
|
|
1363
1364
|
setShowExtensionSuggestions(false);
|
|
1364
1365
|
}, 200);
|
|
1365
1366
|
}, []);
|
|
1367
|
+
const loadFromUrl = useCallback(
|
|
1368
|
+
async (url, fetchOptions = {}) => {
|
|
1369
|
+
var _a;
|
|
1370
|
+
try {
|
|
1371
|
+
const response = await fetch(url, fetchOptions);
|
|
1372
|
+
if (!response.ok) {
|
|
1373
|
+
throw new Error(
|
|
1374
|
+
`[useScreenplayEditor] Failed to fetch script. HTTP Status: ${response.status}`
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
let text = await response.text();
|
|
1378
|
+
let preParsedBlocks = void 0;
|
|
1379
|
+
let scriptContent = text;
|
|
1380
|
+
if (text.includes('class="divtype') || url.toLowerCase().includes(".sbx")) {
|
|
1381
|
+
if (text.includes("<div")) {
|
|
1382
|
+
const textarea = document.createElement("textarea");
|
|
1383
|
+
textarea.innerHTML = text;
|
|
1384
|
+
text = textarea.value;
|
|
1385
|
+
}
|
|
1386
|
+
const parser = new DOMParser();
|
|
1387
|
+
const doc = parser.parseFromString(text, "text/html");
|
|
1388
|
+
const divs = Array.from(doc.querySelectorAll("div"));
|
|
1389
|
+
const parsed = [];
|
|
1390
|
+
const typeMap = {
|
|
1391
|
+
divtype0: "SCENE_HEADING",
|
|
1392
|
+
divtype2: "ACTION",
|
|
1393
|
+
divtype3: "CHARACTER",
|
|
1394
|
+
divtype4: "PARENTHETICAL",
|
|
1395
|
+
divtype5: "DIALOGUE",
|
|
1396
|
+
divtype6: "TRANSITION"
|
|
1397
|
+
};
|
|
1398
|
+
divs.forEach((div) => {
|
|
1399
|
+
var _a2;
|
|
1400
|
+
let divText = ((_a2 = div.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
1401
|
+
if (!divText) return;
|
|
1402
|
+
let type = "ACTION";
|
|
1403
|
+
for (const className of Array.from(div.classList)) {
|
|
1404
|
+
if (typeMap[className]) {
|
|
1405
|
+
type = typeMap[className];
|
|
1406
|
+
break;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
const block = { type, text: divText };
|
|
1410
|
+
if (type === "SCENE_HEADING") {
|
|
1411
|
+
const sceneNum = div.getAttribute("data-scene");
|
|
1412
|
+
if (sceneNum) block.sceneNumber = sceneNum;
|
|
1413
|
+
let parsedText = divText;
|
|
1414
|
+
const typeMatch = parsedText.match(/^(INT\/EXT|INT|EXT)\.?\s+/i);
|
|
1415
|
+
if (typeMatch) {
|
|
1416
|
+
let sType = typeMatch[1].toUpperCase();
|
|
1417
|
+
if (!sType.endsWith(".")) sType += ".";
|
|
1418
|
+
block.sceneType = sType;
|
|
1419
|
+
parsedText = parsedText.substring(typeMatch[0].length).trim();
|
|
1420
|
+
}
|
|
1421
|
+
const timeMatch = parsedText.match(/\s+-\s+([^-]+)$/);
|
|
1422
|
+
if (timeMatch) {
|
|
1423
|
+
block.timeOfDay = timeMatch[1].trim().toUpperCase();
|
|
1424
|
+
parsedText = parsedText.substring(0, timeMatch.index).trim();
|
|
1425
|
+
}
|
|
1426
|
+
block.text = parsedText;
|
|
1427
|
+
}
|
|
1428
|
+
parsed.push(block);
|
|
1429
|
+
});
|
|
1430
|
+
if (parsed.length > 0) {
|
|
1431
|
+
preParsedBlocks = parsed;
|
|
1432
|
+
scriptContent = "";
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
const filename = ((_a = url.split("/").pop()) == null ? void 0 : _a.replace(/\.sbx$/i, "")) || "Imported from URL";
|
|
1436
|
+
handleScriptImport(filename, scriptContent, preParsedBlocks);
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
console.error(
|
|
1439
|
+
"[useScreenplayEditor] Error loading script from URL:",
|
|
1440
|
+
error
|
|
1441
|
+
);
|
|
1442
|
+
throw error;
|
|
1443
|
+
}
|
|
1444
|
+
},
|
|
1445
|
+
[handleScriptImport]
|
|
1446
|
+
);
|
|
1447
|
+
useEffect(() => {
|
|
1448
|
+
if ((options == null ? void 0 : options.initialUrl) && options.initialUrl !== loadedUrlRef.current) {
|
|
1449
|
+
loadedUrlRef.current = options.initialUrl;
|
|
1450
|
+
loadFromUrl(options.initialUrl, options.fetchOptions);
|
|
1451
|
+
}
|
|
1452
|
+
}, [options == null ? void 0 : options.initialUrl, options == null ? void 0 : options.fetchOptions, loadFromUrl]);
|
|
1366
1453
|
return {
|
|
1367
1454
|
blocks,
|
|
1368
1455
|
refs,
|
|
@@ -1382,7 +1469,8 @@ function useScreenplayEditor() {
|
|
|
1382
1469
|
handleScriptImport,
|
|
1383
1470
|
handleSceneNumberChange,
|
|
1384
1471
|
handleFocus,
|
|
1385
|
-
handleBlur
|
|
1472
|
+
handleBlur,
|
|
1473
|
+
loadFromUrl
|
|
1386
1474
|
};
|
|
1387
1475
|
}
|
|
1388
1476
|
var handleSaveAsPdf = (blocks, sceneNumbers) => {
|