@kitschpatrol/tldraw-cli 3.0.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,20 +1,19 @@
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>;
14
- download(output: string, filename: string, format: TldrawFormat, stripStyle: boolean): Promise<string[]>;
15
- downloadFrame(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, frameNameOrId: string): Promise<string[]>;
16
- downloadFrames(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, frameNamesOrIds: string[]): Promise<string[]>;
17
- downloadAllFrames(output: string, filename: string, format: TldrawFormat, stripStyle: boolean): Promise<string[]>;
13
+ download(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, print: boolean): Promise<string[]>;
14
+ downloadFrame(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, frameNameOrId: string, print: boolean): Promise<string[]>;
15
+ downloadFrames(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, frameNamesOrIds: string[], print: boolean): Promise<string[]>;
16
+ downloadAllFrames(output: string, filename: string, format: TldrawFormat, stripStyle: boolean, print: boolean): Promise<string[]>;
18
17
  setTransparency(transparent: boolean): Promise<void>;
19
18
  setDarkMode(darkMode: boolean): Promise<void>;
20
19
  private _download;
@@ -5,6 +5,7 @@ export type TldrawToImageOptions = {
5
5
  frames?: boolean | string[];
6
6
  name?: string;
7
7
  output?: string;
8
+ print?: boolean;
8
9
  stripStyle?: boolean;
9
10
  transparent?: boolean;
10
11
  verbose?: boolean;
@@ -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.0.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
@@ -34,7 +34,7 @@ npm install --global @kitschpatrol/tldraw-cli
34
34
 
35
35
  ### Invocation
36
36
 
37
- To leave room for future functionality, `tldraw-cli` exposes functionality under several sub-commands.
37
+ `tldraw-cli`'s functionality is organized into several sub-commands.
38
38
 
39
39
  #### Top-level
40
40
 
@@ -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,52 +56,51 @@ 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
- Export a tldraw ".tldr" file or tldraw\.com URL to an svg, png image, and other formats.
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 convert export an image 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`. |
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
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, use the option flag alone to export all frames, or pass one or more frame names or IDs, slugified frame names will also match. | `false` |
76
- | `--strip-style` | | Remove `<style>` elements from SVG output, useful to lighten the load of embedded fonts or if you are going to provide your own stylesheet for the SVG. | `false` |
77
- | `--verbose` | | Enable verbose output. | `false` |
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` |
78
79
 
79
80
  #### Command: Open
80
81
 
81
82
  ```sh
82
- tldraw-cli open [file-or-url]
83
+ tldraw-cli open [files-or-urls..]
83
84
  ```
84
85
 
85
- 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.
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.
86
87
 
87
- Sketches opened via URL are copied to the local system, and will not be kept in sync with tldraw.com.
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._
88
89
 
89
- "Save as" support is not yet implemented in the local tldraw instance, so it's recommended for viewing purposes only at the moment.
90
-
91
- | Argument | Description |
92
- | --------------- | ------------------------------------------------------------------------------------------------------------------------------ |
93
- | `[file-or-url]` | The .tldr file or tldraw\.com sketch url to open. Omit 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`. |
94
93
 
95
94
  No options.
96
95
 
97
96
  ## Examples
98
97
 
99
- ### Basic .tldr file image export
98
+ ### Basic `.tldr` file image export
100
99
 
101
- To export the file `your-drawing.tldr` to an svg named `your-drawing.svg` in the current working directory, run the following command. Note that the default output format is SVG, and the default export location is the current working directory.
100
+ To export the file `your-drawing.tldr` to an SVG named `your-drawing.svg` in the current working directory, run the following command. Note that the default output format is SVG, and the default export location is the current working directory.
102
101
 
103
102
  ```sh
104
- npx @kitschpatrol/tldraw-cli export your-drawing.tldr
103
+ tldraw-cli export your-drawing.tldr
105
104
  ```
106
105
 
107
106
  The file will retain its original name, e.g. `your-drawing.svg`
@@ -109,27 +108,27 @@ The file will retain its original name, e.g. `your-drawing.svg`
109
108
  ### Basic tldraw\.com image download
110
109
 
111
110
  ```sh
112
- npx @kitschpatrol/tldraw-cli export https://www.tldraw.com/s/v2_c_JsxJk8dag6QsrqExukis4
111
+ tldraw-cli export https://www.tldraw.com/s/v2_c_JsxJk8dag6QsrqExukis4
113
112
  ```
114
113
 
115
- The tldraw URL's id (e.g. `v2_c_JsxJk8dag6QsrqExukis4`) will be used for the file name.
114
+ The tldraw.com URL's id (e.g. `v2_c_JsxJk8dag6QsrqExukis4`) will be used for the file name.
116
115
 
117
116
  This is approximately equivalent to clicking the tldraw\.com "☰ → Edit → Export As → SVG" menu item.
118
117
 
119
118
  ### Export a remote tldraw\.com image to a local .tldr file
120
119
 
121
120
  ```sh
122
- npx @kitschpatrol/tldraw-cli export https://www.tldraw.com/s/v2_c_JsxJk8dag6QsrqExukis4 --format tldr
121
+ tldraw-cli export https://www.tldraw.com/s/v2_c_JsxJk8dag6QsrqExukis4 --format tldr
123
122
  ```
124
123
 
125
124
  This is approximately equivalent to clicking the tldraw\.com "☰ → File → Save a copy" menu item.
126
125
 
127
126
  Note that using `--format tldr` with a _file path_ instead of a _URL_ will still send the file through the pipeline, but it's effectively a no-op. (Except perhaps rare edge cases where tldraw performs a file format version migration).
128
127
 
129
- ### Export to a specific format
128
+ ### Export to a specific image / file format
130
129
 
131
130
  ```sh
132
- npx @kitschpatrol/tldraw-cli export your-drawing.tldr --format png
131
+ tldraw-cli export your-drawing.tldr --format png
133
132
  ```
134
133
 
135
134
  This is approximately equivalent to clicking the tldraw\.com "☰ → Edit → Export As → PNG" menu item.
@@ -137,7 +136,7 @@ This is approximately equivalent to clicking the tldraw\.com "☰ → Edit → E
137
136
  ### Export with a transparent background
138
137
 
139
138
  ```sh
140
- npx @kitschpatrol/tldraw-cli export your-drawing.tldr --transparent --format png
139
+ tldraw-cli export your-drawing.tldr --transparent --format png
141
140
  ```
142
141
 
143
142
  This is approximately equivalent to checking the tldraw\.com "☰ → Edit → Export As → ☐ Transparent" menu item.
@@ -145,7 +144,7 @@ This is approximately equivalent to checking the tldraw\.com "☰ → Edit → E
145
144
  ### Export to a specific destination
146
145
 
147
146
  ```sh
148
- npx @kitschpatrol/tldraw-cli export your-drawing.tldr --output ~/Desktop
147
+ tldraw-cli export your-drawing.tldr --output ~/Desktop
149
148
  ```
150
149
 
151
150
  Exports to `~/Desktop/your-drawing.svg`
@@ -153,15 +152,15 @@ Exports to `~/Desktop/your-drawing.svg`
153
152
  ### Export to a specific destination and filename
154
153
 
155
154
  ```sh
156
- npx @kitschpatrol/tldraw-cli export your-drawing.tldr --output ~/Desktop --name not-your-drawing
155
+ tldraw-cli export your-drawing.tldr --output ~/Desktop --name not-your-drawing
157
156
  ```
158
157
 
159
158
  Exports to `~/Desktop/not-your-drawing.svg`
160
159
 
161
- ### Export all frames from a tldraw URL
160
+ ### Export all frames from a tldraw.com URL
162
161
 
163
162
  ```sh
164
- npx @kitschpatrol/tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames
163
+ tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames
165
164
  ```
166
165
 
167
166
  The exported files will be suffixed with their frame name, e.g.:
@@ -174,33 +173,45 @@ The frame name will be slugified.
174
173
 
175
174
  It's possible in tldraw to give multiple frames in a single sketch the same name. In these cases, the frame ID is used in addition to the name to ensure unique output file names.
176
175
 
177
- ### Export a specific frame from a tldraw URL
176
+ ### Export a specific frame from a tldraw.com URL
177
+
178
+ ```sh
179
+ tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames "Frame 3"
180
+ ```
181
+
182
+ ### Export multiple frames from a tldraw.com URL
178
183
 
179
184
  ```sh
180
- npx @kitschpatrol/tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames "Frame 1" "Frame 3"
185
+ tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames "Frame 1" "Frame 3"
181
186
  ```
182
187
 
183
188
  ### Export to JSON
184
189
 
185
190
  ```sh
186
- npx @kitschpatrol/tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --frames "Frame 1" "Frame 3"
191
+ tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --format "json"
187
192
  ```
188
193
 
189
- The .tldr file format is also JSON under the covers, but the `--format json` flag will yield a slightly different format than `--format tldr`. `--format json` is equivalent to what's produced via the tldraw\.com "☰ → Edit → Export As → JSON" menu item.
194
+ The `.tldr` file format is also JSON under the covers, but the `--format json` flag will yield a slightly different format than `--format tldr`. `--format json` is equivalent to what's produced via the tldraw\.com "☰ → Edit → Export As → JSON" menu item.
190
195
 
191
196
  I'm not completely clear on the use-case for this format, but since tldr.com supports it, so too shall `tldraw-cli`.
192
197
 
193
- ### Open a tldraw URL
198
+ ### Write an SVG to stdout
199
+
200
+ ```sh
201
+ tldraw-cli export https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw --print
202
+ ```
203
+
204
+ ### Open a tldraw.com URL
194
205
 
195
206
  ```sh
196
- npx @kitschpatrol/tldraw-cli open https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw
207
+ tldraw-cli open https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw
197
208
  ```
198
209
 
199
210
  The remote sketch is copied to a locally-hosted instance of tldraw, which is then opened in your default browser.
200
211
 
201
212
  ## API usage
202
213
 
203
- The `export` command's functionality is also provided as a module for use in TypeScript or JavaScript Node projects.
214
+ The `export` command's functionality is also provided in module form for use in TypeScript or JavaScript Node projects.
204
215
 
205
216
  The library exports a single async function, `tldrawToImage`, which takes an options argument mirroring the arguments available via the command line. The same default values apply:
206
217
 
@@ -234,10 +245,10 @@ import { tldrawToImage } from '@kitschpatrol/tldraw-cli'
234
245
  const [imagePath] = await tldrawToImage('./some-file.tldr', { format: 'png', output: './' })
235
246
  console.log(`Wrote image to: "${imagePath}"`)
236
247
 
237
- // Convert a remote tldraw URL to SVG
248
+ // Convert a remote tldraw.com URL to SVG
238
249
  await tldrawToImage('https://www.tldraw.com/s/v2_c_JsxJk8dag6QsrqExukis4')
239
250
 
240
- // Convert all frames from a single tldraw URL to separate SVGs
251
+ // Convert all frames from a single tldraw.com URL to separate SVGs
241
252
  // When the `frames` option is set, the function returns an array
242
253
  // of resulting file paths, instead of a solitary string
243
254
  const framePathsArray = await tldrawToImage('https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw', {
@@ -245,7 +256,7 @@ const framePathsArray = await tldrawToImage('https://www.tldraw.com/s/v2_c_FI5RY
245
256
  })
246
257
  console.log(`Wrote frames to: "${framePathsArray}"`)
247
258
 
248
- // Convert a specific frame from a tldraw URL to a PNG
259
+ // Convert a specific frame from a tldraw.com URL to a PNG
249
260
  await tldrawToImage('https://www.tldraw.com/s/v2_c_FI5RYWbdpAtjsy4OIKrKw', {
250
261
  frames: ['Frame 3'],
251
262
  format: 'png',
@@ -293,10 +304,13 @@ The local instance of tldraw includes its assets dependencies, so the tool shoul
293
304
  This is a very minimal implementation. Current plans for future improvements include the following:
294
305
 
295
306
  - Add save button to local tldraw
307
+ - Accept globs and optimize batch processing with a single puppeteer instance
296
308
  - Add CLI tests
297
309
  - Implement the ability to export specific pages as separate image files
298
310
  - Add an option flag to set dpi when exporting to a bitmap format
299
311
  - Additional commands beyond sketch conversion / export?
312
+ - There's room for optimization in how tldraw functions are passed to Puppeteer
313
+ - There's room for optimization in the `--print` option implementation
300
314
 
301
315
  Any other suggestions are welcome.
302
316