Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

excalidraw CLI #1261

Open
eunjae-lee opened this issue Apr 6, 2020 · 24 comments
Open

excalidraw CLI #1261

eunjae-lee opened this issue Apr 6, 2020 · 24 comments
Labels
enhancement New feature or request

Comments

@eunjae-lee
Copy link

Hi there,
I was wondering, what if we have a CLI for excalidraw?

excalidraw my-drawing.excalidraw

This will open a browser. If my-drawing.excalidraw already exists, it will load it.

When user clicks "save" button, it won't show the dialog but quietly save to my-drawing.excalidraw.

excalidraw my-drawing.excalidraw --export

with --export given, whenever user saves, the PNG version is exported as well.

excalidraw my-drawing.excalidraw --export images/my-drawing.png

I guess this can unblock new workflows, for example, for developers who want to have drawings in their git repository.

What do you think?

@j-f1 j-f1 added the enhancement New feature or request label Apr 6, 2020
@tommywalkie
Copy link

tommywalkie commented Jun 17, 2020

Hello there, I'm currently trying to implement it in the following repo : tommywalkie/excalidraw-cli.
A lot of CLI key features / refactoring / testing are still work-in-progress but it already works for directories with *.excalidraw files.

Early concept demo

demo

I may consider opening another issue to export some useful Excalidraw renderer methods and constants (especially drawElementOnCanvas()) so it can be easily integrated with this tool.

@j-f1
Copy link
Member

j-f1 commented Jun 17, 2020

Awesome @tommywalkie! When you feel like it’s more polished, would you be willing to perhaps collab with @MichaelDeBoey to use it for gatsby-remark-embedder? PR here: MichaelDeBoey/gatsby-remark-embedder#122

@MichaelDeBoey
Copy link

Would be awesome if we could use this inside gatsby-remark-embedder!

@tommywalkie
Copy link

Hi @MichaelDeBoey @j-f1, thanks for your response, I would be glad to collab once I polished the CLI. Initially, I was planning to make it work for Rollup (for a Sapper/Svelte blog) but implementing it as a Gatsby plugin would be awesome!

@tommywalkie
Copy link

tommywalkie commented Jun 20, 2020

The experimental CLI tool has been polished and is now close to a stable release.

NPM package : @tommywalkie/excalidraw-cli

Demo (0.3.2)

demo

$ excalidraw-cli --help
Parses Excalidraw JSON schemas into PNGs

USAGE
  $ excalidraw-cli [INPUT] [OUTPUT]

ARGUMENTS
  INPUT   [default: {cwd}] Excalidraw file path / directory path
  OUTPUT  [default: {cwd}] Output PNG file path / directory path

OPTIONS
  -h, --help     show CLI help
  -q, --quiet    disable console outputs
  -v, --version  show CLI version

@MichaelDeBoey @j-f1 I can start working on integrating it with Gatsby, I may have some questions, I may be wrong but considering this CLI tool can handle JSON data / Excalidraw files as input, wouldn't be better to create a Remark transformer instead ?

Or maybe we can add some JSON API endpoint to the Excalidraw app itself so the cli tool can handle it and use it in gatsby-remark-embedder ?

@MichaelDeBoey
Copy link

@tommywalkie What gatsby-remark-embedder is doing is given the URL for a certain thing (tweet/video/sandbox/...), transforming that link to the proper embed code.

So what I want to do is provide you with a link and get the correct embed code or svg back

@tommywalkie
Copy link

tommywalkie commented Jun 22, 2020

@MichaelDeBoey I think my question was poorly worded, I was wondering about how to actually get the JSON from Excalidraw, using some URL link. But now, after some researches, I became aware of https://json.excalidraw.com/api/v2/ and the exported method importFromBackend which may help with my issue.

