konsumer / inkscape-svgo

Plugin to optimize SVGs in inkscape
73 stars 7 forks source link

Using makefile include x86_64 only full node js distribution #9

Closed Popolon closed 3 years ago

Popolon commented 3 years ago

I tried to apply a make with the included makefile,

Using this makefile include x86_64 only full node js distribution and lot of dependencies.

I already have node on my OS, and SVGO lib included in standard distribution package. I would be interested to build this Inkscape extension for ArchLinux, without reinstalling node, and even less x86_64 version, to keep the multi-architecture possibility of node.js. This would allow to use it on ARM, RISC-V, MIPS, Power, and any other kind of architectures and could use far less disk space and memory.

Do you have, please a mean to link it to existing node.js and SVGO installation. ?

konsumer commented 3 years ago

I'm not sure I understand what you are asking, but I will try.

The Makefile is for development, which requires devtools (node, libraries, etc.) this project is made in node, so if you want to build it, you need all that stuff. (much like if you wanted to build a program made in C, you would need a C compiler, all the libs, etc.) I use Makefiles as a way to record the steps so I can remember how to do things, when I come back to the project. It's just to make my life easier, for release. You can build for other platforms/arches though, even without the Makefile (anything that pkg supports.)

If you want to build for other platforms:

git clone https://github.com/konsumer/inkscape-svgo.git
cd inkscape-svgo
npm i

pkg src/inkscape-svgo.js --targets WHATEVER --out-path=dist/WHATEVER
cp inkscape-svgo.inx dist/WHATEVER/inkscape-svgo.inx

If what your asking is that you want me to build some other platform for you, I can do that, if you tell me what you os/arch you need, and I'll add it to releases. Releases don't require node/libs because they have all that inside them. It's provided to be helpful for people who don't want/care about nodejs.

Popolon commented 3 years ago

Sorry to not have be clear, and thank you very much, that was exactly build instruction I needed, I already have node/npm, and svgo installed by my system (ArchLinux) and I would create a package for inkscape-svgo with only it installed, I know the path of inkscape, I will try to make it now and update the ticket when it is done.

Again sorry, I don't have packaged anything in with npm until now, perhaps adding few line with these instructions could help other packagers.

konsumer commented 3 years ago

No prob! Lemme know if you need more help, and I'd be happy to add a release for you, if you need another CPU architecture

Popolon commented 3 years ago

I tried by just copying .inx/.js in inkscape extensions, it wasn't detected. I triend by changing .inx file, and add the script .js with interpreter node, it detect it but can't be executed.

if i Trie pkg, it download again node14-linux-x64, but I already have it on my system. Is there a mean to package it without downloading another nodejs binary ?

On my system : nodejs-lts-fermium 14.17.4-1

and it is in standard path: $ node --version v14.17.4 $ whereis node node: /usr/bin/node /usr/include/node /usr/share/man/man1/node.1.gz

Popolon commented 3 years ago

The goal is to have a standard AUR package, architecture independant, and that use preinstalled node js/pkg/npm commands if possilbe.

Popolon commented 3 years ago

managed to install it:

  npm install -g inkscape-svgo@${pkgver} --prefix "${pkgdir}/usr/"
  install -Dm644  inkscape-svgo.inx ${pkgdir}/usr/share/inkscape/extensions/inkscape-svgo.inx
  ln -s /usr/lib/node_modules/inkscape-svgo /${pkgdir}/usr/share/inkscape/extensions/
Popolon commented 3 years ago

That's not the good process, npm just copy the src and packages that are already at least in part in nodejs installation (like svgo):

ansi-regex color-convert csso domelementtype emoji-regex is-fullwidth-code-point source-map svgo yargs ansi-styles colorette css-select domhandler entities mdn-data stable @trysound yargs-parser boolbase color-name css-tree dom-serializer escalade nth-check string-width wrap-ansi cliui commander css-what domutils get-caller-file require-directory strip-ansi y18n

The option menu appear, and then the export fail.

konsumer commented 3 years ago

I tried by just copying .inx/.js in inkscape extensions, it wasn't detected. I triend by changing .inx file, and add the script .js with interpreter node, it detect it but can't be executed.

I don't really understand what you are doing. this is the meta-info file that makes it work for inkscape. it's not a js file. if it's not working, then check inkscape docs for how to install a plugin. You need inkscape-svgo somewhere in your path (not the same dir.)

if i Trie pkg, it download again node14-linux-x64, but I already have it on my system. Is there a mean to package it without downloading another nodejs binary ?

Like I said, it's made in node. To build a standalone compiled binary, you will need other stuff on your system.

The goal is to have a standard AUR package, architecture independant, and that use preinstalled node js/pkg/npm commands if possilbe.

