├── .no-sublime-package
├── .gitattributes
├── Svgo.sublime-settings
├── test.svg
├── Svgo.sublime-commands
├── .editorconfig
├── .github
└── dependabot.yml
├── package.json
├── Main.sublime-menu
├── svgo.mjs
├── node_bridge.py
├── license
├── readme.md
└── Svgo.py
/.no-sublime-package:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/Svgo.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "indent": 2
3 | }
4 |
--------------------------------------------------------------------------------
/test.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/Svgo.sublime-commands:
--------------------------------------------------------------------------------
1 | [{
2 | "caption": "SVGO: Minify SVG",
3 | "command": "svgo_minify"
4 | }, {
5 | "caption": "SVGO: Prettify SVG",
6 | "command": "svgo_prettify"
7 | }]
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | time: "20:00"
8 | open-pull-requests-limit: 10
9 | ignore:
10 | - dependency-name: svgo
11 | versions:
12 | - 2.0.3
13 | - 2.1.0
14 | - 2.2.1
15 | - 2.2.2
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "7.0.0",
3 | "private": true,
4 | "type": "module",
5 | "scripts": {
6 | "postversion": "git push && git push --tags"
7 | },
8 | "dependencies": {
9 | "get-stdin": "^9.0.0",
10 | "svgo": "^3.3.2"
11 | },
12 | "engines": {
13 | "node": ">=20",
14 | "npm": ">=10"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Main.sublime-menu:
--------------------------------------------------------------------------------
1 | [{
2 | "caption": "Preferences",
3 | "mnemonic": "n",
4 | "id": "preferences",
5 | "children": [{
6 | "caption": "Package Settings",
7 | "mnemonic": "P",
8 | "id": "package-settings",
9 | "children": [{
10 | "caption": "svgo",
11 | "children": [{
12 | "command": "open_file",
13 | "args": {
14 | "file": "${packages}/svgo/Svgo.sublime-settings"
15 | },
16 | "caption": "Settings – Default"
17 | }, {
18 | "command": "open_file",
19 | "args": {
20 | "file": "${packages}/User/Svgo.sublime-settings"
21 | },
22 | "caption": "Settings – User"
23 | }, {
24 | "caption": "-"
25 | }]
26 | }]
27 | }]
28 | }]
29 |
--------------------------------------------------------------------------------
/svgo.mjs:
--------------------------------------------------------------------------------
1 | import {Buffer} from 'node:buffer';
2 | import getStdin from 'get-stdin';
3 | import {optimize} from 'svgo';
4 |
5 | getStdin()
6 | .then(data => minify(data))
7 | .then(data => process.stdout.write(data));
8 |
9 | function minify(data) {
10 | const options = JSON.parse(process.argv[2]);
11 | const svg = Buffer.isBuffer(data) ? data.toString() : data;
12 | const plugins = ['preset-default'];
13 |
14 | // Add user plugins
15 | for (const plugin of Object.keys(options.plugins || [])) {
16 | plugins.push({
17 | [plugin]: options.plugins[plugin],
18 | });
19 | }
20 |
21 | return optimize(svg, {
22 | js2svg: {
23 | pretty: options.pretty,
24 | indent: options.indent
25 | },
26 | plugins,
27 | }).data;
28 | }
29 |
--------------------------------------------------------------------------------
/node_bridge.py:
--------------------------------------------------------------------------------
1 | import os
2 | import platform
3 | import subprocess
4 |
5 | IS_MACOS = platform.system() == 'Darwin'
6 | IS_WINDOWS = platform.system() == 'Windows'
7 |
8 | def node_bridge(data, bin, args=[]):
9 | env = None
10 | startupinfo = None
11 |
12 | if IS_MACOS:
13 | env = os.environ.copy()
14 | env['PATH'] += ':/usr/local/bin'
15 |
16 | if IS_WINDOWS:
17 | startupinfo = subprocess.STARTUPINFO()
18 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
19 |
20 | try:
21 | p = subprocess.Popen(['node', bin] + args,
22 | stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE,
23 | env=env, startupinfo=startupinfo)
24 | except OSError:
25 | raise Exception('Couldn\'t find Node.js. Make sure it\'s in your $PATH by running `node -v` in your command-line.')
26 |
27 | stdout, stderr = p.communicate(input=data.encode('utf-8'))
28 | stdout = stdout.decode('utf-8')
29 | stderr = stderr.decode('utf-8')
30 |
31 | if stderr:
32 | raise Exception('Error: %s' % stderr)
33 | else:
34 | return stdout
35 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Shogo Sensui (https://github.com/1000ch)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Sublime-svgo
2 |
3 | A plugin for [Sublime Text](https://www.sublimetext.com/) providing an interface to [SVGO](https://github.com/svg/svgo).
4 |
5 | 
6 |
7 | ## Install
8 |
9 | You can install via with [Package Control](https://packagecontrol.io/) and restart Sublime.
10 |
11 | - **Install Package**: Search with `SVGO`.
12 | - **Add Repository**: Put URL `https://github.com/1000ch/Sublime-svgo`.
13 |
14 | Also you can install this extension locally by putting symbolic link from `~/Library/Application\ Support/Sublime\ Text/Packages/` to `~/path/to/this/repo` like below.
15 |
16 | ```bash
17 | $ ln -s ~/workspace/github.com/1000ch/Sublime-svgo ~/Library/Application\ Support/Sublime\ Text/Packages/SVGO
18 | ```
19 |
20 | ### Prerequisite
21 |
22 | [SVGO](https://github.com/svg/svgo) requires Node.js as runtime. If you don't have Node.js, I recommend you to install Node.js using version managers like the followings.
23 |
24 | - Use [nodenv/nodenv](https://github.com/nodenv/nodenv)
25 | - Use [hokaccha/nodebrew](https://github.com/hokaccha/nodebrew)
26 |
27 | ## Usage
28 |
29 | In a SVG file, open the Command Palette (Cmd Shift P) and choose **Minify SVG** or **Prettify SVG**.
30 |
31 | ## Config
32 |
33 | You can configure following options from Preferences → Package Settings → Svgo → Settings - User.
34 |
35 | ### indent
36 |
37 | Indent size used on prettify.
38 |
39 | ## License
40 |
41 | [MIT](https://1000ch.mit-license.org) © [Shogo Sensui](https://github.com/1000ch)
42 |
--------------------------------------------------------------------------------
/Svgo.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 | import json
4 | from os.path import dirname, realpath, join
5 |
6 | try:
7 | # Python 2
8 | from node_bridge import node_bridge
9 | except:
10 | from .node_bridge import node_bridge
11 |
12 | sublime.Region.totuple = lambda self: (self.a, self.b)
13 | sublime.Region.__iter__ = lambda self: self.totuple().__iter__()
14 |
15 | BIN_PATH = join(sublime.packages_path(), dirname(realpath(__file__)), 'svgo.mjs')
16 |
17 | def get_setting(view, key):
18 | settings = view.settings().get('Svgo')
19 |
20 | if settings is None:
21 | settings = sublime.load_settings('Svgo.sublime-settings')
22 |
23 | return settings.get(key)
24 |
25 | class SvgoMinifyCommand(sublime_plugin.TextCommand):
26 | def run(self, edit):
27 | region = sublime.Region(0, self.view.size())
28 | buffer = self.view.substr(region)
29 | processed = self.minify(buffer)
30 |
31 | if processed:
32 | self.view.replace(edit, region, processed)
33 |
34 | def minify(self, data):
35 | try:
36 | return node_bridge(data, BIN_PATH, [json.dumps({
37 | 'indent': get_setting(self.view, 'indent'),
38 | 'plugins': get_setting(self.view, 'plugins')
39 | })])
40 | except Exception as e:
41 | sublime.error_message('svgo\n%s' % e)
42 |
43 | class SvgoPrettifyCommand(sublime_plugin.TextCommand):
44 | def run(self, edit):
45 | region = sublime.Region(0, self.view.size())
46 | buffer = self.view.substr(region)
47 | processed = self.prettify(buffer)
48 |
49 | if processed:
50 | self.view.replace(edit, region, processed)
51 |
52 | def prettify(self, data):
53 | try:
54 | return node_bridge(data, BIN_PATH, [json.dumps({
55 | 'pretty': True,
56 | 'indent': get_setting(self.view, 'indent'),
57 | 'plugins': get_setting(self.view, 'plugins')
58 | })])
59 | except Exception as e:
60 | sublime.error_message('svgo\n%s' % e)
61 |
--------------------------------------------------------------------------------