export const importFromBackend = async (
id: string | null,
privateKey: string | undefined,
) => {

If this is what I think, I can add "Handle Excalidraw URLs as input" as a new CLI feature which then would provide a lightweight easy-to-use alternative to puppeteer in MichaelDeBoey/gatsby-remark-embedder#122

Untitled-2020-06-22-1104(1)

@MichaelDeBoey
Copy link

MichaelDeBoey commented Jun 22, 2020

@tommywalkie After talking to @j-f1 this is my understanding of how @excalidraw is working:

The thing I'm doing in the gatsby-remark-embedder plugin is either resolve the url myself or doing an API call
Now that's always to the oembed endpoint, but I can use another endpoint too of course

So I could use http://json.excalidraw.com, but then I have to do the decode of the blob myself

Another option would be to copy-paste the @excalidraw code, but that would cause problems each time you guys change something on your end so that's not the way we want to go.

So what I would like to have is having a lightweight way (this could be an npm package like excalidraw-cli) to pass the URL and get the decoded svg back.

@tommywalkie
Copy link

Another option would be to copy-paste the @excalidraw code, but that would cause problems each time you guys change something on your end so that's not the way we want to go.

@MichaelDeBoey I understand the issue very well, I already opened #1780 because I have this exact problem on the rendering process because I don't have access to drawElementOnCanvas() method, so I had to re-implement the renderer myself. 😅 It's doing fine currently but I wish I could rely on Excalidraw renderer directly for consistency, maybe I should open a PR about this.

@pomdtr
Copy link
Contributor

pomdtr commented Feb 12, 2021

Kroki-cli now supports SVG generation using excalidraw -> https://github.com/yuzutech/kroki-cli

@lipis
Copy link
Member

lipis commented Feb 14, 2021

I didn't follow the whole conversation.. but should we maybe create an official excalidraw/excalidraw-cli repo and take it from there? It seems that we need this tool.

@aur3l14no
Copy link

aur3l14no commented Oct 8, 2021

You can write one with @excaliraw/excaliraw.

excalidraw-export.js

#!/usr/bin/env node
const fs = require('fs-extra')
const path = require('path')
const Hook = require('require-in-the-middle')
const { Crypto } = require("@peculiar/webcrypto")
require('jsdom-global')()

global.crypto = new Crypto()
global.devicePixelRatio = 1

Hook(['@excalidraw/excalidraw'], function (exports, name, basedir) {
    const version = require(path.join(basedir, 'package.json')).version
    exports._version = version
    return exports
})

const Excalidraw = require('@excalidraw/excalidraw')

const readExcalidrawFile = async path => {
    try {
        const data = await fs.readFile(path, 'utf8')
        if (data) return JSON.parse(data)
    } catch (error) {
        console.error(error)
    }
}

const main = async () => {
    const [, , inputFile, outputDir, ..._] = process.argv
    const outputFile = path.format({
        dir: outputDir,
        name: path.basename(inputFile, '.excalidraw'),
        ext: '.svg'
    })
    var excalidrawFile = await readExcalidrawFile(inputFile)
    var svg = await Excalidraw.exportToSvg({ ...excalidrawFile })
    return await fs.writeFile(outputFile, svg.outerHTML, 'utf8')
}

main().then(() => process.exit())

And you may use it with excalidraw-export.js /path/to/input.excalidraw /export/dir.

I don't know much about JS so this code might appear ugly, but it works 😂.

@Timmmm
Copy link

Timmmm commented Apr 7, 2022

Here's another one I just found: https://github.com/JRJurman/excalidraw-to-svg

Seems to do things using JSDOM to create a fake page with an export script. Probably the best approach.

There are a couple of bugs in it but it did work after I fixed them.

@dwelle
Copy link
Member

dwelle commented Apr 7, 2022

Cool. Note that we will at some point be decoupling the renderer, UI, and the editor, so that you won't have to fake the DOM. But it's unclear when we'll be able to get to it.

@Timmmm
Copy link

Timmmm commented Apr 7, 2022

That would be great. Looking forward to a WASM based implementation with a pluggable rendering API! :-P

In the mean time I finally wrote a solid tool to do it. Thanks to @JRJurman - probably would have given up trying to figure JSDom out with his code. I manage to simplify it quite a lot, fix various issues, and also add PDF export and some workarounds for font issues (e.g. embedding them).

Here it is: 👉 https://www.npmjs.com/package/excalidraw_export 👈

npm install --global excalidraw_export
excalidraw_export foo.excalidraw

Please let me know if the npm install --global excalidraw_export command doesn't work! Annoying to test.

@godalming123
Copy link

godalming123 commented Nov 27, 2023

I feel like this could be achieved using the web's File System API, rathor then forcing the user to download a package. It may also be easier to implement using this API.

Offline functionality could then also be achieved using Progressive Web Apps.

Update: I see that excalidraw already works offline using PWAs.

I don't see any reason to implement a CLI instead of using web APIs, using web APIs also allows for functionality on every OS.

@realazthat
Copy link

I feel like this could be achieved using the web's File System API, rathor then forcing the user to download a package. It may also be easier to implement using this API.

Offline functionality could then also be achieved using Progressive Web Apps.

Update: I see that excalidraw already works offline using PWAs.

I don't see any reason to implement a CLI instead of using web APIs, using web APIs also allows for functionality on every OS.

Forgive my ignorance, how does one use a File System API or web API from another program or the command line?

@godalming123
Copy link

godalming123 commented Apr 8, 2024

How does one use a File System API or web API from another program or the command line?

I'm a bit confused about what you mean exactly.

  • Firstly, the web file system API cannot be used from the command line, and is only designed for use within websites.
  • Because the web's file system API can only be used within websites, this feature would have to be programmed into excalidraw itself. This would happen by editing the javascript (and possibly typescript) files within excalidraw's source code to use the web's file system API to save the file without querying the user (MDN docs to the web's file system API are linked in my previous comment)

