@kitschpatrol/tldraw-cli 3.1.0 → 3.2.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.
@@ -1,8 +1,7 @@
1
1
  export default class LocalTldrawServer {
2
2
  private readonly tldrData?;
3
- verbose: boolean;
4
3
  private server?;
5
- constructor(tldrData?: string | undefined, verbose?: boolean);
4
+ constructor(tldrData?: string | undefined);
6
5
  close(): void;
7
6
  start(): Promise<void>;
8
7
  get href(): string;
@@ -1,13 +1,12 @@
1
1
  import type { TldrawFormat } from './tldraw-to-image';
2
2
  export default class TldrawController {
3
3
  private readonly href;
4
- verbose: boolean;
5
4
  private page?;
6
5
  private isEmpty?;
7
6
  private browser?;
8
7
  private client?;
9
8
  private originalDarkMode?;
10
- constructor(href: string, verbose?: boolean);
9
+ constructor(href: string);
11
10
  private get isLocal();
12
11
  start(): Promise<void>;
13
12
  close(): Promise<void>;
@@ -0,0 +1,8 @@
1
+ export declare let cli: boolean;
2
+ export declare let verbose: boolean;
3
+ export declare function setCli(value: boolean): void;
4
+ export declare function setVerbose(value: boolean): void;
5
+ export declare function log(...data: unknown[]): void;
6
+ export declare function warn(...data: unknown[]): void;
7
+ export declare function error(...data: unknown[]): void;
8
+ export declare function info(...data: unknown[]): void;
@@ -312,4 +312,4 @@ Error generating stack: `+s.message+`
312
312
  font-weight: ${m.weight};
313
313
  font-style: ${m.style};
314
314
  src: url("${o}") format("woff2")
315
- }`,()=>{document.fonts.delete(m),h=!0}},[e,n]),t};function Eee(e){return{draw:{url:e.fonts.draw},serif:{url:e.fonts.serif},sansSerif:{url:e.fonts.sansSerif},monospace:{url:e.fonts.monospace}}}function _ee(e){const n=x.useMemo(()=>Eee(e),[e]),t=[Fd("tldraw_draw",n.draw),Fd("tldraw_serif",n.serif),Fd("tldraw_sans",n.sansSerif),Fd("tldraw_mono",n.monospace)];return{error:t.some(r=>r===1),done:!t.some(r=>r===2)}}function Iee(e){const{children:n,maxImageDimension:t,maxAssetSize:r,acceptedImageMimeTypes:o,acceptedVideoMimeTypes:s,onMount:i,...a}=e,l=i7(a.components??{}),c=Cx(a.shapeUtils??[]),u=Cx(a.tools??[]),d={initialState:"select",...a,components:x.useMemo(()=>({Scribble:vb,CollaboratorScribble:vb,SelectionForeground:gU,SelectionBackground:pU,Handles:aU,HoveredShapeIndicator:lU,...l}),[l]),shapeUtils:x.useMemo(()=>[..._V,...c],[c]),tools:x.useMemo(()=>[...BV,...iH,...u],[u])},h=DG(a.assetUrls),{done:p,error:m}=_ee(h);return m?g.jsx(n7,{children:"Could not load assets. Please refresh the page."}):p?g.jsx(Qj,{...d,children:g.jsxs(nee,{...d,children:[g.jsx(Pee,{children:g.jsx(Rv,{})}),g.jsx(Tee,{maxImageDimension:t,maxAssetSize:r,acceptedImageMimeTypes:o,acceptedVideoMimeTypes:s,onMount:i}),n]})}):g.jsx(bk,{children:"Loading assets..."})}function Tee({maxImageDimension:e=1e3,maxAssetSize:n=10*1024*1024,acceptedImageMimeTypes:t=["image/jpeg","image/png","image/gif","image/svg+xml"],acceptedVideoMimeTypes:r=["video/mp4","video/quicktime"],onMount:o}){const s=V(),i=$ee(a=>{const l=[];return l.push(...IV(a)),GU(a,{maxImageDimension:e,maxAssetSize:n,acceptedImageMimeTypes:t,acceptedVideoMimeTypes:r}),l.push(o==null?void 0:o(a)),()=>{l.forEach(c=>c==null?void 0:c())}});return x.useLayoutEffect(()=>{if(s)return i==null?void 0:i(s)},[s,i]),null}function $ee(e){const n=x.useRef();return x.useLayoutEffect(()=>{n.current=e}),x.useDebugValue(e),x.useCallback((...t)=>{const r=n.current;return _o(r,"fn does not exist"),r(...t)},[])}const Mee=1,Aee=be({tldrawFileFormatVersion:P5,schema:be({schemaVersion:Uu,storeVersion:Uu,recordVersions:xy(ge,be({version:Uu,subTypeVersions:xy(ge,Uu).optional(),subTypeKey:ge.optional()}))}),records:Xt(be({id:ge,typeName:ge}).allowUnknownProperties())});function Oee(e){var n;try{return!!((n=e.document)!=null&&n.version)}catch{return!1}}function Ree({json:e,schema:n}){let t;try{t=Aee.validate(JSON.parse(e))}catch(o){try{if(t=JSON.parse(e),Oee(t))return Gs.err({type:"v1File",data:t})}catch{}return Gs.err({type:"notATldrawFile",cause:o})}if(t.tldrawFileFormatVersion>Mee)return Gs.err({type:"fileFormatVersionTooNew",version:t.tldrawFileFormatVersion});let r;try{const o=Object.fromEntries(t.records.map(s=>[s.id,s]));r=n.migrateStoreSnapshot({store:o,schema:t.schema})}catch(o){return Gs.err({type:"invalidRecords",cause:o})}if(r.type==="error")return Gs.err({type:"migrationFailed",reason:r.reason});try{return Gs.ok(vk({initialData:r.value,schema:n}))}catch(o){return Gs.err({type:"invalidRecords",cause:o})}}function Dee(){const[e,n]=x.useState();function t(r){e===void 0?fetch("/tldr-data").then(async o=>{if(!o.ok){console.log(`No tldr data to load from local endpoint (${o.status})`);return}return o.text()}).then(o=>{if(o===void 0)return;const s=Ree({json:o,schema:r.store.schema});s.ok?(console.log("Loaded tldr file from local endpoint"),n(s.value)):console.error(`Error parsing tldr file: ${String(s.error.type)}`)}).catch(o=>{console.error("Error fetching data:",o)}):(r.updateViewportScreenBounds(),r.zoomToFit(),window.app.clearOpenMenus())}return g.jsx("div",{style:{inset:0,position:"fixed"},children:g.jsx(Iee,{assetUrls:LA(),onMount:t,store:e})})}var cv={},zC=il;cv.createRoot=zC.createRoot,cv.hydrateRoot=zC.hydrateRoot;cv.createRoot(document.querySelector("#root")).render(g.jsx(ne.StrictMode,{children:g.jsx(Dee,{})}));
315
+ }`,()=>{document.fonts.delete(m),h=!0}},[e,n]),t};function Eee(e){return{draw:{url:e.fonts.draw},serif:{url:e.fonts.serif},sansSerif:{url:e.fonts.sansSerif},monospace:{url:e.fonts.monospace}}}function _ee(e){const n=x.useMemo(()=>Eee(e),[e]),t=[Fd("tldraw_draw",n.draw),Fd("tldraw_serif",n.serif),Fd("tldraw_sans",n.sansSerif),Fd("tldraw_mono",n.monospace)];return{error:t.some(r=>r===1),done:!t.some(r=>r===2)}}function Iee(e){const{children:n,maxImageDimension:t,maxAssetSize:r,acceptedImageMimeTypes:o,acceptedVideoMimeTypes:s,onMount:i,...a}=e,l=i7(a.components??{}),c=Cx(a.shapeUtils??[]),u=Cx(a.tools??[]),d={initialState:"select",...a,components:x.useMemo(()=>({Scribble:vb,CollaboratorScribble:vb,SelectionForeground:gU,SelectionBackground:pU,Handles:aU,HoveredShapeIndicator:lU,...l}),[l]),shapeUtils:x.useMemo(()=>[..._V,...c],[c]),tools:x.useMemo(()=>[...BV,...iH,...u],[u])},h=DG(a.assetUrls),{done:p,error:m}=_ee(h);return m?g.jsx(n7,{children:"Could not load assets. Please refresh the page."}):p?g.jsx(Qj,{...d,children:g.jsxs(nee,{...d,children:[g.jsx(Pee,{children:g.jsx(Rv,{})}),g.jsx(Tee,{maxImageDimension:t,maxAssetSize:r,acceptedImageMimeTypes:o,acceptedVideoMimeTypes:s,onMount:i}),n]})}):g.jsx(bk,{children:"Loading assets..."})}function Tee({maxImageDimension:e=1e3,maxAssetSize:n=10*1024*1024,acceptedImageMimeTypes:t=["image/jpeg","image/png","image/gif","image/svg+xml"],acceptedVideoMimeTypes:r=["video/mp4","video/quicktime"],onMount:o}){const s=V(),i=$ee(a=>{const l=[];return l.push(...IV(a)),GU(a,{maxImageDimension:e,maxAssetSize:n,acceptedImageMimeTypes:t,acceptedVideoMimeTypes:r}),l.push(o==null?void 0:o(a)),()=>{l.forEach(c=>c==null?void 0:c())}});return x.useLayoutEffect(()=>{if(s)return i==null?void 0:i(s)},[s,i]),null}function $ee(e){const n=x.useRef();return x.useLayoutEffect(()=>{n.current=e}),x.useDebugValue(e),x.useCallback((...t)=>{const r=n.current;return _o(r,"fn does not exist"),r(...t)},[])}const Mee=1,Aee=be({tldrawFileFormatVersion:P5,schema:be({schemaVersion:Uu,storeVersion:Uu,recordVersions:xy(ge,be({version:Uu,subTypeVersions:xy(ge,Uu).optional(),subTypeKey:ge.optional()}))}),records:Xt(be({id:ge,typeName:ge}).allowUnknownProperties())});function Oee(e){var n;try{return!!((n=e.document)!=null&&n.version)}catch{return!1}}function Ree({json:e,schema:n}){let t;try{t=Aee.validate(JSON.parse(e))}catch(o){try{if(t=JSON.parse(e),Oee(t))return Gs.err({type:"v1File",data:t})}catch{}return Gs.err({type:"notATldrawFile",cause:o})}if(t.tldrawFileFormatVersion>Mee)return Gs.err({type:"fileFormatVersionTooNew",version:t.tldrawFileFormatVersion});let r;try{const o=Object.fromEntries(t.records.map(s=>[s.id,s]));r=n.migrateStoreSnapshot({store:o,schema:t.schema})}catch(o){return Gs.err({type:"invalidRecords",cause:o})}if(r.type==="error")return Gs.err({type:"migrationFailed",reason:r.reason});try{return Gs.ok(vk({initialData:r.value,schema:n}))}catch(o){return Gs.err({type:"invalidRecords",cause:o})}}function Dee(){const[e,n]=x.useState();function t(r){e===void 0?fetch("/tldr-data").then(async o=>{if(!o.ok){console.log(`No tldr data to load from local endpoint (${o.status})`);return}return o.text()}).then(o=>{if(o===void 0)return;const s=Ree({json:o,schema:r.store.schema});s.ok?(console.log("Loaded tldr file from local endpoint"),n(s.value)):console.error(`Couldn't parse tldr file: ${String(s.error.type)}`)}).catch(o=>{console.error("Couldn't fetch data:",o)}):(r.updateViewportScreenBounds(),r.zoomToFit(),window.app.clearOpenMenus())}return g.jsx("div",{style:{inset:0,position:"fixed"},children:g.jsx(Iee,{assetUrls:LA(),onMount:t,store:e})})}var cv={},zC=il;cv.createRoot=zC.createRoot,cv.hydrateRoot=zC.hydrateRoot;cv.createRoot(document.querySelector("#root")).render(g.jsx(ne.StrictMode,{children:g.jsx(Dee,{})}));
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>tldraw via tldraw-cli</title>
7
- <script type="module" crossorigin src="/assets/index-ehug49np.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-l3509weP.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-S3CdIkLU.css">
9
9
  </head>