I'm not sure what is involved with making an AUR (and I don't use archlinux, I use debian, so I don't really want to go figure it out) but for a full build you will need all the deps and dev-tools installed (run npm install with no args, in the project dir) but like I said, I can also build whatever binaries you need, and add them to releases, then you just need to wget/curl, and no need for node or anything else.

konsumer commented 3 years ago

what exactly is the issue with the file in release? Are you trying to use it on non-86_64?

Popolon commented 3 years ago

I try it on x86 first, but il already download a full nodejs of several MB in the process, I don't understand why for, there is already nodejs on my system. Why don't use already installed node ?

Popolon commented 3 years ago

OK found the answer, pulling it via npm: sudo npm -g install inkscape-svgo

Popolon commented 3 years ago

mmmh the node module is installed, but I don't understand how to use it with inkscape now. I tried to link it to inkscape extension modules the following way:

cd /usr/share/inkscape/extensions/
ln -s /usr/share/inkscape/extensions/inkscape-svgo .

So now The script is visible in the save as window formats, I have access to the export parameters window, but when I click on save (in /tmp to be sure to have write access), Inkscape complain about rights to execute on nodejs tree ??? It looks like npm install sources of the module?

Sorry I nearly don't know npm usage.

** (org.inkscape.Inkscape:9102): CRITICAL **: 08:52:22.396: Script::execute(): failed to execute program '/usr/share/inkscape/extensions/inkscape-svgo'.
    Reason: Failed to execute child process ?/usr/share/inkscape/extensions/inkscape-svgo? (Permission denied)
Popolon commented 3 years ago

I fnally tried with pkg, without another solution. It build a 75 MB extension. I can't decently make an Arch package like this on a limited resources world where it should take about 5MB with npm. especially when the goal is to optimize things :(. Sorry, this is not a blame, I describe just what looks like a problem, and thanks you very much for your efforts to integrate it in Inksape, I would like to help to make a lighter process if I know node.js enough, I will try to look a bit more at how packaging work in npm and if there is a possible more elegant solution later.

I still tried to export a file with the 75 MB pkg-ed extenation and get the following error :

When I tried to save:
(node:40723) UnhandledPromiseRejectionWarning: TypeError: object is not a constructor
    at main (/snapshot/inkscape-svgo/src/inkscape-svgo.js)
    at Object.<anonymous> (/snapshot/inkscape-svgo/src/inkscape-svgo.js)
    at Module._compile (pkg/prelude/bootstrap.js:1320:22)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1218:10)
    at Module.load (internal/modules/cjs/loader.js:1047:32)
    at Function.Module._load (internal/modules/cjs/loader.js:935:14)
    at Function.Module.runMain (pkg/prelude/bootstrap.js:1375:12)
    at internal/main/run_main_module.js:17:47
(Use `inkscape-svgo --trace-warnings ...` to show where the warning was created)
(node:40723) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:40723) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
konsumer commented 3 years ago

Before I say anything else, let me be clear about this: I don't work for you, and no one owes you free software, support, or anything else. There is no team that made the (actually well-over, including the orgs I also started) 500 github repos I have made over the years, it's just me. I make them when have time outside of work, spending time with my family, riding my bike, or doing other things I enjoy. I made this tool in my free time, and it worked for me (back when I used inkscape a lot, which was years ago.) If it doesn't work for you, or work exactly how you want it to, I'm really ok with that. Make the change you wish to see.

Fortunately for you, I'm a nice guy, who likes to share things that are useful to me with others, so they can (if they can work it out) use them, or make their own things based on them. It's open source, if you don't like it, make your own, and you have a great headstart, using my code. Inkscape plugin documentation is pretty bad (or at least was when I made this) and this plugin will probably be helpful, at least as an example, to look at the things I figured out. You're welcome.

This idea that I need to help you make it work, exactly how you want, even if it requires code-changes, extra work, and tons of hand-holding on my part, is not based on reality. I don't get anything from helping you with this, other than telling myself "cool, that thing I made works for this stranger on the internet." Maybe hire a linux/programmer friend, or write (or pay someone to write) your own plugin that works more how you imagine this one should?

Secondly, this user that can't handle installing 5MB plugin but is ok with installing inkscape (which is huge and has a lot of dependencies) and node, and all the library dependencies, is mostly imaginary. If you want to make an archlinux package for that use-case, that's fine (and my code should even sort of support that) but it seems like the issues you are having are basic nodejs, linux & inkscape usage-issues, and you should probably work those out first, before you start being the maintainer of the package you are wrapping around my plugin. I don't have the time/interest to support you in that, so maybe try an inkscape/archlinux/nodejs forum?

