├── .gitignore
├── LICENSE
├── README.md
├── public
├── alfred_buffer.webp
├── icon_dark_mode.webp
├── icon_light_mode.webp
├── log_detail.webp
├── types.webp
└── universal_action.webp
└── src
├── compress.sh
├── entry.js
├── icon.png
├── icons
├── delete.webp
├── info.webp
├── manual.webp
├── new.webp
├── presets.webp
├── return.webp
├── run.webp
└── web.webp
├── info.plist
├── json
└── presets.json
├── notificator
├── options.js
└── presets.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | **/.DS_Store
3 | src/prefs.plist
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-present Benjamin Oddou
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | [](https://github.com/BenjaminOddou)
5 | [](https://saythanks.io/to/BenjaminOddou)
6 |
7 | Welcome to the Alfred Smart WebP repository: **An Alfred Workflow** ✨
8 |
9 | ## ✅ Prerequisites
10 |
11 | * MacOS
12 | * Alfred 5. Note that the [Alfred Powerpack](https://www.alfredapp.com/powerpack/) is required to use workflows.
13 |
14 | ## 🏎️ cwebp
15 |
16 | Under the hood, the compression is made with [cwebp](https://developers.google.com/speed/webp/docs/cwebp) (made by Google), a tool that allows to compress images into the WebP format, which is generally lighter, and broadly used to share images on the web.
17 |
18 | ## ⬇️ Installation
19 |
20 | 1. [Download the workflow](https://github.com/BenjaminOddou/alfred-smart-webp-compression/releases/latest)
21 | 2. Double click the `.alfredworkflow` file to install
22 |
23 | ## 🧰 Setup the workflow
24 |
25 | #### Open the Terminal of you Mac and run the following command:
26 |
27 | Install cwebp (using [Homebrew](https://brew.sh)):
28 |
29 | ```shell
30 | brew install webp
31 | ```
32 |
33 | ## 🧙♂️ Invoke the workflow
34 |
35 | You can invoke the workflow by writing `webp` into the Alfred search box. You can change this value by changing the `🕹️ Trigger` variable in workflow configuration panel.
36 |
37 | ## 🤖 Usage of the workflow
38 |
39 | ### Handling presets
40 |
41 | #### Create a preset
42 |
43 | Go under the `presets section` and click on `Add a new preset`.
44 |
45 | Add your preset by putting a `value`, press ⏎ and input a `title` and a `subtitle` separated by a `/`.
46 |
47 | #### Modify a preset
48 |
49 | Go under the `presets section` and click on the preset you want to modify.
50 |
51 | Select wether you want to modify the `title/subtitle` or the `value` and press ⏎. Input the new title/subtitle or value and press ⏎.
52 |
53 | #### Remove a preset
54 |
55 | Under the `presets section`, click on `Remove a preset`.
56 |
57 | Select the preset you want to remove and press ⏎.
58 |
59 | ### Start the compression
60 |
61 | #### Using Workflow File Filter
62 |
63 | Under the home menu, click on `Start the compression`.
64 |
65 | Select the folder with images or directly the image you want to compress and press enter ⏎.
66 |
67 | > Note that when selecting a folder, images within subdirectories aren't selected if `🔍 Depth of the search` is 1. If you want images in subdirectories, increase this value. Only images with `png|jpg|jpeg|tif|tiff|webp` file extensions are selected. In addition, they aren't case sensitive, meaning that the image extension can be `PNG|JpG|tifF...`
68 |
69 | Here is an example where the user selected a folder and put `Level 2` in `🔍 Depth of the search` :
70 | ```shell
71 | .
72 | ├── selected folder # Level 1
73 | │ ├── subdirectory # Level 2
74 | │ │ ├── image.PnG # selected ✅
75 | │ │ ├── a nested folder # Level 3
76 | │ │ │ ├── one image.webp # not selected ❌
77 | │ │ │ └── a second image.tiff # not selected ❌
78 | │ │ └── file.doc # not selected ❌
79 | │ └── first-image.jpeg # selected ✅
80 | ```
81 |
82 | Alternatively, use the `Alfred Buffer` to select folder(s) and image(s) at the same time !! Basic commands are :
83 |
84 | * ⌥↑ to add a file to the buffer from Alfred's results.
85 | * ⌥↓ to add a file and move to the next item in your list of results.
86 | * ⌥← to remove the last item from the buffer.
87 | * ⌥→ to action all items in the buffer.
88 | * ⌥⌫ to remove all items from the buffer.
89 |
90 | To know more on how to use `Alfred Buffer`, follow this [link](https://www.alfredapp.com/help/features/file-search/#file-buffer).
91 |
92 | > Note that `Alfred Buffer` is preferred compare to the `{query}`, meaning that if you select a folder/image (by clicking on it or by pressing enter ⏎) that is not included in the buffer, **it will not be compressed**.
93 |
94 | 
95 |
96 | Choose the cwebp options by selecting a preset or input it manually by pressing `Manual options`.
97 |
98 | #### Using Alfred Universal Actions
99 |
100 | Select the folder(s) / image(s) you want to compress within alfred using `Quick Search` and run `Universal Actions` with → or ⌥→ if you used the `Alfred buffer`. Select "Compress images to WebP".
101 |
102 | 
103 |
104 | > Note that the workflow is type sensitive, meaning that if you select a file that is not part of the following types, the action "Compress images to WebP" will not be available
105 |
106 | 
107 |
108 | If you want to know more on how to use Alfred Universal Actions, follow this [link](https://www.alfredapp.com/help/features/universal-actions/).
109 |
110 | #### Logs output
111 |
112 | Check the logs of your compression under the `Data folder`. The log file contains the 2 parts.
113 |
114 | 1. In the orange box there is :
115 | * Date of the compression with a `YYYY/MM/dd` pattern.
116 | * Exact time of the compression with a `HH:mm:ss` pattern.
117 | * Folder(s) + image(s) path(s) selected with a tab ⇥ separator.
118 | * Preset or manual input. Preset will be displayed as `preset_name,preset_detail` whereas manual input will be displayed raw.
119 | * The selected level of variable `🔍 Depth of the search`
120 | 2. In the green box there is the cwebp output.
121 |
122 | > Note that each compression is separated by a line.
123 |
124 | 
125 |
126 | ## ⚖️ License
127 |
128 | [MIT License](LICENSE) © Benjamin Oddou
129 |
--------------------------------------------------------------------------------
/public/alfred_buffer.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/alfred_buffer.webp
--------------------------------------------------------------------------------
/public/icon_dark_mode.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/icon_dark_mode.webp
--------------------------------------------------------------------------------
/public/icon_light_mode.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/icon_light_mode.webp
--------------------------------------------------------------------------------
/public/log_detail.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/log_detail.webp
--------------------------------------------------------------------------------
/public/types.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/types.webp
--------------------------------------------------------------------------------
/public/universal_action.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/public/universal_action.webp
--------------------------------------------------------------------------------
/src/compress.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 |
3 | function handle_error {
4 | source ./notificator --title "🚨 Error" --message "An error occurred! Exiting script.." --sound "$sound"
5 | exit 1
6 | }
7 |
8 | trap "handle_error" ERR
9 |
10 | (source ./notificator --title "⏳ Please wait..." --message "The workflow is generating images" --sound "$sound") &
11 |
12 | echo "🔍 Depth of the search : Level ${level}\n"
13 |
14 | LINKS=(${(s/ /)_links_list}) # split by tab
15 | IMAGES=()
16 | IFS=$'\n'
17 |
18 | for LINK in "${LINKS[@]}"; do
19 | if [ -d "$LINK" ]; then
20 | IMAGES+=($(find -E "$LINK" -maxdepth "$level" -iregex '.*\.(png|jpg|jpeg|tif|tiff|webp)'))
21 | else
22 | IMAGES+=("$LINK")
23 | fi
24 | done
25 |
26 | for IMAGE in "${IMAGES[@]}"; do
27 | 2>&1 eval "cwebp $_the_preset \"$IMAGE\" -o \"${IMAGE%.*}.webp\""
28 | done
29 |
30 | if [[ $workflow_action = "_notif" ]];then
31 | sleep 0.5
32 | source ./notificator --title "⌛ Finished" --message "Process completed. You can check the log file" --sound "$sound"
33 | fi
--------------------------------------------------------------------------------
/src/entry.js:
--------------------------------------------------------------------------------
1 | ObjC.import('stdlib')
2 | const app = Application.currentApplication()
3 | app.includeStandardAdditions = true
4 | const PWD = $.getenv("PWD")
5 | const fm = $.NSFileManager.defaultManager
6 | const encoding = $.NSUTF8StringEncoding
7 | const level = $.NSProcessInfo.processInfo.environment.objectForKey('split2')?.js || 0
8 | const type = $.NSProcessInfo.processInfo.environment.objectForKey('split3')?.js || null
9 | const action = $.NSProcessInfo.processInfo.environment.objectForKey('split4')?.js || null
10 | const key = $.NSProcessInfo.processInfo.environment.objectForKey('split5')?.js || null
11 | const data_folder = $.NSProcessInfo.processInfo.environment.objectForKey('data_folder')?.js || $.NSProcessInfo.processInfo.environment.objectForKey('alfred_workflow_data').js
12 | const cmd = "which cwebp";
13 | let items = []
14 |
15 | function readFile(path) {
16 | if (fm.fileExistsAtPath(path)) {
17 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
18 | } else {
19 | const sourcePath = `${PWD}/json/presets.json`
20 | fm.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(data_folder, true, $(), null)
21 | fm.copyItemAtPathToPathError(sourcePath, path, null)
22 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
23 | }
24 | }
25 |
26 | try {
27 | app.doShellScript(cmd)
28 | if (level == 0){
29 | items.push(
30 | {
31 | title: 'Start the compression',
32 | subtitle: 'Run the cwebp compression with your parameters',
33 | arg: '_compress',
34 | icon: { path: 'icons/run.webp' },
35 | },
36 | {
37 | title: 'Presets',
38 | subtitle: 'Create, modify or remove presets',
39 | arg: '_rerun;1;presets',
40 | icon: { path: 'icons/presets.webp' },
41 | },
42 | {
43 | title: 'Online documentation',
44 | subtitle: 'Show cwebp documentation',
45 | quicklookurl: 'https://developers.google.com/speed/webp/docs/cwebp',
46 | arg: '_web;https://developers.google.com/speed/webp/docs/cwebp',
47 | icon: { path: 'icons/web.webp' },
48 | },
49 | )
50 | } else {
51 | items.push({
52 | title: 'Return',
53 | subtitle: 'Back to previous state',
54 | arg: `_rerun;${level - 1};${type}`,
55 | icon: { path: 'icons/return.webp' },
56 | })
57 | if (level == 1) {
58 | if (type == 'presets') {
59 | items.push(
60 | {
61 | title: 'Add a new preset',
62 | subtitle: 'Create a new preset with custom cwebp options',
63 | arg: '_presets;new',
64 | icon: { path: 'icons/new.webp' },
65 | },
66 | {
67 | title: 'Delete a preset',
68 | subtitle: 'Erase a preset from the list below',
69 | arg: '_rerun;2;presets;delete',
70 | icon: { path: 'icons/delete.webp' },
71 | }
72 | )
73 | content = JSON.parse(readFile(`${data_folder}/presets.json`))
74 | content.items.forEach(item => {
75 | item.arg = `_rerun;2;presets;modify;${item.id}`
76 | items.push(item)
77 | })
78 | }
79 | } else if (level == 2) {
80 | if (type == 'presets') {
81 | if (action == 'delete') {
82 | content = JSON.parse(readFile(`${data_folder}/presets.json`))
83 | content.items.forEach(item => {
84 | item.arg = `_presets;delete;${item.id}`
85 | items.push(item)
86 | })
87 | } else if (action == 'modify') {
88 | content = JSON.parse(readFile(`${data_folder}/presets.json`))
89 | content.items.forEach(item => {
90 | if (item.id == key) {
91 | items.push(
92 | {
93 | title: 'Modify the Preset\'s Title/Subtitle',
94 | subtitle: `Current Title: ${item.title} ǀ Current Subtitle: ${item.subtitle}`,
95 | arg: `_presets;modify;tl&sb;Title and/or Subtitle;${item.title}/${item.subtitle};${key}`,
96 | icon: { path: 'icons/presets.webp' },
97 | },
98 | {
99 | title: 'Modify the Preset\'s Value',
100 | subtitle: `Current Value: ${item.arg}`,
101 | arg: `_presets;modify;arg;Value;${item.arg};${key}`,
102 | icon: { path: 'icons/presets.webp' },
103 | }
104 | )
105 | }
106 | })
107 | }
108 | }
109 | }
110 | }
111 | JSON.stringify({ items })
112 | } catch {
113 | items = []
114 | items.push(
115 | {
116 | title: 'Something went wrong...',
117 | subtitle: 'Press ⏎ to check the docs online',
118 | arg: '_web;https://github.com/BenjaminOddou/alfred-smart-webp-compression',
119 | quicklookurl: 'https://github.com/BenjaminOddou/alfred-smart-webp-compression',
120 | icon: { path: 'icons/info.webp' },
121 | },
122 | )
123 | JSON.stringify({ items })
124 | }
--------------------------------------------------------------------------------
/src/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icon.png
--------------------------------------------------------------------------------
/src/icons/delete.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/delete.webp
--------------------------------------------------------------------------------
/src/icons/info.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/info.webp
--------------------------------------------------------------------------------
/src/icons/manual.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/manual.webp
--------------------------------------------------------------------------------
/src/icons/new.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/new.webp
--------------------------------------------------------------------------------
/src/icons/presets.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/presets.webp
--------------------------------------------------------------------------------
/src/icons/return.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/return.webp
--------------------------------------------------------------------------------
/src/icons/run.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/run.webp
--------------------------------------------------------------------------------
/src/icons/web.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BenjaminOddou/alfred-smart-webp-compression/0c2c10e882d5739de7d9871901b31aea84bfb87e/src/icons/web.webp
--------------------------------------------------------------------------------
/src/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bundleid
6 | com.benjamino.smart_webp_compression
7 | connections
8 |
9 | 045C5FE6-9D9A-4C6E-BB9F-73E732480CB9
10 |
11 |
12 | destinationuid
13 | 1F5239EB-3ECF-4E0E-8431-A65EB2327A19
14 | modifiers
15 | 0
16 | modifiersubtext
17 |
18 | vitoclose
19 |
20 |
21 |
22 | 0BC6A292-B409-4DAC-8EA9-2C8604D1F303
23 |
24 |
25 | destinationuid
26 | 42AF05BF-C545-42DF-AC3B-9F81F851C963
27 | modifiers
28 | 0
29 | modifiersubtext
30 |
31 | vitoclose
32 |
33 |
34 |
35 | 13DDCB6C-9438-4C2B-B386-867F758EEDAF
36 |
37 |
38 | destinationuid
39 | 38FEF466-6198-4D50-AA90-D70C13B216F4
40 | modifiers
41 | 0
42 | modifiersubtext
43 |
44 | vitoclose
45 |
46 |
47 |
48 | 1F5239EB-3ECF-4E0E-8431-A65EB2327A19
49 |
50 |
51 | destinationuid
52 | 13DDCB6C-9438-4C2B-B386-867F758EEDAF
53 | modifiers
54 | 0
55 | modifiersubtext
56 |
57 | sourceoutputuid
58 | 82863E01-18CA-4A51-B90A-43A845142D62
59 | vitoclose
60 |
61 |
62 |
63 | destinationuid
64 | A5FB494F-4E88-47A0-879E-401294A7C6D4
65 | modifiers
66 | 0
67 | modifiersubtext
68 |
69 | sourceoutputuid
70 | 1891A02A-6CF8-4BBC-B8F9-97BD1B09BF5B
71 | vitoclose
72 |
73 |
74 |
75 | destinationuid
76 | FDEDA57C-C351-4AA4-B0D2-BA3A16A2125F
77 | modifiers
78 | 0
79 | modifiersubtext
80 |
81 | sourceoutputuid
82 | F94A9936-1BF8-45BE-AFB3-BED2285C65FD
83 | vitoclose
84 |
85 |
86 |
87 | destinationuid
88 | E059706B-E9CB-457B-A984-1F96041A300B
89 | modifiers
90 | 0
91 | modifiersubtext
92 |
93 | sourceoutputuid
94 | 3E3E8353-8D8A-4CFD-B5B3-BDD74E9917F5
95 | vitoclose
96 |
97 |
98 |
99 | 2308696E-54E9-47F6-BFAD-BE577F5EA33C
100 |
101 |
102 | destinationuid
103 | 94DB40C4-AE8A-4383-B916-29465859AAF9
104 | modifiers
105 | 0
106 | modifiersubtext
107 |
108 | vitoclose
109 |
110 |
111 |
112 | 24C70ED0-81F4-484E-841F-032B110455CA
113 |
114 |
115 | destinationuid
116 | 6C3B838B-C528-449D-B058-3836F59421EA
117 | modifiers
118 | 0
119 | modifiersubtext
120 |
121 | vitoclose
122 |
123 |
124 |
125 | 2594B231-AB96-474F-A44E-2C733F045144
126 |
127 |
128 | destinationuid
129 | 3FEE47AA-2088-45F6-B112-EC2794BD9397
130 | modifiers
131 | 0
132 | modifiersubtext
133 |
134 | vitoclose
135 |
136 |
137 |
138 | 29E00EF6-FC86-4DE7-83BC-A4D225269C5E
139 |
140 |
141 | destinationuid
142 | 3B719F83-111C-42AA-A4F0-3858F6AEBDF8
143 | modifiers
144 | 0
145 | modifiersubtext
146 |
147 | vitoclose
148 |
149 |
150 |
151 | 29FE5492-8E67-4F8F-87A3-159939E6A097
152 |
153 |
154 | destinationuid
155 | 8CA4509B-0219-4AD8-9C45-13EC464FF9DF
156 | modifiers
157 | 0
158 | modifiersubtext
159 |
160 | vitoclose
161 |
162 |
163 |
164 | 312ACF3E-422C-4D71-B4C8-524DD7FA8B12
165 |
166 |
167 | destinationuid
168 | 3FEE47AA-2088-45F6-B112-EC2794BD9397
169 | modifiers
170 | 0
171 | modifiersubtext
172 |
173 | vitoclose
174 |
175 |
176 |
177 | 38FEF466-6198-4D50-AA90-D70C13B216F4
178 |
179 |
180 | destinationuid
181 | 69BA9B7D-DD02-4970-AF06-8266F95388C9
182 | modifiers
183 | 0
184 | modifiersubtext
185 |
186 | vitoclose
187 |
188 |
189 |
190 | 3B719F83-111C-42AA-A4F0-3858F6AEBDF8
191 |
192 |
193 | destinationuid
194 | E05259B6-5B68-46E1-B5E3-A2955ACC4A3A
195 | modifiers
196 | 0
197 | modifiersubtext
198 |
199 | vitoclose
200 |
201 |
202 |
203 | 3BC14125-DD5B-4FA9-9AD5-A3A69F183B2F
204 |
205 |
206 | destinationuid
207 | 6C3B838B-C528-449D-B058-3836F59421EA
208 | modifiers
209 | 0
210 | modifiersubtext
211 |
212 | vitoclose
213 |
214 |
215 |
216 | 3F40E4A0-B574-41EF-B31C-49AF88E9DEA3
217 |
218 |
219 | destinationuid
220 | ECEF6C22-D209-4F02-8240-FFF192BCD9B9
221 | modifiers
222 | 0
223 | modifiersubtext
224 |
225 | vitoclose
226 |
227 |
228 |
229 | 3FEE47AA-2088-45F6-B112-EC2794BD9397
230 |
231 |
232 | destinationuid
233 | 3F40E4A0-B574-41EF-B31C-49AF88E9DEA3
234 | modifiers
235 | 0
236 | modifiersubtext
237 |
238 | vitoclose
239 |
240 |
241 |
242 | 42AF05BF-C545-42DF-AC3B-9F81F851C963
243 |
244 |
245 | destinationuid
246 | 24C70ED0-81F4-484E-841F-032B110455CA
247 | modifiers
248 | 0
249 | modifiersubtext
250 |
251 | vitoclose
252 |
253 |
254 |
255 | 69BA9B7D-DD02-4970-AF06-8266F95388C9
256 |
257 |
258 | destinationuid
259 | CF9124F1-C2EF-4BBE-B066-A2CCC6C1149B
260 | modifiers
261 | 0
262 | modifiersubtext
263 |
264 | vitoclose
265 |
266 |
267 |
268 | 7587F5D4-DC06-4411-BDC1-EA1FD81363D6
269 |
270 |
271 | destinationuid
272 | 3BC14125-DD5B-4FA9-9AD5-A3A69F183B2F
273 | modifiers
274 | 0
275 | modifiersubtext
276 |
277 | vitoclose
278 |
279 |
280 |
281 | 8CA4509B-0219-4AD8-9C45-13EC464FF9DF
282 |
283 |
284 | destinationuid
285 | F2BF7B8C-1591-4877-AFF5-0EAFDFB59178
286 | modifiers
287 | 0
288 | modifiersubtext
289 |
290 | vitoclose
291 |
292 |
293 |
294 | 94DB40C4-AE8A-4383-B916-29465859AAF9
295 |
296 |
297 | destinationuid
298 | 3B719F83-111C-42AA-A4F0-3858F6AEBDF8
299 | modifiers
300 | 0
301 | modifiersubtext
302 |
303 | vitoclose
304 |
305 |
306 |
307 | C4C284CD-55E1-41E9-867A-B48CA7AB5D47
308 |
309 |
310 | destinationuid
311 | 2594B231-AB96-474F-A44E-2C733F045144
312 | modifiers
313 | 0
314 | modifiersubtext
315 |
316 | vitoclose
317 |
318 |
319 |
320 | CF9124F1-C2EF-4BBE-B066-A2CCC6C1149B
321 |
322 |
323 | destinationuid
324 | 29E00EF6-FC86-4DE7-83BC-A4D225269C5E
325 | modifiers
326 | 0
327 | modifiersubtext
328 |
329 | sourceoutputuid
330 | 40F21FC1-5AB6-4DD3-BBB7-CDD2D7B59B8F
331 | vitoclose
332 |
333 |
334 |
335 | destinationuid
336 | 94DB40C4-AE8A-4383-B916-29465859AAF9
337 | modifiers
338 | 0
339 | modifiersubtext
340 |
341 | vitoclose
342 |
343 |
344 |
345 | E05259B6-5B68-46E1-B5E3-A2955ACC4A3A
346 |
347 |
348 | destinationuid
349 | C4C284CD-55E1-41E9-867A-B48CA7AB5D47
350 | modifiers
351 | 0
352 | modifiersubtext
353 |
354 | sourceoutputuid
355 | B04F7F98-F4C6-4E61-986D-68F6986FEA93
356 | vitoclose
357 |
358 |
359 |
360 | destinationuid
361 | 312ACF3E-422C-4D71-B4C8-524DD7FA8B12
362 | modifiers
363 | 0
364 | modifiersubtext
365 |
366 | vitoclose
367 |
368 |
369 |
370 | E059706B-E9CB-457B-A984-1F96041A300B
371 |
372 |
373 | destinationuid
374 | 0BC6A292-B409-4DAC-8EA9-2C8604D1F303
375 | modifiers
376 | 0
377 | modifiersubtext
378 |
379 | sourceoutputuid
380 | 40F21FC1-5AB6-4DD3-BBB7-CDD2D7B59B8F
381 | vitoclose
382 |
383 |
384 |
385 | destinationuid
386 | 6C3B838B-C528-449D-B058-3836F59421EA
387 | modifiers
388 | 0
389 | modifiersubtext
390 |
391 | sourceoutputuid
392 | 9A4468F5-CA10-41FA-9110-3FEAA5816577
393 | vitoclose
394 |
395 |
396 |
397 | destinationuid
398 | 7587F5D4-DC06-4411-BDC1-EA1FD81363D6
399 | modifiers
400 | 0
401 | modifiersubtext
402 |
403 | sourceoutputuid
404 | 8EE14863-8E4A-47BE-9D21-B6624353D444
405 | vitoclose
406 |
407 |
408 |
409 | ECEF6C22-D209-4F02-8240-FFF192BCD9B9
410 |
411 |
412 | destinationuid
413 | 58F33492-15F5-46AB-A362-CA56E17F396D
414 | modifiers
415 | 0
416 | modifiersubtext
417 |
418 | sourceoutputuid
419 | 858CBA9A-76BF-4F4E-AB3A-16789D3C48CF
420 | vitoclose
421 |
422 |
423 |
424 | destinationuid
425 | C498F126-D109-47CE-9C8D-C1439C5F5B30
426 | modifiers
427 | 0
428 | modifiersubtext
429 |
430 | sourceoutputuid
431 | E483B0E6-5E1E-4F8E-BE08-F61FB4E857AB
432 | vitoclose
433 |
434 |
435 |
436 | F2BF7B8C-1591-4877-AFF5-0EAFDFB59178
437 |
438 |
439 | destinationuid
440 | 045C5FE6-9D9A-4C6E-BB9F-73E732480CB9
441 | modifiers
442 | 0
443 | modifiersubtext
444 |
445 | sourceoutputuid
446 | 1891A02A-6CF8-4BBC-B8F9-97BD1B09BF5B
447 | vitoclose
448 |
449 |
450 |
451 |
452 | createdby
453 | Benjamin Oddou
454 | description
455 | 🧙♂️ Transform your images into WebP format with ease
456 | disabled
457 |
458 | name
459 | Smart WebP
460 | objects
461 |
462 |
463 | config
464 |
465 | openwith
466 |
467 | sourcefile
468 | {var:data_folder}/logs.txt
469 |
470 | type
471 | alfred.workflow.action.openfile
472 | uid
473 | 58F33492-15F5-46AB-A362-CA56E17F396D
474 | version
475 | 3
476 |
477 |
478 | config
479 |
480 | addfilestobuffer
481 |
482 | clearbuffer
483 |
484 | outputtype
485 | 0
486 |
487 | type
488 | alfred.workflow.action.buffer
489 | uid
490 | 69BA9B7D-DD02-4970-AF06-8266F95388C9
491 | version
492 | 1
493 |
494 |
495 | config
496 |
497 | anchorfields
498 |
499 | argumenttrimmode
500 | 0
501 | argumenttype
502 | 0
503 | daterange
504 | 0
505 | fields
506 |
507 |
508 | field
509 | kMDItemDisplayName
510 | not
511 |
512 | split
513 |
514 | value
515 | {query}
516 | words
517 |
518 |
519 |
520 | field
521 | kMDItemAlternateNames
522 | not
523 |
524 | split
525 |
526 | value
527 | {query}
528 | words
529 |
530 |
531 |
532 | field
533 | kMDItemFinderComment
534 | not
535 |
536 | split
537 |
538 | value
539 | {query}
540 | words
541 |
542 |
543 |
544 | includesystem
545 |
546 | limit
547 | 0
548 | runningsubtext
549 |
550 | scopes
551 |
552 | sortmode
553 | 0
554 | subtext
555 | Start writing to find images and folders
556 | title
557 | Choose images / folders for compression
558 | types
559 |
560 | org.webmproject.webp
561 | public.folder
562 | public.jpeg
563 | public.png
564 | public.tiff
565 |
566 | withspace
567 |
568 |
569 | inboundconfig
570 |
571 | externalid
572 | {query}
573 | usecustominputarg
574 |
575 |
576 | type
577 | alfred.workflow.input.filefilter
578 | uid
579 | 13DDCB6C-9438-4C2B-B386-867F758EEDAF
580 | version
581 | 2
582 |
583 |
584 | config
585 |
586 | argumenttype
587 | 0
588 | subtext
589 | Write the cwebp options and press ⏎
590 | text
591 | Input your cwebp options
592 | withspace
593 |
594 |
595 | inboundconfig
596 |
597 | externalid
598 | {query}
599 | usecustominputarg
600 |
601 |
602 | type
603 | alfred.workflow.input.keyword
604 | uid
605 | C4C284CD-55E1-41E9-867A-B48CA7AB5D47
606 | version
607 | 1
608 |
609 |
610 | config
611 |
612 | argument
613 |
614 | passthroughargument
615 |
616 | variables
617 |
618 | _links_list
619 | {var:_link_no_buffer}
620 |
621 |
622 | type
623 | alfred.workflow.utility.argument
624 | uid
625 | 29E00EF6-FC86-4DE7-83BC-A4D225269C5E
626 | version
627 | 1
628 |
629 |
630 | config
631 |
632 | conditions
633 |
634 |
635 | inputstring
636 |
637 | matchcasesensitive
638 |
639 | matchmode
640 | 0
641 | matchstring
642 |
643 | outputlabel
644 |
645 | uid
646 | 40F21FC1-5AB6-4DD3-BBB7-CDD2D7B59B8F
647 |
648 |
649 | elselabel
650 | else
651 | hideelse
652 |
653 |
654 | type
655 | alfred.workflow.utility.conditional
656 | uid
657 | CF9124F1-C2EF-4BBE-B066-A2CCC6C1149B
658 | version
659 | 1
660 |
661 |
662 | config
663 |
664 | argument
665 |
666 | passthroughargument
667 |
668 | variables
669 |
670 | _link_no_buffer
671 | {query}
672 |
673 |
674 | type
675 | alfred.workflow.utility.argument
676 | uid
677 | 38FEF466-6198-4D50-AA90-D70C13B216F4
678 | version
679 | 1
680 |
681 |
682 | config
683 |
684 | argument
685 |
686 | passthroughargument
687 |
688 | variables
689 |
690 | _the_preset
691 | {query}
692 |
693 |
694 | type
695 | alfred.workflow.utility.argument
696 | uid
697 | 2594B231-AB96-474F-A44E-2C733F045144
698 | version
699 | 1
700 |
701 |
702 | config
703 |
704 | concurrently
705 |
706 | escaping
707 | 102
708 | script
709 | ./compress.sh
710 | scriptargtype
711 | 1
712 | scriptfile
713 |
714 | type
715 | 5
716 |
717 | type
718 | alfred.workflow.action.script
719 | uid
720 | 3FEE47AA-2088-45F6-B112-EC2794BD9397
721 | version
722 | 2
723 |
724 |
725 | config
726 |
727 | adduuid
728 |
729 | allowemptyfiles
730 |
731 | createintermediatefolders
732 |
733 | filename
734 | {var:data_folder}/logs.txt
735 | filetext
736 | {date:YYYY/MM/dd}
737 | {time:HH:mm:ss}
738 | user input : {var:_links_list}
739 | cwebp options : {var:_the_preset}
740 | {query}
741 | ______________________
742 |
743 | ignoredynamicplaceholders
744 |
745 | relativepathmode
746 | 0
747 | type
748 | 3
749 |
750 | type
751 | alfred.workflow.output.writefile
752 | uid
753 | 3F40E4A0-B574-41EF-B31C-49AF88E9DEA3
754 | version
755 | 1
756 |
757 |
758 | config
759 |
760 | alfredfiltersresults
761 |
762 | alfredfiltersresultsmatchmode
763 | 0
764 | argumenttreatemptyqueryasnil
765 |
766 | argumenttrimmode
767 | 0
768 | argumenttype
769 | 1
770 | escaping
771 | 102
772 | queuedelaycustom
773 | 3
774 | queuedelayimmediatelyinitially
775 |
776 | queuedelaymode
777 | 0
778 | queuemode
779 | 1
780 | runningsubtext
781 | Loading elements...
782 | script
783 | osascript -l JavaScript options.js
784 | scriptargtype
785 | 1
786 | scriptfile
787 | menu.sh
788 | subtext
789 |
790 | title
791 | Select a preset or input your options
792 | type
793 | 5
794 | withspace
795 |
796 |
797 | type
798 | alfred.workflow.input.scriptfilter
799 | uid
800 | 3B719F83-111C-42AA-A4F0-3858F6AEBDF8
801 | version
802 | 3
803 |
804 |
805 | config
806 |
807 | conditions
808 |
809 |
810 | inputstring
811 | {var:workflow_action}
812 | matchcasesensitive
813 |
814 | matchmode
815 | 0
816 | matchstring
817 | _open
818 | outputlabel
819 | open
820 | uid
821 | 858CBA9A-76BF-4F4E-AB3A-16789D3C48CF
822 |
823 |
824 | inputstring
825 | {var:workflow_action}
826 | matchcasesensitive
827 |
828 | matchmode
829 | 0
830 | matchstring
831 | _reveal
832 | outputlabel
833 | reveal
834 | uid
835 | E483B0E6-5E1E-4F8E-BE08-F61FB4E857AB
836 |
837 |
838 | elselabel
839 | else
840 | hideelse
841 |
842 |
843 | type
844 | alfred.workflow.utility.conditional
845 | uid
846 | ECEF6C22-D209-4F02-8240-FFF192BCD9B9
847 | version
848 | 1
849 |
850 |
851 | config
852 |
853 | conditions
854 |
855 |
856 | inputstring
857 |
858 | matchcasesensitive
859 |
860 | matchmode
861 | 0
862 | matchstring
863 | manual
864 | outputlabel
865 |
866 | uid
867 | B04F7F98-F4C6-4E61-986D-68F6986FEA93
868 |
869 |
870 | elselabel
871 | else
872 | hideelse
873 |
874 |
875 | type
876 | alfred.workflow.utility.conditional
877 | uid
878 | E05259B6-5B68-46E1-B5E3-A2955ACC4A3A
879 | version
880 | 1
881 |
882 |
883 | config
884 |
885 | path
886 | {var:data_folder}/logs.txt
887 |
888 | type
889 | alfred.workflow.action.revealfile
890 | uid
891 | C498F126-D109-47CE-9C8D-C1439C5F5B30
892 | version
893 | 1
894 |
895 |
896 | config
897 |
898 | argument
899 |
900 | passthroughargument
901 |
902 | variables
903 |
904 | _the_preset
905 | {query}
906 |
907 |
908 | type
909 | alfred.workflow.utility.argument
910 | uid
911 | 312ACF3E-422C-4D71-B4C8-524DD7FA8B12
912 | version
913 | 1
914 |
915 |
916 | config
917 |
918 | acceptsmulti
919 | 1
920 | filetypes
921 |
922 | org.webmproject.webp
923 | public.folder
924 | public.jpeg
925 | public.png
926 | public.tiff
927 |
928 | name
929 | Compress images to WebP
930 |
931 | type
932 | alfred.workflow.trigger.action
933 | uid
934 | 2308696E-54E9-47F6-BFAD-BE577F5EA33C
935 | version
936 | 1
937 |
938 |
939 | config
940 |
941 | argument
942 |
943 | passthroughargument
944 |
945 | variables
946 |
947 | _links_list
948 | {query}
949 |
950 |
951 | type
952 | alfred.workflow.utility.argument
953 | uid
954 | 94DB40C4-AE8A-4383-B916-29465859AAF9
955 | version
956 | 1
957 |
958 |
959 | config
960 |
961 | externaltriggerid
962 | _reruncwebp
963 | passinputasargument
964 |
965 | passvariables
966 |
967 | workflowbundleid
968 | self
969 |
970 | type
971 | alfred.workflow.output.callexternaltrigger
972 | uid
973 | A5FB494F-4E88-47A0-879E-401294A7C6D4
974 | version
975 | 1
976 |
977 |
978 | config
979 |
980 | conditions
981 |
982 |
983 | inputstring
984 | {var:split1}
985 | matchcasesensitive
986 |
987 | matchmode
988 | 0
989 | matchstring
990 | _compress
991 | outputlabel
992 | compress
993 | uid
994 | 82863E01-18CA-4A51-B90A-43A845142D62
995 |
996 |
997 | inputstring
998 | {var:split1}
999 | matchcasesensitive
1000 |
1001 | matchmode
1002 | 0
1003 | matchstring
1004 | _rerun
1005 | outputlabel
1006 | rerun
1007 | uid
1008 | 1891A02A-6CF8-4BBC-B8F9-97BD1B09BF5B
1009 |
1010 |
1011 | inputstring
1012 | {var:split1}
1013 | matchcasesensitive
1014 |
1015 | matchmode
1016 | 0
1017 | matchstring
1018 | _web
1019 | outputlabel
1020 | web
1021 | uid
1022 | F94A9936-1BF8-45BE-AFB3-BED2285C65FD
1023 |
1024 |
1025 | inputstring
1026 | {var:split1}
1027 | matchcasesensitive
1028 |
1029 | matchmode
1030 | 0
1031 | matchstring
1032 | _presets
1033 | outputlabel
1034 | preset
1035 | uid
1036 | 3E3E8353-8D8A-4CFD-B5B3-BDD74E9917F5
1037 |
1038 |
1039 | elselabel
1040 | else
1041 | hideelse
1042 |
1043 |
1044 | type
1045 | alfred.workflow.utility.conditional
1046 | uid
1047 | 1F5239EB-3ECF-4E0E-8431-A65EB2327A19
1048 | version
1049 | 1
1050 |
1051 |
1052 | config
1053 |
1054 | alfredfiltersresults
1055 |
1056 | alfredfiltersresultsmatchmode
1057 | 0
1058 | argumenttreatemptyqueryasnil
1059 |
1060 | argumenttrimmode
1061 | 0
1062 | argumenttype
1063 | 1
1064 | escaping
1065 | 102
1066 | keyword
1067 | {var:trigger}
1068 | queuedelaycustom
1069 | 3
1070 | queuedelayimmediatelyinitially
1071 |
1072 | queuedelaymode
1073 | 0
1074 | queuemode
1075 | 1
1076 | runningsubtext
1077 | Loading elements...
1078 | script
1079 | osascript -l JavaScript entry.js "$1"
1080 | scriptargtype
1081 | 1
1082 | scriptfile
1083 | menu.sh
1084 | subtext
1085 | Compress images to webp format easily
1086 | title
1087 | Smart webp compression
1088 | type
1089 | 5
1090 | withspace
1091 |
1092 |
1093 | type
1094 | alfred.workflow.input.scriptfilter
1095 | uid
1096 | 8CA4509B-0219-4AD8-9C45-13EC464FF9DF
1097 | version
1098 | 3
1099 |
1100 |
1101 | config
1102 |
1103 | availableviaurlhandler
1104 |
1105 | triggerid
1106 | _reruncwebp
1107 |
1108 | type
1109 | alfred.workflow.trigger.external
1110 | uid
1111 | 29FE5492-8E67-4F8F-87A3-159939E6A097
1112 | version
1113 | 1
1114 |
1115 |
1116 | config
1117 |
1118 | delimiter
1119 | ;
1120 | discardemptyarguments
1121 |
1122 | outputas
1123 | 0
1124 | trimarguments
1125 |
1126 | variableprefix
1127 | split
1128 |
1129 | type
1130 | alfred.workflow.utility.split
1131 | uid
1132 | 045C5FE6-9D9A-4C6E-BB9F-73E732480CB9
1133 | version
1134 | 1
1135 |
1136 |
1137 | config
1138 |
1139 | conditions
1140 |
1141 |
1142 | inputstring
1143 |
1144 | matchcasesensitive
1145 |
1146 | matchmode
1147 | 1
1148 | matchstring
1149 |
1150 | outputlabel
1151 |
1152 | uid
1153 | 1891A02A-6CF8-4BBC-B8F9-97BD1B09BF5B
1154 |
1155 |
1156 | elselabel
1157 | else
1158 | hideelse
1159 |
1160 |
1161 | type
1162 | alfred.workflow.utility.conditional
1163 | uid
1164 | F2BF7B8C-1591-4877-AFF5-0EAFDFB59178
1165 | version
1166 | 1
1167 |
1168 |
1169 | config
1170 |
1171 | browser
1172 |
1173 | skipqueryencode
1174 |
1175 | skipvarencode
1176 |
1177 | spaces
1178 |
1179 | url
1180 | {var:split2}
1181 |
1182 | type
1183 | alfred.workflow.action.openurl
1184 | uid
1185 | FDEDA57C-C351-4AA4-B0D2-BA3A16A2125F
1186 | version
1187 | 1
1188 |
1189 |
1190 | config
1191 |
1192 | argumenttype
1193 | 0
1194 | subtext
1195 | Input valid cwebp options, check the documentation
1196 | text
1197 | Preset Value
1198 | withspace
1199 |
1200 |
1201 | inboundconfig
1202 |
1203 | externalid
1204 | {query}
1205 | usecustominputarg
1206 |
1207 |
1208 | type
1209 | alfred.workflow.input.keyword
1210 | uid
1211 | 0BC6A292-B409-4DAC-8EA9-2C8604D1F303
1212 | version
1213 | 1
1214 |
1215 |
1216 | config
1217 |
1218 | argumenttype
1219 | 0
1220 | subtext
1221 | Input a title and a description for the preset ǀ Example: 'My Preset/Some description'
1222 | text
1223 | Preset Title/Subtitle
1224 | withspace
1225 |
1226 |
1227 | type
1228 | alfred.workflow.input.keyword
1229 | uid
1230 | 24C70ED0-81F4-484E-841F-032B110455CA
1231 | version
1232 | 1
1233 |
1234 |
1235 | config
1236 |
1237 | argument
1238 |
1239 | passthroughargument
1240 |
1241 | variables
1242 |
1243 | _new_preset
1244 | {query}
1245 |
1246 |
1247 | type
1248 | alfred.workflow.utility.argument
1249 | uid
1250 | 42AF05BF-C545-42DF-AC3B-9F81F851C963
1251 | version
1252 | 1
1253 |
1254 |
1255 | config
1256 |
1257 | concurrently
1258 |
1259 | escaping
1260 | 102
1261 | script
1262 | osascript -l JavaScript presets.js "$1"
1263 | scriptargtype
1264 | 1
1265 | scriptfile
1266 |
1267 | type
1268 | 5
1269 |
1270 | type
1271 | alfred.workflow.action.script
1272 | uid
1273 | 6C3B838B-C528-449D-B058-3836F59421EA
1274 | version
1275 | 2
1276 |
1277 |
1278 | config
1279 |
1280 | conditions
1281 |
1282 |
1283 | inputstring
1284 | {var:split2}
1285 | matchcasesensitive
1286 |
1287 | matchmode
1288 | 0
1289 | matchstring
1290 | new
1291 | outputlabel
1292 | new
1293 | uid
1294 | 40F21FC1-5AB6-4DD3-BBB7-CDD2D7B59B8F
1295 |
1296 |
1297 | inputstring
1298 | {var:split2}
1299 | matchcasesensitive
1300 |
1301 | matchmode
1302 | 0
1303 | matchstring
1304 | delete
1305 | outputlabel
1306 | delete
1307 | uid
1308 | 9A4468F5-CA10-41FA-9110-3FEAA5816577
1309 |
1310 |
1311 | inputstring
1312 | {var:split2}
1313 | matchcasesensitive
1314 |
1315 | matchmode
1316 | 0
1317 | matchstring
1318 | modify
1319 | outputlabel
1320 | modify
1321 | uid
1322 | 8EE14863-8E4A-47BE-9D21-B6624353D444
1323 |
1324 |
1325 | elselabel
1326 | else
1327 | hideelse
1328 |
1329 |
1330 | type
1331 | alfred.workflow.utility.conditional
1332 | uid
1333 | E059706B-E9CB-457B-A984-1F96041A300B
1334 | version
1335 | 1
1336 |
1337 |
1338 | config
1339 |
1340 | argumenttype
1341 | 0
1342 | subtext
1343 | Don't forget to use a '/' to separate elements
1344 | text
1345 | Modify the {var:modif4}
1346 | withspace
1347 |
1348 |
1349 | inboundconfig
1350 |
1351 | custominputarg
1352 | {var:modif5}
1353 | externalid
1354 | {query}
1355 | usecustominputarg
1356 |
1357 |
1358 | type
1359 | alfred.workflow.input.keyword
1360 | uid
1361 | 3BC14125-DD5B-4FA9-9AD5-A3A69F183B2F
1362 | version
1363 | 1
1364 |
1365 |
1366 | config
1367 |
1368 | delimiter
1369 | ;
1370 | discardemptyarguments
1371 |
1372 | outputas
1373 | 0
1374 | trimarguments
1375 |
1376 | variableprefix
1377 | modif
1378 |
1379 | type
1380 | alfred.workflow.utility.split
1381 | uid
1382 | 7587F5D4-DC06-4411-BDC1-EA1FD81363D6
1383 | version
1384 | 1
1385 |
1386 |
1387 | readme
1388 | # 🎩 Alfred Smart WebP
1389 |
1390 | ✨ *Transform your images into WebP format with ease* ✨
1391 |
1392 | ## ✅ Prerequisites
1393 |
1394 | * MacOS.
1395 | * Alfred 5. Note that the [Alfred Powerpack](https://www.alfredapp.com/powerpack/) is required to use workflows.
1396 |
1397 | ## 🏎️ cwebp
1398 |
1399 | Under the hood, the compression is made with [cwebp](https://developers.google.com/speed/webp/docs/cwebp) (made by Google), a tool that allows to compress images into the WebP format, which is generally lighter, and broadly used to share images on the web.
1400 |
1401 | ## 🧰 Setup the workflow
1402 |
1403 | #### Open the Terminal of you Mac and run the following command:
1404 |
1405 | Install cwebp (using [Homebrew](https://brew.sh)):
1406 |
1407 | `brew install webp`
1408 |
1409 | ## 🧙♂️ Invoke the workflow
1410 |
1411 | You can invoke the workflow by writing `webp` into the Alfred search box. You can change this value by changing the `🕹️ Trigger` variable in workflow configuration panel.
1412 |
1413 | ## 🤖 Usage of the workflow
1414 |
1415 | Go to the dedicated [GitHub repository](https://github.com/BenjaminOddou/alfred-smart-webp-compression) page to check the documentation
1416 |
1417 | © Benjamin Oddou
1418 | uidata
1419 |
1420 | 045C5FE6-9D9A-4C6E-BB9F-73E732480CB9
1421 |
1422 | xpos
1423 | 535
1424 | ypos
1425 | 435
1426 |
1427 | 0BC6A292-B409-4DAC-8EA9-2C8604D1F303
1428 |
1429 | xpos
1430 | 950
1431 | ypos
1432 | 635
1433 |
1434 | 13DDCB6C-9438-4C2B-B386-867F758EEDAF
1435 |
1436 | xpos
1437 | 950
1438 | ypos
1439 | 145
1440 |
1441 | 1F5239EB-3ECF-4E0E-8431-A65EB2327A19
1442 |
1443 | xpos
1444 | 620
1445 | ypos
1446 | 395
1447 |
1448 | 2308696E-54E9-47F6-BFAD-BE577F5EA33C
1449 |
1450 | xpos
1451 | 950
1452 | ypos
1453 | 265
1454 |
1455 | 24C70ED0-81F4-484E-841F-032B110455CA
1456 |
1457 | xpos
1458 | 1235
1459 | ypos
1460 | 635
1461 |
1462 | 2594B231-AB96-474F-A44E-2C733F045144
1463 |
1464 | xpos
1465 | 2005
1466 | ypos
1467 | 180
1468 |
1469 | 29E00EF6-FC86-4DE7-83BC-A4D225269C5E
1470 |
1471 | xpos
1472 | 1480
1473 | ypos
1474 | 160
1475 |
1476 | 29FE5492-8E67-4F8F-87A3-159939E6A097
1477 |
1478 | xpos
1479 | 95
1480 | ypos
1481 | 405
1482 |
1483 | 312ACF3E-422C-4D71-B4C8-524DD7FA8B12
1484 |
1485 | xpos
1486 | 2005
1487 | ypos
1488 | 245
1489 |
1490 | 38FEF466-6198-4D50-AA90-D70C13B216F4
1491 |
1492 | xpos
1493 | 1130
1494 | ypos
1495 | 175
1496 |
1497 | 3B719F83-111C-42AA-A4F0-3858F6AEBDF8
1498 |
1499 | xpos
1500 | 1560
1501 | ypos
1502 | 200
1503 |
1504 | 3BC14125-DD5B-4FA9-9AD5-A3A69F183B2F
1505 |
1506 | xpos
1507 | 1235
1508 | ypos
1509 | 795
1510 |
1511 | 3F40E4A0-B574-41EF-B31C-49AF88E9DEA3
1512 |
1513 | xpos
1514 | 2300
1515 | ypos
1516 | 185
1517 |
1518 | 3FEE47AA-2088-45F6-B112-EC2794BD9397
1519 |
1520 | colorindex
1521 | 11
1522 | xpos
1523 | 2135
1524 | ypos
1525 | 185
1526 |
1527 | 42AF05BF-C545-42DF-AC3B-9F81F851C963
1528 |
1529 | xpos
1530 | 1130
1531 | ypos
1532 | 665
1533 |
1534 | 58F33492-15F5-46AB-A362-CA56E17F396D
1535 |
1536 | xpos
1537 | 2595
1538 | ypos
1539 | 125
1540 |
1541 | 69BA9B7D-DD02-4970-AF06-8266F95388C9
1542 |
1543 | xpos
1544 | 1235
1545 | ypos
1546 | 145
1547 |
1548 | 6C3B838B-C528-449D-B058-3836F59421EA
1549 |
1550 | colorindex
1551 | 8
1552 | xpos
1553 | 1465
1554 | ypos
1555 | 715
1556 |
1557 | 7587F5D4-DC06-4411-BDC1-EA1FD81363D6
1558 |
1559 | xpos
1560 | 1130
1561 | ypos
1562 | 825
1563 |
1564 | 8CA4509B-0219-4AD8-9C45-13EC464FF9DF
1565 |
1566 | xpos
1567 | 305
1568 | ypos
1569 | 405
1570 |
1571 | 94DB40C4-AE8A-4383-B916-29465859AAF9
1572 |
1573 | xpos
1574 | 1480
1575 | ypos
1576 | 295
1577 |
1578 | A5FB494F-4E88-47A0-879E-401294A7C6D4
1579 |
1580 | xpos
1581 | 950
1582 | ypos
1583 | 390
1584 |
1585 | C498F126-D109-47CE-9C8D-C1439C5F5B30
1586 |
1587 | xpos
1588 | 2595
1589 | ypos
1590 | 245
1591 |
1592 | C4C284CD-55E1-41E9-867A-B48CA7AB5D47
1593 |
1594 | xpos
1595 | 1825
1596 | ypos
1597 | 150
1598 |
1599 | CF9124F1-C2EF-4BBE-B066-A2CCC6C1149B
1600 |
1601 | xpos
1602 | 1385
1603 | ypos
1604 | 165
1605 |
1606 | E05259B6-5B68-46E1-B5E3-A2955ACC4A3A
1607 |
1608 | xpos
1609 | 1740
1610 | ypos
1611 | 220
1612 |
1613 | E059706B-E9CB-457B-A984-1F96041A300B
1614 |
1615 | xpos
1616 | 775
1617 | ypos
1618 | 720
1619 |
1620 | ECEF6C22-D209-4F02-8240-FFF192BCD9B9
1621 |
1622 | xpos
1623 | 2465
1624 | ypos
1625 | 205
1626 |
1627 | F2BF7B8C-1591-4877-AFF5-0EAFDFB59178
1628 |
1629 | xpos
1630 | 465
1631 | ypos
1632 | 435
1633 |
1634 | FDEDA57C-C351-4AA4-B0D2-BA3A16A2125F
1635 |
1636 | xpos
1637 | 950
1638 | ypos
1639 | 510
1640 |
1641 |
1642 | userconfigurationconfig
1643 |
1644 |
1645 | config
1646 |
1647 | default
1648 | ~/Library/Application Support/Alfred/Workflow Data/com.benjamino.smart_webp_compression
1649 | filtermode
1650 | 1
1651 | placeholder
1652 |
1653 | required
1654 |
1655 |
1656 | description
1657 | this folder contains presets and logs outputs.
1658 | label
1659 | 📂 Data folder
1660 | type
1661 | filepicker
1662 | variable
1663 | data_folder
1664 |
1665 |
1666 | config
1667 |
1668 | default
1669 | webp
1670 | placeholder
1671 |
1672 | required
1673 |
1674 | trim
1675 |
1676 |
1677 | description
1678 | keyword that launches the workflow.
1679 | label
1680 | 🕹️ Trigger
1681 | type
1682 | textfield
1683 | variable
1684 | trigger
1685 |
1686 |
1687 | config
1688 |
1689 | default
1690 | 1
1691 | placeholder
1692 |
1693 | required
1694 |
1695 | trim
1696 |
1697 |
1698 | description
1699 | input a value between 1 and ∞. allows to compress images in nested folders.
1700 | label
1701 | 🔍 Depth of the search
1702 | type
1703 | textfield
1704 | variable
1705 | level
1706 |
1707 |
1708 | config
1709 |
1710 | default
1711 | _open
1712 | pairs
1713 |
1714 |
1715 | Open log file 🟢
1716 | _open
1717 |
1718 |
1719 | Reveal log file in finder 🔵
1720 | _reveal
1721 |
1722 |
1723 | Display a notification 🟡
1724 | _notif
1725 |
1726 |
1727 | Do nothing 🔴
1728 |
1729 |
1730 |
1731 |
1732 | description
1733 | choose output action.
1734 | label
1735 | 🔫 Workflow action
1736 | type
1737 | popupbutton
1738 | variable
1739 | workflow_action
1740 |
1741 |
1742 | config
1743 |
1744 | default
1745 | Submarine
1746 | pairs
1747 |
1748 |
1749 | Mute 🔕
1750 |
1751 |
1752 |
1753 | Submarine 🤿
1754 | Submarine
1755 |
1756 |
1757 | Pop 🎉
1758 | Pop
1759 |
1760 |
1761 | Ping ✨
1762 | Ping
1763 |
1764 |
1765 | Purr 🐯
1766 | Purr
1767 |
1768 |
1769 | Hero ⚔️
1770 | Hero
1771 |
1772 |
1773 | Funk 🕺
1774 | Funk
1775 |
1776 |
1777 | Basso 🎧
1778 | Basso
1779 |
1780 |
1781 | Sosumi 📻
1782 | Sosumi
1783 |
1784 |
1785 | Glass 🍸
1786 | Glass
1787 |
1788 |
1789 | Blow 💨
1790 | Blow
1791 |
1792 |
1793 | Bottle 🍼
1794 | Bottle
1795 |
1796 |
1797 | Frog 🐸
1798 | Frog
1799 |
1800 |
1801 | Tink 🛎️
1802 | Tink
1803 |
1804 |
1805 | Morse ♨️
1806 | Morse
1807 |
1808 |
1809 | Classic 😃
1810 | default
1811 |
1812 |
1813 |
1814 | description
1815 | workflow notification sound.
1816 | label
1817 | 🎷 Notification sound
1818 | type
1819 | popupbutton
1820 | variable
1821 | sound
1822 |
1823 |
1824 | variablesdontexport
1825 |
1826 | version
1827 | 3.0.2
1828 | webaddress
1829 | https://github.com/BenjaminOddou/alfred-smart-webp-compression
1830 |
1831 |
1832 |
--------------------------------------------------------------------------------
/src/json/presets.json:
--------------------------------------------------------------------------------
1 | {
2 | "items": [
3 | {
4 | "title": "Example of presets ↓",
5 | "subtitle": "Press ⏎ to modify the preset. These are just examples, you can remove them",
6 | "arg": "remove me",
7 | "id": "9563BA83-6322-4392-9B39-93FE9A13CE47",
8 | "icon": {
9 | "path": "icons/presets.webp"
10 | }
11 | },
12 | {
13 | "title": "Classic",
14 | "subtitle": "Good quality (80) with slow compression and multithread",
15 | "arg": "-v -print_psnr -print_ssim -print_lsim -m 6 -q 70 -mt -af",
16 | "id": "C9536D8E-79E1-4E51-B94B-65FD313BC32E",
17 | "icon": {
18 | "path": "icons/presets.webp"
19 | }
20 | },
21 | {
22 | "title": "Crop 64px",
23 | "subtitle": "Crop image to 64px height + medium quality (60)",
24 | "arg": "-q 60 -resize 64 0",
25 | "id": "4F77F996-0B86-4036-9B8D-9104DA5A523F",
26 | "icon": {
27 | "path": "icons/presets.webp"
28 | }
29 | }
30 | ]
31 | }
--------------------------------------------------------------------------------
/src/notificator:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 |
3 | ####################################################
4 | ### Created by Vítor Galvão ###
5 | ### Find the latest version at: ###
6 | ### https://github.com/vitorgalvao/notificator ###
7 | ####################################################
8 |
9 | readonly program="$(basename "${0}")"
10 |
11 | # Helpers
12 | function show_notification {
13 | /usr/bin/open "${app}" --args "${notificator_message}" "${notificator_title}" "${notificator_subtitle}" "${notificator_sound}"
14 | }
15 |
16 | function make_icns {
17 | # Setup
18 | local -r file="${1}"
19 | local -r tmp_dir="$(/usr/bin/mktemp -d)"
20 | local -r icon="${tmp_dir}/icon.icns"
21 | local -r iconset="${tmp_dir}/icon.iconset"
22 | /bin/mkdir "${iconset}"
23 |
24 | # Create iconset
25 | for size in {16,32,64,128,256,512}; do
26 | /usr/bin/sips --resampleHeightWidth "${size}" "${size}" "${file}" --out "${iconset}/icon_${size}x${size}.png" &> /dev/null
27 | /usr/bin/sips --resampleHeightWidth "$((size * 2))" "$((size * 2))" "${file}" --out "${iconset}/icon_${size}x${size}@2x.png" &> /dev/null
28 | done
29 |
30 | # Convert to icns
31 | /usr/bin/iconutil --convert icns "${iconset}" --output "${icon}"
32 |
33 | # Clean up and return path to icns
34 | /bin/rm -rf "${iconset}"
35 | echo "${icon}"
36 | }
37 |
38 | function usage {
39 | echo "
40 | Trigger macOS notifications from Alfred, using the Workflow icon
41 |
42 | Usage:
43 | ${program} --message [options]
44 |
45 | Options:
46 | -m, --message Message text
47 | -t, --title Title text
48 | -s, --subtitle Subtitle text
49 | -p, --sound Sound name (from /System/Library/Sounds)
50 | -h, --help Show this help
51 | " | sed -E 's/^ {4}//'
52 | }
53 |
54 | # Options
55 | args=()
56 | while [[ "${1}" ]]; do
57 | case "${1}" in
58 | -h | --help)
59 | usage
60 | exit 0
61 | ;;
62 | -m | --message)
63 | readonly notificator_message="${2}"
64 | shift
65 | ;;
66 | -t | --title)
67 | readonly notificator_title="${2}"
68 | shift
69 | ;;
70 | -s | --subtitle)
71 | readonly notificator_subtitle="${2}"
72 | shift
73 | ;;
74 | -p | --sound)
75 | readonly notificator_sound="${2}"
76 | shift
77 | ;;
78 | --)
79 | shift
80 | args+=("${@}")
81 | break
82 | ;;
83 | -*)
84 | echo "Unrecognised option: ${1}"
85 | exit 1
86 | ;;
87 | *)
88 | args+=("${1}")
89 | ;;
90 | esac
91 | shift
92 | done
93 | set -- "${args[@]}"
94 |
95 | # Check for required arguments
96 | if [[ -z "${notificator_message}" ]]; then
97 | echo 'A message is mandatory! Aborting…' >&2
98 | exit 1
99 | fi
100 |
101 | readonly bundle_id="$(tr -cd '[:alnum:]._-' <<< "${alfred_workflow_bundleid}")"
102 | readonly name="$(tr -cd '[:alnum:]._- ' <<< "${alfred_workflow_name}")"
103 | readonly icon="${alfred_preferences}/workflows/${alfred_workflow_uid}/icon.png"
104 | readonly app="${alfred_workflow_cache}/Notificator for ${name}.app"
105 | readonly plist="${app}/Contents/Info.plist"
106 |
107 | # Exit early if Notificator exists and was modified fewer than 30 days ago
108 | if [[ -e "${app}" && -n "$(find "${app}" -depth 0 -mtime -30)" ]]; then
109 | show_notification
110 | exit 0
111 | fi
112 |
113 | # Pre-build checks
114 | if [[ -z "${bundle_id}" ]]; then
115 | echo "Workflow is missing the bundle identifier! Aborting…" >&2
116 | exit 1
117 | fi
118 |
119 | if [[ -z "${name}" ]]; then
120 | echo "Workflow is missing the name! Aborting…" >&2
121 | exit 1
122 | fi
123 |
124 | if [[ ! -f "${icon}" ]]; then
125 | echo "Workflow is missing the icon! Aborting…" >&2
126 | exit 1
127 | fi
128 |
129 | # Build Notificator
130 | readonly jxa_script='
131 | // Build argv/argc in a way that can be used from the applet inside the app bundle
132 | ObjC.import("Foundation")
133 | const args = $.NSProcessInfo.processInfo.arguments
134 | const argv = []
135 | const argc = args.count
136 | for (let i = 0; i < argc; i++) { argv.push(ObjC.unwrap(args.objectAtIndex(i))) }
137 |
138 | // Notification script
139 | const app = Application.currentApplication()
140 | app.includeStandardAdditions = true
141 |
142 | if (argv.length < 2) { // We use "2" because the script will always see at least one argument: the applet itself
143 | argv[1] = "Opening usage instructions…"
144 | argv[2] = "Notificator is a command-line app"
145 | argv[4] = "Funk"
146 |
147 | app.openLocation("https://github.com/vitorgalvao/notificator#usage")
148 | }
149 |
150 | const message = argv[1]
151 | const title = argv[2]
152 | const subtitle = argv[3]
153 | const sound = argv[4]
154 |
155 | const options = {}
156 | if (title) options.withTitle = title
157 | if (subtitle) options.subtitle = subtitle
158 | if (sound) options.soundName = sound
159 |
160 | app.displayNotification(message, options)
161 | '
162 |
163 | [[ -d "${app}" ]] && rm -r "${app}"
164 | /bin/mkdir -p "${alfred_workflow_cache}"
165 | /usr/bin/osacompile -l JavaScript -o "${app}" -e "${jxa_script}" 2> /dev/null
166 |
167 | # Modify Notificator
168 | /usr/libexec/PlistBuddy -c "add :CFBundleIdentifier string ${bundle_id}.notificator" "${plist}"
169 | /usr/libexec/PlistBuddy -c 'add :LSUIElement string 1' "${plist}"
170 | mv "$(make_icns "${icon}")" "${app}/Contents/Resources/applet.icns"
171 |
172 | # Redo signature
173 | codesign --remove-signature "${app}"
174 | codesign --sign - "${app}"
175 |
176 | show_notification
--------------------------------------------------------------------------------
/src/options.js:
--------------------------------------------------------------------------------
1 | ObjC.import('stdlib')
2 | const app = Application.currentApplication()
3 | app.includeStandardAdditions = true
4 | const PWD = $.getenv("PWD")
5 | const fm = $.NSFileManager.defaultManager
6 | const encoding = $.NSUTF8StringEncoding
7 | const data_folder = $.NSProcessInfo.processInfo.environment.objectForKey('data_folder')?.js || $.NSProcessInfo.processInfo.environment.objectForKey('alfred_workflow_data').js
8 | let items = []
9 |
10 | function readFile(path) {
11 | if (fm.fileExistsAtPath(path)) {
12 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
13 | } else {
14 | const sourcePath = `${PWD}/json/presets.json`
15 | fm.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(data_folder, true, $(), null)
16 | fm.copyItemAtPathToPathError(sourcePath, path, null)
17 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
18 | }
19 | }
20 |
21 | items.push(
22 | {
23 | title: 'Manual options',
24 | subtitle: 'Run the cwebp compression with your manual input',
25 | arg: 'manual',
26 | icon: { path: 'icons/manual.webp' },
27 | },
28 | )
29 | try {
30 | content = JSON.parse(readFile(`${data_folder}/presets.json`))
31 | content.items.forEach(item => { items.push(item) })
32 | } catch {}
33 |
34 | JSON.stringify({ items })
--------------------------------------------------------------------------------
/src/presets.js:
--------------------------------------------------------------------------------
1 | ObjC.import('stdlib')
2 | ObjC.import('Cocoa')
3 | const app = Application.currentApplication()
4 | app.includeStandardAdditions = true
5 | const fm = $.NSFileManager.defaultManager
6 | const encoding = $.NSUTF8StringEncoding
7 | const sound = $.NSProcessInfo.processInfo.environment.objectForKey('sound')?.js || 'Submarine'
8 | const data_folder = $.NSProcessInfo.processInfo.environment.objectForKey('data_folder')?.js || $.NSProcessInfo.processInfo.environment.objectForKey('alfred_workflow_data').js
9 | const action = $.NSProcessInfo.processInfo.environment.objectForKey('split2')?.js || ''
10 | let items =[]
11 |
12 | function readFile(path) {
13 | if (fm.fileExistsAtPath(path)) {
14 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
15 | } else {
16 | const sourcePath = `${PWD}/json/presets.json`
17 | fm.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(data_folder, true, $(), null)
18 | fm.copyItemAtPathToPathError(sourcePath, path, null)
19 | return $.NSString.stringWithContentsOfFileEncodingError(path, encoding, null).js
20 | }
21 | }
22 |
23 | content = JSON.parse(readFile(`${data_folder}/presets.json`))
24 |
25 | try {
26 | if (action == 'new') {
27 | const uuid = $.NSUUID.UUID.UUIDString.js
28 | const _new_preset = $.NSProcessInfo.processInfo.environment.objectForKey('_new_preset')?.js || ''
29 | const args = $.NSProcessInfo.processInfo.arguments.objectAtIndex(4).js.split('/')
30 | const title = args[0]?.trim() !== '' ? args[0]?.trim() : 'No title';
31 | const subtitle = args[1]?.trim() !== '' ? args[1]?.trim() : 'No description';
32 | items.push(
33 | {
34 | title: `${title}`,
35 | subtitle: `${subtitle}`,
36 | arg: `${_new_preset}`,
37 | id: `${uuid}`,
38 | icon: { path: 'icons/presets.webp' },
39 | },
40 | )
41 | content.items.forEach(item => { items.push(item) })
42 | app.doShellScript('./notificator --title "✅ Success !" --message "Preset ' + title + ' created" --sound "'+ sound + '"')
43 | } else if (action == 'delete') {
44 | const key = $.NSProcessInfo.processInfo.environment.objectForKey('split3')?.js || ''
45 | content.items.forEach(item => {
46 | if (item.id != key) {
47 | items.push(item)
48 | } else {
49 | app.doShellScript('./notificator --title "✅ Success !" --message "Preset ' + item.title + ' deleted" --sound "'+ sound + '"')
50 | }
51 | })
52 | } else if (action == 'modify') {
53 | const type = $.NSProcessInfo.processInfo.environment.objectForKey('modif3')?.js || ''
54 | const new_value = $.NSProcessInfo.processInfo.arguments.objectAtIndex(4).js
55 | const key = $.NSProcessInfo.processInfo.environment.objectForKey('modif6')?.js || ''
56 | if (type == 'tl&sb') {
57 | const args = new_value.split('/')
58 | const title = args[0]?.trim() !== '' ? args[0]?.trim() : 'No title';
59 | const subtitle = args[1]?.trim() !== '' ? args[1]?.trim() : 'No description';
60 | content.items.forEach(item => {
61 | if (item.id == key) {
62 | item.title = title
63 | item.subtitle = subtitle
64 | app.doShellScript('./notificator --title "✅ Success !" --message "Preset ' + title + ' modified" --sound "'+ sound + '"')
65 | }
66 | items.push(item)
67 | })
68 | } else if (type == 'arg') {
69 | content.items.forEach(item => {
70 | if (item.id == key) {
71 | item.arg = new_value
72 | app.doShellScript('./notificator --title "✅ Success !" --message "Preset ' + item.title + ' modified" --sound "'+ sound + '"')
73 | }
74 | items.push(item)
75 | })
76 | }
77 |
78 | }
79 |
80 | $.NSString.alloc.initWithUTF8String(JSON.stringify({'items': items}, null, 4))
81 | .writeToFileAtomicallyEncodingError(`${data_folder}/presets.json`, true, encoding, null)
82 | } catch (e) {
83 | app.doShellScript('./notificator --title "🚨 Error !" --message "' + e + '" --sound "'+ sound + '"')
84 | }
--------------------------------------------------------------------------------