10
10
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitschpatrol/tldraw-cli",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "type": "module",
5
5
  "description": "A tiny little CLI tool for exporting tldraw sketches to svg or png images.",
6
6
  "repository": {
@@ -56,6 +56,7 @@
56
56
  "@types/yargs": "^17.0.32",
57
57
  "@vitejs/plugin-react-swc": "^3.5.0",
58
58
  "bumpp": "^9.3.0",
59
+ "chalk": "^5.3.0",
59
60
  "cheerio": "1.0.0-rc.12",
60
61
  "esbuild": "^0.19.11",
61
62
  "eslint-plugin-react-hooks": "^4.6.0",
@@ -64,6 +65,8 @@
64
65
  "nanoid": "^5.0.4",
65
66
  "open": "^10.0.3",
66
67
  "path-type": "^5.0.0",
68
+ "plur": "^5.1.0",
69
+ "pretty-ms": "^9.0.0",
67
70
  "react": "^18.2.0",
68
71
  "react-dom": "^18.2.0",
69
72
  "tsx": "^4.7.0",
package/readme.md CHANGED
@@ -44,9 +44,9 @@ tldraw-cli <command>
44
44
 
45
45
  The top-level collection of CLI tools for tldraw.
46
46
 
47
- | Argument | Description |
48
- | --------- | ------------------- |
49
- | `command` | `export` or `open`. |
47
+ | Argument | Description |
48
+ | --------- | ----------------------------------------------------------------- |
49
+ | `command` | CLI tools for tldraw. Available commands are `export` and `open`. |
50
50
 
51
51
  | Option | Alias | Description Value |
52
52
  | ----------- | ----- | -------------------- |
@@ -56,42 +56,40 @@ The top-level collection of CLI tools for tldraw.
56
56
  #### Command: Export
57
57
 
58
58
  ```sh
59
- tldraw-cli export <file-or-url>
59
+ tldraw-cli export <files-or-urls..>
60
60
  ```
61
61
 
62
62
  Export a tldraw `.tldr` file or tldraw\.com URL to SVG, PNG, and other formats.
63
63
 
64
- | Argument | Description |
65
- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
66
- | `<file-or-url>` | The sketch to export either a path to a local `.tldr` file, or a tldraw\.com sketch URL. Prints the absolute path(s) to the exported image(s) to `stdout`. |
67
-
68
- | Option | Alias | Description Value | Default Value |
69
- | ------------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
70
- | `--format <string>` | `-f` | Output image format, one of `svg`, `png`, `json`, or `tldr`. | `svg` |
71
- | `--dark-mode ` | `-d` | Output a dark theme version of the image. | `false` |
72
- | `--transparent ` | `-t` | Output an image with a transparent background. | `false` |
73
- | `--output <string>` | `-o` | Output directory. | `./` |
74
- | `--name <string>` | `-n` | Output file name without extension; by default the original file name or URL id is used. | |
75
- | `--frames <array?>` | | Export each sketch "frame" as a separate image. Pass one or more frame names or IDs to export specific frames, or skip the arguments to export all frames. | `false` |
76
- | `--strip-style` | | Remove `<style>` elements from SVG output, useful to lighten the load of embedded fonts if you intend to provide your own stylesheets. | `false` |
77
- | `--print` | `-p` | Print the exported image(s) to stdout instead of saving to a file. Incompatible with --output, and overrides --name. PNGs are printed as base64-encoded strings. | `false` |
78
- | `--verbose` | | Enable verbose output. | `false` |
64
+ | Argument | Description |
65
+ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
66
+ | `<files-or-urls..>` | The tldraw sketch to export. May be one or more paths to local `.tldr` files, or tldraw.com sketch URLs. Accepts a mix of both file paths and URLs, and supports glob matching via your shell. Prints the absolute path(s) to the exported image(s) to `stdout`. |
67
+
68
+ | Option | Alias | Description Value | Default Value |
69
+ | ------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
70
+ | `--format [string]` | `-f` | Output image format, one of `svg`, `png`, `json`, or `tldr`. | `svg` |
71
+ | `--output <string>` | `-o` | Output image directory. | `./` |
72
+ | `--name <string>` | `-n` | Output image name (without extension). By default the original file name or URL id is used. | |
73
+ | `--frames [array]` | | Export each sketch "frame" as a separate image. Pass one or more frame names or IDs to export specific frames, or skip the arguments to export all frames. | `false` |
74
+ | `--transparent ` | `-t` | Export an image with a transparent background. | `false` |
75
+ | `--dark-mode ` | `-d` | Export a dark theme version of the image. | `false` |
76
+ | `--strip-style` | | Remove `<style>` elements from SVG output, useful to lighten the load of embedded fonts if you intend to provide your own stylesheets. Applies to SVG output only. | `false` |
77
+ | `--print` | `-p` | Print the exported image(s) to stdout instead of saving to a file. Incompatible with `--output`, and overrides `--name`. PNGs are printed as base64-encoded strings. | `false` |
78
+ | `--verbose` | | Enable verbose logging. All verbose logs and prefixed with their log level and are printed to `stderr` for ease of redirection. | `false` |
79
79
 
80
80
  #### Command: Open
81
81
 
82
82
  ```sh
83
- tldraw-cli open [file-or-url]
83
+ tldraw-cli open [files-or-urls..]
84
84
  ```
85
85
 
86
- Open a tldraw `.tldr` file or tldraw\.com URL your default browser. Uses a locally-hosted instance of tldraw. Call `open` without an argument to open a blank sketch.
87
-
88
- Sketches opened via URL are copied to the local system, and will not be kept in sync with tldraw.com.
86
+ Open a tldraw `.tldr` file or tldraw\.com URL your default browser. Uses a locally-hosted instance of tldraw. Call `open` without an argument to open a blank sketch. Sketches opened via URL are temporarily copied to the local system, and will not be kept in sync with tldraw.com.
89
87
 
90
88
  _"Save as" support is not yet implemented in the local tldraw instance, so the `open` command is only recommended for viewing purposes at the moment._
91
89
 
92
- | Argument | Description |
93
- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
94
- | `[file-or-url]` | The `.tldr` file or tldraw\.com sketch url to open. Omit the argument to open a blank sketch. Prints the url of the local server to `stdout`. |
90
+ | Argument | Description |
91
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
92
+ | `[files-or-urls..]` | The `.tldr` file(s) or tldraw\.com sketch URL(s) to open. Omit the argument to open a blank sketch. Supports glob matching via your shell. Prints the URL of the local server to `stdout`. |
95
93
 
96
94
  No options.
97
95
 
@@ -306,6 +304,7 @@ The local instance of tldraw includes its assets dependencies, so the tool shoul
306
304
  This is a very minimal implementation. Current plans for future improvements include the following:
307
305
 
308
306
  - Add save button to local tldraw
307
+ - Accept globs and optimize batch processing with a single puppeteer instance
309
308
  - Add CLI tests
310
309
  - Implement the ability to export specific pages as separate image files
311
310
  - Add an option flag to set dpi when exporting to a bitmap format