@realazthat
Copy link

How does one use a File System API or web API from another program or the command line?

I'm a bit confused about what you mean exactly

Oh hmm I thought you were responding to the original post, and suggesting that the Filesystem APIs and Web APIs can solve the issue, and I was confused.

to save the file without querying the user.

To clarify, this is not the question of the OP. The OP is about being able to run the the entire excalidraw => image workflow from the command line, which would allow it to be used as a tool, like most such tools (e.g graphviz). Maybe I am misunderstanding your suggestion, my response is with the understanding that you are responding to the OP, which I am not sure is correct. Sorry if I am misunderstanding.

@godalming123
Copy link

I thought you were responding to the original post, and suggesting that the Filesystem APIs and Web APIs can solve the issue, and I was confused.

I was responding to the origianal post, saying that the web's filesystem API can be used to save a file without getting the user to enter the path of the file each time that it is saved. To be clear, this solution would not allow the user to use a CLI command, instead, the user would use the excalidraw website and click a button that could be titled "open excalidraw file from your computer and edit it". This button would use the web's file system API to allow the user to select a file that can be saved without the user having to select the path to the file everytime. This solution also wouldn't involve the user installing a CLI package. I think that using the web's filesystem API in excalidraw would be a better solution then the CLI command that was suggested in the original post becuase it means that the user does not have to install a package, and also becuase using the web's file system API would work on almost any web broweser, rathor then it having to be maintained for every OS and CPU architecture.

The OP is about being able to run the the entire excalidraw => image

The web's file system API could allow for this wihout a CLI command/package, but that is not what I suggested in my original comment

The thing that I was confused about was what exactly was meant by your question becuase the web's file system API cannot be used on the command line:

How does one use a File System API or web API from another program or the command line?

@realazthat
Copy link

The thing that I was confused about was what exactly was meant by your question becuase the web's file system API cannot be used on the command line:

Right, which is why i don't understand how your solution is a solution.

@realazthat
Copy link

To be clear: I am trying to use excalidraw in my book, which uses LaTeX tooling. For graphviz, I use dot, and it takes my .dot files, and turns them into SVGs. For other diagram formats I use other tools. For excalidraw, I have a .excalidraw file stored locally, and in git, but i have no way to generate the SVGs without doing that by hand which is quite labor intensive. "Use the website" is not a tool. Yes, I can use the website on any platform, but the OP is addressing usage as a tool, for automated conversion, so it can be used in an automated workflow.

@eunjae-lee
Copy link
Author

To be clear: I am trying to use excalidraw in my book, which uses LaTeX tooling. For graphviz, I use dot, and it takes my .dot files, and turns them into SVGs. For other diagram formats I use other tools. For excalidraw, I have a .excalidraw file stored locally, and in git, but i have no way to generate the SVGs without doing that by hand which is quite labor intensive. "Use the website" is not a tool. Yes, I can use the website on any platform, but the OP is addressing usage as a tool, for automated conversion, so it can be used in an automated workflow.

I asked for two features which may have confused all the discussions :)

@realazthat
Copy link

Ah my bad, I think I get the confusion now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests