├── .github └── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_suggestion.yml ├── LICENSE ├── README.md └── Workflow ├── icon.png ├── images └── about │ ├── tinypng.png │ └── ua.png └── info.plist /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | body: 4 | - type: input 5 | attributes: 6 | label: Workflow version 7 | description: Open the Workflow in Alfred Preferences and find it at the top, near the description 8 | validations: 9 | required: true 10 | - type: input 11 | attributes: 12 | label: Alfred version 13 | description: In the top left corner of Alfred Preferences → General 14 | validations: 15 | required: true 16 | - type: input 17 | attributes: 18 | label: macOS version 19 | description: Click  on the menubar → About This Mac 20 | validations: 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: Debugger output 25 | description: Perform the failing action with [the debugger](https://www.alfredapp.com/help/workflows/advanced/debugger/) open 26 | render: alfred_debugger 27 | validations: 28 | required: true 29 | - type: textarea 30 | attributes: 31 | label: More details 32 | description: Explain what you did, what happened, and what you expected to happen 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_suggestion.yml: -------------------------------------------------------------------------------- 1 | name: Feature Suggestion 2 | description: Suggest a new feature 3 | body: 4 | - type: textarea 5 | attributes: 6 | label: Feature details 7 | description: Explain the feature idea 8 | validations: 9 | required: true 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Running with Crayons Ltd 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # icon TinyPNG Alfred Workflow 2 | 3 | Compress images via TinyPNG 4 | 5 | [⤓ Install on the Alfred Gallery](https://alfred.app/workflows/alfredapp/tinypng) 6 | 7 | ## Usage 8 | 9 | Compress PNG, JPEG, and WebP images with [TinyPNG](https://tinypng.com/) via the [Universal Action](https://www.alfredapp.com/help/features/universal-actions/). 10 | 11 | ![Universal Action for TinyPNG Compression](Workflow/images/about/ua.png) 12 | 13 | Alternatively, find images with the `tinypng` keyword. 14 | 15 | ![Alfred search for tinypng transparenc](Workflow/images/about/tinypng.png) 16 | -------------------------------------------------------------------------------- /Workflow/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfredapp/tinypng-workflow/8a5be899cc8c79cc6eef0011e750781b28859061/Workflow/icon.png -------------------------------------------------------------------------------- /Workflow/images/about/tinypng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfredapp/tinypng-workflow/8a5be899cc8c79cc6eef0011e750781b28859061/Workflow/images/about/tinypng.png -------------------------------------------------------------------------------- /Workflow/images/about/ua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfredapp/tinypng-workflow/8a5be899cc8c79cc6eef0011e750781b28859061/Workflow/images/about/ua.png -------------------------------------------------------------------------------- /Workflow/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | com.alfredapp.vitor.tinypng 7 | connections 8 | 9 | 392049EC-35AB-4C54-8A20-5565FBF67B32 10 | 11 | 12 | destinationuid 13 | F2C7428D-06C2-4B70-8C70-8348AE71B137 14 | modifiers 15 | 0 16 | modifiersubtext 17 | 18 | vitoclose 19 | 20 | 21 | 22 | 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 23 | 24 | 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE 25 | 26 | 27 | destinationuid 28 | F2C7428D-06C2-4B70-8C70-8348AE71B137 29 | modifiers 30 | 0 31 | modifiersubtext 32 | 33 | vitoclose 34 | 35 | 36 | 37 | 8F44CFA0-9821-4998-B57A-CBD196BD069B 38 | 39 | 40 | destinationuid 41 | F2C7428D-06C2-4B70-8C70-8348AE71B137 42 | modifiers 43 | 0 44 | modifiersubtext 45 | 46 | vitoclose 47 | 48 | 49 | 50 | 9EDA38AD-8C38-42CA-A270-CFE7AEC0655C 51 | 52 | 53 | destinationuid 54 | 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 55 | modifiers 56 | 0 57 | modifiersubtext 58 | 59 | vitoclose 60 | 61 | 62 | 63 | destinationuid 64 | C22E0CBD-0683-4E3A-80E5-6532D8E5440E 65 | modifiers 66 | 0 67 | modifiersubtext 68 | 69 | vitoclose 70 | 71 | 72 | 73 | C22E0CBD-0683-4E3A-80E5-6532D8E5440E 74 | 75 | 76 | destinationuid 77 | 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 78 | modifiers 79 | 0 80 | modifiersubtext 81 | 82 | sourceoutputuid 83 | 2402FAA7-E693-486D-84EA-BF27BF8E4AFD 84 | vitoclose 85 | 86 | 87 | 88 | destinationuid 89 | 6D56D157-3EBC-41F6-A030-1C9A9E4490DF 90 | modifiers 91 | 0 92 | modifiersubtext 93 | 94 | vitoclose 95 | 96 | 97 | 98 | CB42BCC1-C05C-4B82-821E-BF371D852F7A 99 | 100 | 101 | destinationuid 102 | 8F44CFA0-9821-4998-B57A-CBD196BD069B 103 | modifiers 104 | 0 105 | modifiersubtext 106 | 107 | vitoclose 108 | 109 | 110 | 111 | F2C7428D-06C2-4B70-8C70-8348AE71B137 112 | 113 | 114 | destinationuid 115 | 9EDA38AD-8C38-42CA-A270-CFE7AEC0655C 116 | modifiers 117 | 0 118 | modifiersubtext 119 | 120 | vitoclose 121 | 122 | 123 | 124 | FD60CC76-3DD5-45D7-A184-5A5580E0790F 125 | 126 | 127 | destinationuid 128 | F2C7428D-06C2-4B70-8C70-8348AE71B137 129 | modifiers 130 | 0 131 | modifiersubtext 132 | 133 | vitoclose 134 | 135 | 136 | 137 | 138 | createdby 139 | Vítor Galvão 140 | description 141 | Compress images via TinyPNG 142 | disabled 143 | 144 | name 145 | TinyPNG 146 | objects 147 | 148 | 149 | config 150 | 151 | acceptsmulti 152 | 1 153 | filetypes 154 | 155 | org.webmproject.webp 156 | public.jpeg 157 | public.png 158 | 159 | name 160 | TinyPNG Compression 161 | 162 | type 163 | alfred.workflow.trigger.action 164 | uid 165 | 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE 166 | version 167 | 1 168 | 169 | 170 | config 171 | 172 | concurrently 173 | 174 | escaping 175 | 102 176 | script 177 | # Constants 178 | readonly backup_dir="${backup_originals}/$(date +'%Y.%m.%d.%H.%M.%S')" 179 | 180 | # Helpers 181 | function get_json_key { 182 | local -r json="${1}" # JSON string 183 | local -r key="${2}" # Of the form ['first']['second'] or .first.second 184 | 185 | local -r result="$(/usr/bin/osascript -l 'JavaScript' -e "function run(argv) { return JSON.parse(argv[0])${key} }" "${json}")" 186 | 187 | [[ -n "${key}" && -n "${result}" ]] || return 1 # If no valid result 188 | 189 | echo -n "${result}" 190 | } 191 | 192 | function state { 193 | /usr/bin/osascript -l JavaScript -e "function run(argv) { 194 | return JSON.stringify({ alfredworkflow: { variables: { 195 | success: argv[0] === 'success', 196 | message: argv[1] 197 | }}}) 198 | }" "${1}" "${2}" 199 | } 200 | 201 | function error { 202 | echo "${1}" >&2 # For Alfred's debugger 203 | state 'failure' "${1}" # For the notification and sound 204 | exit 1 205 | } 206 | 207 | # Main 208 | # Abort if backups are desirable but cannot create directory 209 | if [[ -n "${backup_originals}" ]] && ! /bin/mkdir -p "${backup_dir}"; then 210 | error "Could not create backups directory at ${backup_originals}!" 211 | fi 212 | 213 | # Loop over images 214 | for image in "${@}"; do 215 | json_response="$(/usr/bin/curl --silent --user api:"${api_key}" --data-binary @"${image}" -i 'https://api.tinify.com/shrink' | /usr/bin/tail -1)" 216 | 217 | # On failed connection 218 | if [[ -z "${json_response}" ]]; then 219 | error 'Unable to connect to TinyPNG' 220 | fi 221 | 222 | # On error 223 | if [[ -n "$(get_json_key "${json_response}" '.error')" ]]; then 224 | error "$(get_json_key "${json_response}" '.message')" 225 | fi 226 | 227 | # Backup image 228 | if [[ -d "${backup_dir}" ]]; then 229 | /bin/cp -p "${image}" "${backup_dir}" 230 | fi 231 | 232 | # Save result 233 | compressed_url="$(get_json_key "${json_response}" '.output.url')" 234 | /usr/bin/curl --silent "${compressed_url}" --output "${image}" 235 | done 236 | 237 | state 'success' 'Finished compressing' 238 | scriptargtype 239 | 1 240 | scriptfile 241 | 242 | type 243 | 11 244 | 245 | type 246 | alfred.workflow.action.script 247 | uid 248 | F2C7428D-06C2-4B70-8C70-8348AE71B137 249 | version 250 | 2 251 | 252 | 253 | config 254 | 255 | anchorfields 256 | 257 | argumenttrimmode 258 | 0 259 | argumenttype 260 | 0 261 | daterange 262 | 0 263 | fields 264 | 265 | 266 | field 267 | kMDItemDisplayName 268 | not 269 | 270 | split 271 | 272 | value 273 | {query} 274 | words 275 | 276 | 277 | 278 | field 279 | kMDItemAlternateNames 280 | not 281 | 282 | split 283 | 284 | value 285 | {query} 286 | words 287 | 288 | 289 | 290 | field 291 | kMDItemFinderComment 292 | not 293 | 294 | split 295 | 296 | value 297 | {query} 298 | words 299 | 300 | 301 | 302 | includesystem 303 | 304 | keyword 305 | {var:search_keyword} 306 | limit 307 | 0 308 | runningsubtext 309 | 310 | scopes 311 | 312 | sortmode 313 | 0 314 | subtext 315 | Filter for images to compress 316 | title 317 | TinyPNG Compression 318 | types 319 | 320 | org.webmproject.webp 321 | public.jpeg 322 | public.png 323 | 324 | withspace 325 | 326 | 327 | type 328 | alfred.workflow.input.filefilter 329 | uid 330 | 392049EC-35AB-4C54-8A20-5565FBF67B32 331 | version 332 | 2 333 | 334 | 335 | config 336 | 337 | lastpathcomponent 338 | 339 | onlyshowifquerypopulated 340 | 341 | removeextension 342 | 343 | text 344 | {var:message} 345 | title 346 | TinyPNG 347 | 348 | type 349 | alfred.workflow.output.notification 350 | uid 351 | 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 352 | version 353 | 1 354 | 355 | 356 | config 357 | 358 | conditions 359 | 360 | 361 | inputstring 362 | {var:notify} 363 | matchcasesensitive 364 | 365 | matchmode 366 | 0 367 | matchstring 368 | false 369 | outputlabel 370 | Do not notify 371 | uid 372 | 3052F81B-0ECE-4815-AFAE-DCDD42361205 373 | 374 | 375 | elselabel 376 | Notify 377 | hideelse 378 | 379 | 380 | type 381 | alfred.workflow.utility.conditional 382 | uid 383 | 9EDA38AD-8C38-42CA-A270-CFE7AEC0655C 384 | version 385 | 1 386 | 387 | 388 | config 389 | 390 | soundname 391 | Glass 392 | systemsound 393 | 394 | 395 | type 396 | alfred.workflow.output.playsound 397 | uid 398 | 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 399 | version 400 | 1 401 | 402 | 403 | config 404 | 405 | availableviaurlhandler 406 | 407 | triggerid 408 | compress 409 | 410 | type 411 | alfred.workflow.trigger.external 412 | uid 413 | FD60CC76-3DD5-45D7-A184-5A5580E0790F 414 | version 415 | 1 416 | 417 | 418 | config 419 | 420 | conditions 421 | 422 | 423 | inputstring 424 | {var:success} 425 | matchcasesensitive 426 | 427 | matchmode 428 | 5 429 | matchstring 430 | 431 | outputlabel 432 | Success 433 | uid 434 | 2402FAA7-E693-486D-84EA-BF27BF8E4AFD 435 | 436 | 437 | elselabel 438 | Error 439 | hideelse 440 | 441 | 442 | type 443 | alfred.workflow.utility.conditional 444 | uid 445 | C22E0CBD-0683-4E3A-80E5-6532D8E5440E 446 | version 447 | 1 448 | 449 | 450 | config 451 | 452 | availableviaurlhandler 453 | 454 | triggerid 455 | silent_compress 456 | 457 | type 458 | alfred.workflow.trigger.external 459 | uid 460 | CB42BCC1-C05C-4B82-821E-BF371D852F7A 461 | version 462 | 1 463 | 464 | 465 | config 466 | 467 | soundname 468 | Basso 469 | systemsound 470 | 471 | 472 | type 473 | alfred.workflow.output.playsound 474 | uid 475 | 6D56D157-3EBC-41F6-A030-1C9A9E4490DF 476 | version 477 | 1 478 | 479 | 480 | config 481 | 482 | argument 483 | {query} 484 | passthroughargument 485 | 486 | variables 487 | 488 | notify 489 | false 490 | 491 | 492 | type 493 | alfred.workflow.utility.argument 494 | uid 495 | 8F44CFA0-9821-4998-B57A-CBD196BD069B 496 | version 497 | 1 498 | 499 | 500 | readme 501 | ## Usage 502 | 503 | Compress PNG, JPEG, and WebP images with [TinyPNG](https://tinypng.com/) via the [Universal Action](https://www.alfredapp.com/help/features/universal-actions/). 504 | 505 | ![Universal Action for TinyPNG Compression](images/about/ua.png) 506 | 507 | Alternatively, find images with the `tinypng` keyword. 508 | 509 | ![Alfred search for tinypng transparenc](images/about/tinypng.png) 510 | uidata 511 | 512 | 392049EC-35AB-4C54-8A20-5565FBF67B32 513 | 514 | xpos 515 | 35 516 | ypos 517 | 190 518 | 519 | 4D6432C7-2943-4DB6-A25F-B0AC57D3C6F2 520 | 521 | xpos 522 | 670 523 | ypos 524 | 320 525 | 526 | 6D56D157-3EBC-41F6-A030-1C9A9E4490DF 527 | 528 | xpos 529 | 670 530 | ypos 531 | 455 532 | 533 | 72DE7DEE-B771-41EA-9A7C-F10F4F7A5DC5 534 | 535 | xpos 536 | 670 537 | ypos 538 | 190 539 | 540 | 7EA1CA9C-97FC-4B89-999A-7CFE3D8CB0AE 541 | 542 | xpos 543 | 35 544 | ypos 545 | 40 546 | 547 | 8F44CFA0-9821-4998-B57A-CBD196BD069B 548 | 549 | xpos 550 | 195 551 | ypos 552 | 480 553 | 554 | 9EDA38AD-8C38-42CA-A270-CFE7AEC0655C 555 | 556 | xpos 557 | 400 558 | ypos 559 | 195 560 | 561 | C22E0CBD-0683-4E3A-80E5-6532D8E5440E 562 | 563 | xpos 564 | 550 565 | ypos 566 | 355 567 | 568 | CB42BCC1-C05C-4B82-821E-BF371D852F7A 569 | 570 | note 571 | Compress but do not show notification 572 | xpos 573 | 35 574 | ypos 575 | 450 576 | 577 | F2C7428D-06C2-4B70-8C70-8348AE71B137 578 | 579 | xpos 580 | 235 581 | ypos 582 | 40 583 | 584 | FD60CC76-3DD5-45D7-A184-5A5580E0790F 585 | 586 | xpos 587 | 35 588 | ypos 589 | 320 590 | 591 | 592 | userconfigurationconfig 593 | 594 | 595 | config 596 | 597 | default 598 | tinypng 599 | placeholder 600 | 601 | required 602 | 603 | trim 604 | 605 | 606 | description 607 | 608 | label 609 | Search Keyword 610 | type 611 | textfield 612 | variable 613 | search_keyword 614 | 615 | 616 | config 617 | 618 | default 619 | /tmp/com.alfredapp.vitor.tinypng.backups 620 | filtermode 621 | 1 622 | placeholder 623 | 624 | required 625 | 626 | 627 | description 628 | The default backup location is deleted when macOS restarts. 629 | label 630 | Backup Originals 631 | type 632 | filepicker 633 | variable 634 | backup_originals 635 | 636 | 637 | config 638 | 639 | default 640 | 641 | placeholder 642 | 643 | required 644 | 645 | trim 646 | 647 | 648 | description 649 | Request one at https://tinypng.com/developers 650 | label 651 | API Key 652 | type 653 | textfield 654 | variable 655 | api_key 656 | 657 | 658 | version 659 | 2024.2 660 | webaddress 661 | https://github.com/alfredapp/tinypng-workflow/ 662 | 663 | 664 | --------------------------------------------------------------------------------