Also, you do realize that current versions of inkscape come with "Optimized SVG" that uses SVG Scrubber, right? Maybe just use that.

RE: all the stuff about "it's too big", "I don't like node", etc:

The "install node" part isn't really optional, if you don't want to use the release, and the large size is not optional if you don't want to use node. The plugin has dependencies on a bunch of libraries and a node-runtime, and that is not small, and needs to come from somewhere. Write your own no-dep C-based SVG optimizer. You will find you now have other concerns (porting svgo to no-dep cross-platform C, and compiling a C program and distributing it, in general, is not trivial.)

Last I checked, Inkscape plugins work like this:

It was years ago when I made (and actually used) it, and nodejs, inkscape & SVGO lib have all definitely changed. I don't owe it to you to keep this up to date (I do accept PRs, if you want to fix it for everyone else, and you can also just fork it and make one that works better for you.) That said, I just published it (0.0.14) with an extra bin field, and updated svgo-wrapping that should make it easier for others to use in different use-cases. Keep in mind, I don't even use this plugin, personally, anymore, I use "Optimized SVG", that comes with inkscape.

Just now, I tested it on a fairly fresh install of Pop!OS (I prefer debian-based OS's.) Here is 1 path that should mostly work for your use-case:

After that it worked fine for me, but I really have no more time to support this.

Popolon commented 3 years ago

Thank you for you long answer, I agree with you, sorry if you take it as an asking for more work, and again thank you for your work. As I said, I will try to look at it later, I just noticed today there is a svgo command line, so it could be called from a simple python script parsing the arguments of the table of your panel I will loot at it. This additional information will help me understand better the system. I also thought about integrating SVGO optimization in python SCOUR, that looks is used in current Inkscape optimisation output. SVGO is more efficient in several ways, but after my today test with command line, animation is broken. That looks weird with what limited things I know about SVG animtion, because it seems to output most tags a good way. I will try to understand what is wrong and report it to SVGO authors.

Just for information the whole Inkscape package is 156MB with all its functionalities and svgo itself is just 4.2MB. So I just said 75MB is quite a lot for communication between SVGO lib and Inkscape. As I just seen svgo can be called as an independent CLI command so a python bridge could be a simple and efficient solution, I will look at your work on the XML that is quite interesting and looks perfect for this task. Thanks again and I'm really sorry to have irritated you, I am just a little bit excited to discover all the current possibilities of SVG, as I tried 10+ years ago to make animations in Inkscape and there wasn't tools as I just discovered last week :(. I worked a lot with Inkscape developers at the beginning of the project, with translations, tutorials, examples and few (really limited) patch.

konsumer commented 3 years ago

Thank you for you long answer, I agree with you, sorry if you take it as an asking for more work

No prob. I dunno, I was in a really overworked & bad mood, I think. Sorry to rant.

I just noticed today there is a svgo command line, so it could be called from a simple python script parsing the arguments of the table of your panel I will loot at it.

Your users will still need node (required by svgo) + svgo installed, just like with this, but that might work more how you want it to. Using a SVG optimizer that uses the host language (python or whatever) is smaller, and the smallest option is going to be C/rust, with no deps on a full scripting language ecosystem, but writing that from scratch, even with great open-source headstart is going to be a serious pain. Since mine only requires node + svgo, not node + svgo + python, I would argue that mine actually has less dependencies than adding a python wrapper, but it's probly not really a big deal, either way.

Just for information the whole Inkscape package is 156MB with all its functionalities and svgo itself is just 4.2MB. So I just said 75MB is quite a lot for communication between SVGO lib and Inkscape.

Although I agree, since I already use the entire node-ecosystem, for work, and lots of projects, it has almost no size-cost for me, and other people that use node. svgo isn't the heavy part, or my tiny wrapper. It's nodejs.

Keep in mind the prebuilt (for people that don't use node) is nodejs-runtime + svgo + yargs. I think about the only thing you could do for more code-reuse is use commander (because the svgo cli uses that) instead of yargs. I like yargs, and it's really not that big, so I dunno how worth it would be to rewrite that. You will also have to write a lot more code to bind the required inkscape format with the svgo CLI, so it might not actually save that much, and would definitely require a bit more effort.

Fundamentally, you can't really change that svgo needs node (which all together is giant for an inkscape plugin) unless you write your own SVG optimizer that has less deps. I think the absolute best option for size and system-deps is C or rust. This one is made in rust, and seems pretty cool, so it might be a better option. Rust is fortunately very easy to cross-compile for lots of targets, so it could actually be a great cross-platform no-dep option. Looks like they also only build for x86_64, but there is the source, so you could pre-build a million different releases, so users don't need to install the rust toolchain, or a more community-minded solution might be to PR to their repo for a github workflow that builds a million releases, whenever code is pushed, automatically. That way they don;t have to build anything, and even more targets can be supported. I looked at their releases and they are all under 1MB, which is much better, but I have no idea if it works as well as svgo. They do have pretty decent docs on all the CLI flags, though.

Looking at the CLI help, I think it would need some wrapping still (like I needed to do with svgo) but you could write that in rust, and wrap the lib. It use s a format like --remove-comments yes, which is a bit different than inkscape needs.

I worked a lot with Inkscape developers at the beginning of the project, with translations, tutorials, examples and few (really limited) patch.

That's great, and I appreciate your contribution to open-source software we both use. Sorry again to fly off the handle a bit. Not really your fault.

konsumer commented 3 years ago

I had another look at what inkscape does with args:

  '/home/konsumer/.nvm/versions/node/v16.9.1/bin/node',
  '/home/konsumer/.var/app/org.inkscape.Inkscape/config/inkscape/extensions/inkscape-svgo',
  '--options=page_1',
  '--precision=2',
  '--pretty=true',
  '--enable=sortAttrs=false',
  '--multipass=true',
  '--enable=cleanupAttrs=true',
  '--enable=cleanupEnableBackground=true',
  '--enable=cleanupIDs=false',
  '--enable=cleanupNumericValues=true',
  '--enable=collapseGroups=true',
  '--enable=convertColors=true',
  '--enable=convertPathData=true',
  '--enable=convertShapeToPath=false',
  '--enable=convertStyleToAttrs=false',
  '--enable=convertTransform=true',
  '--enable=mergePaths=true',
  '--enable=minifyStyles=true',
  '--enable=moveElemsAttrsToGroup=false',
  '--enable=moveGroupAttrsToElems=false',
  '--enable=removeViewBox=false',
  '--enable=removeDimensions=false',
  '--enable=removeUnknownsAndDefaults=true',
  '--enable=removeUnusedNS=true',
  '--enable=removeUselessDefs=true',
  '--enable=removeUselessStrokeAndFill=true',
  '--enable=removeRasterImages=false',
  '--enable=removeScriptElement=false',
  '--enable=removeStyleElement=false',
  '--enable=removeTitle=true',
  '--enable=removeXMLNS=false',
  '--enable=removeXMLProcInst=true',
  '--enable=removeMetadata=true',
  '--enable=removeNonInheritableGroupAttrs=true',
  '--enable=removeComments=true',
  '--enable=removeDesc=true',
  '--enable=removeDoctype=true',
  '--enable=removeEditorsNSData=true',
  '--enable=removeEmptyAttrs=true',
  '--enable=removeEmptyContainers=true',
  '--enable=removeEmptyText=true',
  '--enable=removeHiddenElems=true',
  '/tmp/ink_ext_XXXXXX.svg4SVX90'

I named the args enable, with extra equal sign in them, because it creates a separate array in yargs, for easier parsing, but the basic format is flag=true/false

So, I tested svgcleaner with svgcleaner --stdout --remove-comments=true test.svg (get stdout output, use a format that could be created with booleans in xml file, etc) and it seems to have worked, but needs more teesting. You might be able to use it without any wrapping, just writing the XML file.

Popolon commented 3 years ago

Thank you for these new informations, it will be hepfull I will try to do my best usage with them. Python has the advantage to be a dependence of inkscape in linux distribution, so fingerprint should be reduced. For sure the best should be C or Rust, but I also think about the fact there are probably more contributors that manage Python in Inkscape ecosystem, and could add small patchs. not sure as this is also used in web and in this area most people work in JS. Thank you again, I will give you information when I made progress on this are (probably not this week).

konsumer commented 3 years ago

Python has the advantage to be a dependence of inkscape in linux distribution, so fingerprint should be reduced.

but I also think about the fact there are probably more contributors that manage Python in Inkscape ecosystem

Except that svgo is made with (and depends on) node, so it still requires node + svgo. So if you want to use python, and don't want those deps, you should probly use another SVG optimizer (written in python.)

If you are ok with using svgo (and requiring nodejs) like I am, then use the above instructions to install the plugin, and it will work fine, and the installed code will be very small (it's literally a symlink to a tiny js file, and node & svgo are installed system-wide.)

I still think, if that rust svg optimizer does the same stuff as svgo, it's going to be a very simple way to not have any system deps (even with an all-python plugin, you will need to instruct the user to pip install something.) Since it's already a small and self-contained CLI, you don't need to know rust to use it, just like you don't need to know js to use svgo, or C++, to use inkscape, but in addition, it has no other deps (there is no rust runtime or anything, like node or python, it's a self-contained compiled program.)