├── .debug ├── .gitignore ├── .vscode └── tasks.json ├── CSXS └── manifest.xml ├── LICENSE ├── NOTES.md ├── README.md ├── SETUP.md ├── _builds ├── protoColors1.00.zxp └── protoColors1.01.zxp ├── assets ├── fillstroke.svg ├── fillstroke2.svg ├── fonts │ ├── protocolors.svg │ ├── protocolors.ttf │ └── protocolors.woff ├── iconLight.png ├── iconLightRollover.png └── icons │ ├── arrow.svg │ ├── cancel.svg │ ├── cursor.svg │ ├── doublearrow.svg │ ├── dropper.svg │ ├── find.svg │ ├── minus.svg │ └── plus.svg ├── client ├── dead.css ├── dead.js ├── index.html ├── libs │ ├── CSInterface.js │ ├── CSInterface9.0.js │ ├── events.js │ ├── menus.js │ ├── preStyle.css │ ├── reference.js │ ├── reset.css │ └── v-outside-events.min.js ├── main.js └── style.css ├── host ├── AEFT │ ├── host.jsx │ ├── host.ts │ └── tsconfig.json ├── ILST │ ├── host.jsx │ ├── host.ts │ └── tsconfig.json ├── PHXS │ ├── host.jsx │ ├── host.ts │ └── tsconfig.json └── universal │ ├── Console.jsx │ └── json2.jsx ├── package-lock.json ├── package.json ├── sandbox ├── fillstroke.ai ├── font.ai ├── mock.ai └── spectrum.ai ├── todo.md └── tsconfig.json /.debug: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "run for Illustrator", 6 | "type": "shell", 7 | "windows": { 8 | "options": { 9 | "shell": { 10 | "executable": "cmd.exe" 11 | } 12 | } 13 | }, 14 | "command": "'C:\\Program Files\\Adobe\\Adobe Illustrator CC 2019\\Support Files\\Contents\\Windows\\illustrator.exe' -r ${workspaceFolder}\\host\\ILST\\host.ts", 15 | "group": "test", 16 | "presentation": { 17 | "reveal": "always", 18 | "panel": "new" 19 | } 20 | }, 21 | { 22 | "type": "typescript", 23 | "tsconfig": "host\\PHXS\\tsconfig.json", 24 | "option": "watch", 25 | "problemMatcher": [ 26 | "$tsc-watch" 27 | ] 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /CSXS/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ./client/index.html 24 | 25 | 26 | 27 | true 28 | 29 | 30 | Panel 31 | protoColors 32 | 33 | 34 | 200 35 | 50 36 | 37 | 38 | 400 39 | 50 40 | 41 | 42 | 100 43 | 50 44 | 45 | 46 | 47 | ./assets/iconLight.png 48 | ./assets/iconLightRollover.png 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tom Scharstein 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 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | ## requests: 2 | 3 | * Variable swatch height 4 | * ~~Verify mac command modifier key works (mask as Ctrl on root.parseModifiers)~~ 5 | * ~~Persistent across sessions [toggle]~~ 6 | 7 | ## to-do 8 | 9 | * TextFrames do not get selected on ctrl+click 10 | * Swatches have no contrast mechanic if same as background of panel. 11 | * Trace Paper -- replaces colorHistory "Highlight". Generate layer above current artwork, replicate paths and fills/strokes, place solid white w/ artboard dimensions and lowered opacity beneath. Delete layer when not hovering. 12 | * ~~Use computed properties as modifiers for isolated Ctrl, Shift, Alt, Ctrl+Shift, Ctrl+Alt, etc.~~ 13 | * ~~Rework swatchList style to support infinite height~~ 14 | * ~~Add CMYK backdoor if document color type~~ 15 | * ~~Load config of context menu settings on mounted()~~ 16 | * ~~Context menu toggle for Sort By breaks easily~~ 17 | * ~~Support textFrame scanning~~ 18 | * ~~Delete/snip swatch~~ 19 | * ~~MagicMirror UI background color~~ 20 | * ~~Alt + Swatchclick: Delete / Replace~~ 21 | * ~~No interruptions or problems on document change~~ 22 | * ~~Fix swatchList if no colors preset~~ 23 | * ~~Fix swatch.key inaccuracies on addNewSwatch~~ 24 | * ~~Reverse~~ 25 | * ~~Sort by spectrum~~ 26 | * ~~Graveyard all unused components~~ 27 | * ~~Selection change timer and visualizer~~ 28 | * ~~Fill/Stroke change timer and visualizer~~ 29 | * ~~All colors in selection (common)~~ 30 | * ~~Tabs -- Timer / Spectrum~~ 31 | * ~~Swatches should support icons and outlines on hover~~ 32 | * ~~Delete swatch needs SVG cancel icon~~ 33 | * ~~Mod key visualizers -- select multiple swatches and find/replace~~ 34 | * ~~All colors in document scan (rare)~~ 35 | * ~~SwatchList -- Colors in document/artboard~~ 36 | * ~~SwatchList -- All recent colors~~ 37 | * ~~Shift + Swatchclick: Add swatch to selected~~ 38 | * ~~Control + Swatchclick: Select items with this color~~ 39 | * ~~Component swatchList and swatch -- compute time/spectrum arrays from masterswatches~~ 40 | 41 | 42 | ## schematic 43 | 44 | ```bash 45 | # component schematic 46 | app > 47 | Header > 48 | SortBy > 49 | > Recent [SVG] 50 | > Spectrum [SVG] 51 | InSelection > 52 | > Colors [CSS GRID] 53 | Visualizers > 54 | > Fill / Stroke [SVG] 55 | > Modifier Keys [GRID] 56 | > Scanning On/Off [SVG] 57 | Body > 58 | SwatchList > 59 | > Nav arrows 60 | swatches in Current [GRID] > 61 | > Handle with icon or icon centered inside 62 | SwatchList > 63 | swatches in Document (unless layer selected) 64 | > Handle with icon or icon centered inside 65 | Footer > 66 | > Info 67 | TestToolbar > 68 | > TestBtn 69 | 70 | # icons 71 | Swatch > 72 | > default: apply as active 73 | > shift: plus + 74 | > control: select/cursor 75 | > alt: minus x 76 | > replace 77 | > find 78 | ``` 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protoColors 2 | 3 | Dynamic recent color history for Illustrator and Photoshop because I've never liked Swatches. 4 | 5 | ![](https://thumbs.gfycat.com/ImpossibleSeparateDassierat-size_restricted.gif) 6 | 7 | ![](https://thumbs.gfycat.com/PertinentMediumFrillneckedlizard-size_restricted.gif) 8 | 9 | >:heavy_exclamation_mark: **Support for After Effects has been dropped, use [Color Claw](https://github.com/Inventsable/Color-Claw) instead.** 10 | 11 | * Auto-detects if active Fill/Stroke or Foreground/Background 12 | * (AI) Auto-collects all colors in current document on reset or non-persistent launch 13 | * (AI) Contextual Select Same Fill or Stroke while holding `cmd/ctrl` 14 | * Unlimited colors 15 | * (Optional) Persistent between sessions 16 | * Sort by Time or Spectrum 17 | * Reskins itself to match any app theme 18 | 19 | --- 20 | 21 | ## Install 22 | 23 | Use [ZXPInstaller](https://zxpinstaller.com/) (or any alternative) with the [latest ZXP build here](https://github.com/Inventsable/protoLayers/blob/master/_builds/protoColors1.01.zxp). 24 | 25 | ``` bash 26 | # Or CEP dev: 27 | # .../AppData/Roaming/Adobe/CEP/extensions 28 | git clone https://github.com/Inventsable/protoLayers.git 29 | ``` -------------------------------------------------------------------------------- /SETUP.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | # Init node and get Adobe types 3 | npm init -y 4 | npm install pravdomil/types-for-adobe 5 | 6 | # Ctrl+Shift+B to Run Task: 7 | tsc:watch - host/tsconfig.json 8 | ``` -------------------------------------------------------------------------------- /_builds/protoColors1.00.zxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/_builds/protoColors1.00.zxp -------------------------------------------------------------------------------- /_builds/protoColors1.01.zxp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/_builds/protoColors1.01.zxp -------------------------------------------------------------------------------- /assets/fillstroke.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /assets/fillstroke2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38 | 39 | fillstroke2 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /assets/fonts/protocolors.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /assets/fonts/protocolors.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/assets/fonts/protocolors.ttf -------------------------------------------------------------------------------- /assets/fonts/protocolors.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/assets/fonts/protocolors.woff -------------------------------------------------------------------------------- /assets/iconLight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/assets/iconLight.png -------------------------------------------------------------------------------- /assets/iconLightRollover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/assets/iconLightRollover.png -------------------------------------------------------------------------------- /assets/icons/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | arrow 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | cancel 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/cursor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | cursor 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/doublearrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | doublearrow 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /assets/icons/dropper.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | dropper 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/find.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | find 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | minus 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/icons/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | plus 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /client/dead.css: -------------------------------------------------------------------------------- 1 | .headerSortBy { 2 | display: grid; 3 | grid-template-columns: 1fr 1fr; 4 | grid-column-gap: .25rem; 5 | } 6 | 7 | [class^="sortBy"] { 8 | box-sizing: border-box; 9 | /* height: 2rem; */ 10 | /* border: 1.35px solid var(--color-ui-border); */ 11 | cursor: pointer; 12 | } 13 | /* [class^="sortBy"]:hover { 14 | background-color: var(--color-ui-hover); 15 | } */ 16 | 17 | .sortBy-Recent-Idle, .sortBy-Spectrum-Idle { 18 | background-color: var(--color-ui-idle); 19 | } 20 | 21 | .sortBy-Recent-Active, .sortBy-Spectrum-Active { 22 | background-color: var(--color-ui-active); 23 | } 24 | 25 | /* [class^="header"] { 26 | margin-bottom: .25rem; 27 | } */ 28 | 29 | 30 | /* .visualizerScanning { 31 | display: grid; 32 | grid-template-columns: 1fr; 33 | box-sizing: border-box; 34 | cursor: pointer; 35 | } 36 | .visualizerScanning-Idle { 37 | background-color: var(--color-ui-idle); 38 | } 39 | .visualizerScanning-Active { 40 | background-color: var(--color-ui-active); 41 | } */ 42 | /* .visualizersL { 43 | display: grid; 44 | grid-template-columns: 4fr 1fr; 45 | grid-row-gap: .25rem; 46 | } */ 47 | 48 | 49 | .bodyHandle { 50 | box-sizing: border-box; 51 | height: 1rem; 52 | width: 100%; 53 | border: 2px solid var(--color-ui-border); 54 | display: flex; 55 | justify-content: center; 56 | align-items: center; 57 | cursor: ns-resize; 58 | } 59 | .bodyHandle:hover { 60 | background-color: var(--color-ui-hover); 61 | } 62 | 63 | .bodyHandleDiv { 64 | border: 1.35px solid var(--color-ui-border); 65 | height: 0px; 66 | width: 80%; 67 | } 68 | 69 | /* .swatchPrefix-Add { 70 | background-color: var(--color-G); 71 | } 72 | .swatchPrefix-Select { 73 | background-color: var(--color-B); 74 | } 75 | .swatchPrefix-Minus { 76 | background-color: var(--color-R); 77 | } 78 | .swatchPrefix-Multi { 79 | background-color: var(--color-ui-active); 80 | } */ 81 | 82 | .font-icon {border: 1px solid red;} 83 | 84 | .footerMain { 85 | display: flex; 86 | /* grid-template-rows: 1fr 1fr; */ 87 | flex-direction: column; 88 | /* flex-wrap: wrap; */ 89 | justify-content: flex-end; 90 | /* align-items: flex-end; */ 91 | /* border: 1px solid red; */ 92 | } 93 | .footerInfo { 94 | width: 100%; 95 | height: 1rem; 96 | border: 1px solid green; 97 | /* height: 1rem; */ 98 | } 99 | 100 | .testToolbar { 101 | width: 100%; 102 | display: grid; 103 | border: 1px solid green; 104 | grid-template-columns: 1fr 1fr; 105 | } 106 | 107 | .testToolbarBtn { 108 | border: 1px solid blue; 109 | height: .5rem; 110 | } 111 | -------------------------------------------------------------------------------- /client/dead.js: -------------------------------------------------------------------------------- 1 | 2 | // Vue.component('sort-by', { 3 | // template: ` 4 | //
5 | //
6 | //
7 | //
8 | // `, 9 | // data() { 10 | // return { 11 | // isDefault: true, 12 | // } 13 | // }, 14 | // computed: { 15 | // isRecent: function(){return (this.isDefault) ? true : false}, 16 | // isSpectrum: function(){return !this.isRecent}, 17 | // }, 18 | // methods: { 19 | // toggleDef(state) { 20 | // if (state !== this.isDefault) 21 | // this.isDefault = !this.isDefault; 22 | // }, 23 | // sortByClass(name) { 24 | // var style = 'sortBy-' + name + '-'; 25 | // if (((this.isDefault) && (name == 'Recent')) 26 | // || ((!this.isDefault) && (name == 'Spectrum'))) { 27 | // style += 'Active' 28 | // } else { 29 | // style += 'Idle' 30 | // } 31 | // return style; 32 | // }, 33 | // } 34 | // }) 35 | 36 | // DEPRECATED 37 | Vue.component('handle', { 38 | props: ['enabled'], 39 | template: ` 40 |
46 |
47 |
48 | `, 49 | data() { 50 | return { 51 | canHandle: false, 52 | canDrag: false, 53 | isDragging: false, 54 | startY: 0, 55 | startH: 0, 56 | endH: 0, 57 | } 58 | }, 59 | methods: { 60 | onMouseOutside(evt, el) { 61 | if ((this.canDrag) && (this.isDragging) && (this.canHandle)) { 62 | // Needs subtraction logic 63 | var res = (this.startY - evt.clientY) * -1; 64 | console.log(res) 65 | var body = el.parentNode.children[0]; 66 | var style = this.$root.getCSS('swatchList-height'); 67 | var newDim = this.startH + res; 68 | if (((res > 0) && (newDim < 240)) || ((res < 0) && (newDim > this.startY))) { 69 | console.log(`${this.startY} - ${evt.clientY} = ${body.clientHeight} + ${res} = ${newDim}, css: ${style}`); 70 | this.$root.setCSS('swatchList-height', newDim + 'px') 71 | this.endH = newDim; 72 | } 73 | } 74 | }, 75 | startDrag(evt) { 76 | if (!this.isDragging) 77 | this.isDragging = true; 78 | if (this.isDragging) 79 | this.startY = evt.clientY; 80 | console.log(`Starting at ${this.startY}`); 81 | }, 82 | endDrag(evt, opt) { 83 | // console.log('Ending drag'); 84 | this.isDragging = false; 85 | // console.log(`${this.startH} : ${this.endH}`); 86 | this.startH = this.endH; 87 | }, 88 | getHeight() { 89 | var swatchList = document.getElementById('bodySwatchList'); 90 | this.startH = swatchList.clientHeight; 91 | }, 92 | }, 93 | mounted() { 94 | var self = this; 95 | Event.$on('endDragEvt', self.endDrag) 96 | console.log(this.canHandle); 97 | var swatchList = document.getElementById('bodySwatchList'); 98 | if (this.canHandle) { 99 | this.$root.setCSS('swatchList-height', swatchList.clientHeight + 4 + 'px') 100 | this.getHeight(); 101 | } 102 | } 103 | }) 104 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | protoColors 12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /client/libs/CSInterface.js: -------------------------------------------------------------------------------- 1 | /************************************************************************************************** 2 | * 3 | * ADOBE SYSTEMS INCORPORATED 4 | * Copyright 2013 Adobe Systems Incorporated 5 | * All Rights Reserved. 6 | * 7 | * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the 8 | * terms of the Adobe license agreement accompanying it. If you have received this file from a 9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior 10 | * written permission of Adobe. 11 | * 12 | **************************************************************************************************/ 13 | 14 | /** CSInterface - v6.1.0 */ 15 | 16 | /** 17 | * Stores constants for the window types supported by the CSXS infrastructure. 18 | */ 19 | function CSXSWindowType() { 20 | } 21 | 22 | /** Constant for the CSXS window type Panel. */ 23 | CSXSWindowType._PANEL = "Panel"; 24 | 25 | /** Constant for the CSXS window type Modeless. */ 26 | CSXSWindowType._MODELESS = "Modeless"; 27 | 28 | /** Constant for the CSXS window type ModalDialog. */ 29 | CSXSWindowType._MODAL_DIALOG = "ModalDialog"; 30 | 31 | /** EvalScript error message */ 32 | EvalScript_ErrMessage = "EvalScript error."; 33 | 34 | /** 35 | * @class Version 36 | * Defines a version number with major, minor, micro, and special 37 | * components. The major, minor and micro values are numeric; the special 38 | * value can be any string. 39 | * 40 | * @param major The major version component, a positive integer up to nine digits long. 41 | * @param minor The minor version component, a positive integer up to nine digits long. 42 | * @param micro The micro version component, a positive integer up to nine digits long. 43 | * @param special The special version component, an arbitrary string. 44 | * 45 | * @return A new \c Version object. 46 | */ 47 | function Version(major, minor, micro, special) { 48 | this.major = major; 49 | this.minor = minor; 50 | this.micro = micro; 51 | this.special = special; 52 | } 53 | 54 | /** 55 | * The maximum value allowed for a numeric version component. 56 | * This reflects the maximum value allowed in PlugPlug and the manifest schema. 57 | */ 58 | Version.MAX_NUM = 999999999; 59 | 60 | /** 61 | * @class VersionBound 62 | * Defines a boundary for a version range, which associates a \c Version object 63 | * with a flag for whether it is an inclusive or exclusive boundary. 64 | * 65 | * @param version The \c #Version object. 66 | * @param inclusive True if this boundary is inclusive, false if it is exclusive. 67 | * 68 | * @return A new \c VersionBound object. 69 | */ 70 | function VersionBound(version, inclusive) { 71 | this.version = version; 72 | this.inclusive = inclusive; 73 | } 74 | 75 | /** 76 | * @class VersionRange 77 | * Defines a range of versions using a lower boundary and optional upper boundary. 78 | * 79 | * @param lowerBound The \c #VersionBound object. 80 | * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. 81 | * 82 | * @return A new \c VersionRange object. 83 | */ 84 | function VersionRange(lowerBound, upperBound) { 85 | this.lowerBound = lowerBound; 86 | this.upperBound = upperBound; 87 | } 88 | 89 | /** 90 | * @class Runtime 91 | * Represents a runtime related to the CEP infrastructure. 92 | * Extensions can declare dependencies on particular 93 | * CEP runtime versions in the extension manifest. 94 | * 95 | * @param name The runtime name. 96 | * @param version A \c #VersionRange object that defines a range of valid versions. 97 | * 98 | * @return A new \c Runtime object. 99 | */ 100 | function Runtime(name, versionRange) { 101 | this.name = name; 102 | this.versionRange = versionRange; 103 | } 104 | 105 | /** 106 | * @class Extension 107 | * Encapsulates a CEP-based extension to an Adobe application. 108 | * 109 | * @param id The unique identifier of this extension. 110 | * @param name The localizable display name of this extension. 111 | * @param mainPath The path of the "index.html" file. 112 | * @param basePath The base path of this extension. 113 | * @param windowType The window type of the main window of this extension. 114 | Valid values are defined by \c #CSXSWindowType. 115 | * @param width The default width in pixels of the main window of this extension. 116 | * @param height The default height in pixels of the main window of this extension. 117 | * @param minWidth The minimum width in pixels of the main window of this extension. 118 | * @param minHeight The minimum height in pixels of the main window of this extension. 119 | * @param maxWidth The maximum width in pixels of the main window of this extension. 120 | * @param maxHeight The maximum height in pixels of the main window of this extension. 121 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. 122 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. 123 | * @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. 124 | * @param isAutoVisible True if this extension is visible on loading. 125 | * @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. 126 | * 127 | * @return A new \c Extension object. 128 | */ 129 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, 130 | defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) { 131 | this.id = id; 132 | this.name = name; 133 | this.mainPath = mainPath; 134 | this.basePath = basePath; 135 | this.windowType = windowType; 136 | this.width = width; 137 | this.height = height; 138 | this.minWidth = minWidth; 139 | this.minHeight = minHeight; 140 | this.maxWidth = maxWidth; 141 | this.maxHeight = maxHeight; 142 | this.defaultExtensionDataXml = defaultExtensionDataXml; 143 | this.specialExtensionDataXml = specialExtensionDataXml; 144 | this.requiredRuntimeList = requiredRuntimeList; 145 | this.isAutoVisible = isAutoVisible; 146 | this.isPluginExtension = isPluginExtension; 147 | } 148 | 149 | /** 150 | * @class CSEvent 151 | * A standard JavaScript event, the base class for CEP events. 152 | * 153 | * @param type The name of the event type. 154 | * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". 155 | * @param appId The unique identifier of the application that generated the event. 156 | * @param extensionId The unique identifier of the extension that generated the event. 157 | * 158 | * @return A new \c CSEvent object 159 | */ 160 | function CSEvent(type, scope, appId, extensionId) { 161 | this.type = type; 162 | this.scope = scope; 163 | this.appId = appId; 164 | this.extensionId = extensionId; 165 | } 166 | 167 | /** Event-specific data. */ 168 | CSEvent.prototype.data = ""; 169 | 170 | /** 171 | * @class SystemPath 172 | * Stores operating-system-specific location constants for use in the 173 | * \c #CSInterface.getSystemPath() method. 174 | * @return A new \c SystemPath object. 175 | */ 176 | function SystemPath() { 177 | } 178 | 179 | /** The path to user data. */ 180 | SystemPath.USER_DATA = "userData"; 181 | 182 | /** The path to common files for Adobe applications. */ 183 | SystemPath.COMMON_FILES = "commonFiles"; 184 | 185 | /** The path to the user's default document folder. */ 186 | SystemPath.MY_DOCUMENTS = "myDocuments"; 187 | 188 | /** @deprecated. Use \c #SystemPath.Extension. */ 189 | SystemPath.APPLICATION = "application"; 190 | 191 | /** The path to current extension. */ 192 | SystemPath.EXTENSION = "extension"; 193 | 194 | /** The path to hosting application's executable. */ 195 | SystemPath.HOST_APPLICATION = "hostApplication"; 196 | 197 | /** 198 | * @class ColorType 199 | * Stores color-type constants. 200 | */ 201 | function ColorType() { 202 | } 203 | 204 | /** RGB color type. */ 205 | ColorType.RGB = "rgb"; 206 | 207 | /** Gradient color type. */ 208 | ColorType.GRADIENT = "gradient"; 209 | 210 | /** Null color type. */ 211 | ColorType.NONE = "none"; 212 | 213 | /** 214 | * @class RGBColor 215 | * Stores an RGB color with red, green, blue, and alpha values. 216 | * All values are in the range [0.0 to 255.0]. Invalid numeric values are 217 | * converted to numbers within this range. 218 | * 219 | * @param red The red value, in the range [0.0 to 255.0]. 220 | * @param green The green value, in the range [0.0 to 255.0]. 221 | * @param blue The blue value, in the range [0.0 to 255.0]. 222 | * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. 223 | * The default, 255.0, means that the color is fully opaque. 224 | * 225 | * @return A new RGBColor object. 226 | */ 227 | function RGBColor(red, green, blue, alpha) { 228 | this.red = red; 229 | this.green = green; 230 | this.blue = blue; 231 | this.alpha = alpha; 232 | } 233 | 234 | /** 235 | * @class Direction 236 | * A point value in which the y component is 0 and the x component 237 | * is positive or negative for a right or left direction, 238 | * or the x component is 0 and the y component is positive or negative for 239 | * an up or down direction. 240 | * 241 | * @param x The horizontal component of the point. 242 | * @param y The vertical component of the point. 243 | * 244 | * @return A new \c Direction object. 245 | */ 246 | function Direction(x, y) { 247 | this.x = x; 248 | this.y = y; 249 | } 250 | 251 | /** 252 | * @class GradientStop 253 | * Stores gradient stop information. 254 | * 255 | * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. 256 | * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. 257 | * 258 | * @return GradientStop object. 259 | */ 260 | function GradientStop(offset, rgbColor) { 261 | this.offset = offset; 262 | this.rgbColor = rgbColor; 263 | } 264 | 265 | /** 266 | * @class GradientColor 267 | * Stores gradient color information. 268 | * 269 | * @param type The gradient type, must be "linear". 270 | * @param direction A \c #Direction object for the direction of the gradient 271 | (up, down, right, or left). 272 | * @param numStops The number of stops in the gradient. 273 | * @param gradientStopList An array of \c #GradientStop objects. 274 | * 275 | * @return A new \c GradientColor object. 276 | */ 277 | function GradientColor(type, direction, numStops, arrGradientStop) { 278 | this.type = type; 279 | this.direction = direction; 280 | this.numStops = numStops; 281 | this.arrGradientStop = arrGradientStop; 282 | } 283 | 284 | /** 285 | * @class UIColor 286 | * Stores color information, including the type, anti-alias level, and specific color 287 | * values in a color object of an appropriate type. 288 | * 289 | * @param type The color type, 1 for "rgb" and 2 for "gradient". 290 | The supplied color object must correspond to this type. 291 | * @param antialiasLevel The anti-alias level constant. 292 | * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. 293 | * 294 | * @return A new \c UIColor object. 295 | */ 296 | function UIColor(type, antialiasLevel, color) { 297 | this.type = type; 298 | this.antialiasLevel = antialiasLevel; 299 | this.color = color; 300 | } 301 | 302 | /** 303 | * @class AppSkinInfo 304 | * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. 305 | * 306 | * @param baseFontFamily The base font family of the application. 307 | * @param baseFontSize The base font size of the application. 308 | * @param appBarBackgroundColor The application bar background color. 309 | * @param panelBackgroundColor The background color of the extension panel. 310 | * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. 311 | * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. 312 | * @param systemHighlightColor The operating-system highlight color, as sRGB. 313 | * 314 | * @return AppSkinInfo object. 315 | */ 316 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) { 317 | this.baseFontFamily = baseFontFamily; 318 | this.baseFontSize = baseFontSize; 319 | this.appBarBackgroundColor = appBarBackgroundColor; 320 | this.panelBackgroundColor = panelBackgroundColor; 321 | this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; 322 | this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; 323 | this.systemHighlightColor = systemHighlightColor; 324 | } 325 | 326 | /** 327 | * @class HostEnvironment 328 | * Stores information about the environment in which the extension is loaded. 329 | * 330 | * @param appName The application's name. 331 | * @param appVersion The application's version. 332 | * @param appLocale The application's current license locale. 333 | * @param appUILocale The application's current UI locale. 334 | * @param appId The application's unique identifier. 335 | * @param isAppOnline True if the application is currently online. 336 | * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. 337 | * 338 | * @return A new \c HostEnvironment object. 339 | */ 340 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) { 341 | this.appName = appName; 342 | this.appVersion = appVersion; 343 | this.appLocale = appLocale; 344 | this.appUILocale = appUILocale; 345 | this.appId = appId; 346 | this.isAppOnline = isAppOnline; 347 | this.appSkinInfo = appSkinInfo; 348 | } 349 | 350 | /** 351 | * @class HostCapabilities 352 | * Stores information about the host capabilities. 353 | * 354 | * @param EXTENDED_PANEL_MENU True if the application supports panel menu. 355 | * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. 356 | * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. 357 | * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. 358 | * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. 359 | * 360 | * @return A new \c HostCapabilities object. 361 | */ 362 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) { 363 | this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; 364 | this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; 365 | this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; 366 | this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; 367 | this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 368 | } 369 | 370 | /** 371 | * @class ApiVersion 372 | * Stores current api version. 373 | * 374 | * Since 4.2.0 375 | * 376 | * @param major The major version 377 | * @param minor The minor version. 378 | * @param micro The micro version. 379 | * 380 | * @return ApiVersion object. 381 | */ 382 | function ApiVersion(major, minor, micro) { 383 | this.major = major; 384 | this.minor = minor; 385 | this.micro = micro; 386 | } 387 | 388 | /** 389 | * @class MenuItemStatus 390 | * Stores flyout menu item status 391 | * 392 | * Since 5.2.0 393 | * 394 | * @param menuItemLabel The menu item label. 395 | * @param enabled True if user wants to enable the menu item. 396 | * @param checked True if user wants to check the menu item. 397 | * 398 | * @return MenuItemStatus object. 399 | */ 400 | function MenuItemStatus(menuItemLabel, enabled, checked) { 401 | this.menuItemLabel = menuItemLabel; 402 | this.enabled = enabled; 403 | this.checked = checked; 404 | } 405 | 406 | /** 407 | * @class ContextMenuItemStatus 408 | * Stores the status of the context menu item. 409 | * 410 | * Since 5.2.0 411 | * 412 | * @param menuItemID The menu item id. 413 | * @param enabled True if user wants to enable the menu item. 414 | * @param checked True if user wants to check the menu item. 415 | * 416 | * @return MenuItemStatus object. 417 | */ 418 | function ContextMenuItemStatus(menuItemID, enabled, checked) { 419 | this.menuItemID = menuItemID; 420 | this.enabled = enabled; 421 | this.checked = checked; 422 | } 423 | //------------------------------ CSInterface ---------------------------------- 424 | 425 | /** 426 | * @class CSInterface 427 | * This is the entry point to the CEP extensibility infrastructure. 428 | * Instantiate this object and use it to: 429 | * 434 | * 435 | * @return A new \c CSInterface object 436 | */ 437 | function CSInterface() { 438 | } 439 | 440 | /** 441 | * User can add this event listener to handle native application theme color changes. 442 | * Callback function gives extensions ability to fine-tune their theme color after the 443 | * global theme color has been changed. 444 | * The callback function should be like below: 445 | * 446 | * @example 447 | * // event is a CSEvent object, but user can ignore it. 448 | * function OnAppThemeColorChanged(event) 449 | * { 450 | * // Should get a latest HostEnvironment object from application. 451 | * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 452 | * // Gets the style information such as color info from the skinInfo, 453 | * // and redraw all UI controls of your extension according to the style info. 454 | * } 455 | */ 456 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; 457 | 458 | /** The host environment data object. */ 459 | CSInterface.prototype.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 460 | 461 | /** Retrieves information about the host environment in which the 462 | * extension is currently running. 463 | * 464 | * @return A \c #HostEnvironment object. 465 | */ 466 | CSInterface.prototype.getHostEnvironment = function () { 467 | this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 468 | return this.hostEnvironment; 469 | }; 470 | 471 | /** Closes this extension. */ 472 | CSInterface.prototype.closeExtension = function () { 473 | window.__adobe_cep__.closeExtension(); 474 | }; 475 | 476 | /** 477 | * Retrieves a path for which a constant is defined in the system. 478 | * 479 | * @param pathType The path-type constant defined in \c #SystemPath , 480 | * 481 | * @return The platform-specific system path string. 482 | */ 483 | CSInterface.prototype.getSystemPath = function (pathType) { 484 | var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); 485 | var OSVersion = this.getOSInformation(); 486 | if (OSVersion.indexOf("Windows") >= 0) { 487 | path = path.replace("file:///", ""); 488 | } 489 | else if (OSVersion.indexOf("Mac") >= 0) { 490 | path = path.replace("file://", ""); 491 | } 492 | return path; 493 | }; 494 | 495 | /** 496 | * Evaluates a JavaScript script, which can use the JavaScript DOM 497 | * of the host application. 498 | * 499 | * @param script The JavaScript script. 500 | * @param callback Optional. A callback function that receives the result of execution. 501 | * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. 502 | */ 503 | CSInterface.prototype.evalScript = function (script, callback) { 504 | if (callback === null || callback === undefined) { 505 | callback = function (result) { }; 506 | } 507 | window.__adobe_cep__.evalScript(script, callback); 508 | }; 509 | 510 | /** 511 | * Retrieves the unique identifier of the application. 512 | * in which the extension is currently running. 513 | * 514 | * @return The unique ID string. 515 | */ 516 | CSInterface.prototype.getApplicationID = function () { 517 | var appId = this.hostEnvironment.appId; 518 | return appId; 519 | }; 520 | 521 | /** 522 | * Retrieves host capability information for the application 523 | * in which the extension is currently running. 524 | * 525 | * @return A \c #HostCapabilities object. 526 | */ 527 | CSInterface.prototype.getHostCapabilities = function () { 528 | var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities()); 529 | return hostCapabilities; 530 | }; 531 | 532 | /** 533 | * Triggers a CEP event programmatically. Yoy can use it to dispatch 534 | * an event of a predefined type, or of a type you have defined. 535 | * 536 | * @param event A \c CSEvent object. 537 | */ 538 | CSInterface.prototype.dispatchEvent = function (event) { 539 | if (typeof event.data == "object") { 540 | event.data = JSON.stringify(event.data); 541 | } 542 | 543 | window.__adobe_cep__.dispatchEvent(event); 544 | }; 545 | 546 | /** 547 | * Registers an interest in a CEP event of a particular type, and 548 | * assigns an event handler. 549 | * The event infrastructure notifies your extension when events of this type occur, 550 | * passing the event object to the registered handler function. 551 | * 552 | * @param type The name of the event type of interest. 553 | * @param listener The JavaScript handler function or method. 554 | * @param obj Optional, the object containing the handler method, if any. 555 | * Default is null. 556 | */ 557 | CSInterface.prototype.addEventListener = function (type, listener, obj) { 558 | window.__adobe_cep__.addEventListener(type, listener, obj); 559 | }; 560 | 561 | /** 562 | * Removes a registered event listener. 563 | * 564 | * @param type The name of the event type of interest. 565 | * @param listener The JavaScript handler function or method that was registered. 566 | * @param obj Optional, the object containing the handler method, if any. 567 | * Default is null. 568 | */ 569 | CSInterface.prototype.removeEventListener = function (type, listener, obj) { 570 | window.__adobe_cep__.removeEventListener(type, listener, obj); 571 | }; 572 | 573 | /** 574 | * Loads and launches another extension, or activates the extension if it is already loaded. 575 | * 576 | * @param extensionId The extension's unique identifier. 577 | * @param startupParams Not currently used, pass "". 578 | * 579 | * @example 580 | * To launch the extension "help" with ID "HLP" from this extension, call: 581 | * requestOpenExtension("HLP", ""); 582 | * 583 | */ 584 | CSInterface.prototype.requestOpenExtension = function (extensionId, params) { 585 | window.__adobe_cep__.requestOpenExtension(extensionId, params); 586 | }; 587 | 588 | /** 589 | * Retrieves the list of extensions currently loaded in the current host application. 590 | * The extension list is initialized once, and remains the same during the lifetime 591 | * of the CEP session. 592 | * 593 | * @param extensionIds Optional, an array of unique identifiers for extensions of interest. 594 | * If omitted, retrieves data for all extensions. 595 | * 596 | * @return Zero or more \c #Extension objects. 597 | */ 598 | CSInterface.prototype.getExtensions = function (extensionIds) { 599 | var extensionIdsStr = JSON.stringify(extensionIds); 600 | var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); 601 | 602 | var extensions = JSON.parse(extensionsStr); 603 | return extensions; 604 | }; 605 | 606 | /** 607 | * Retrieves network-related preferences. 608 | * 609 | * @return A JavaScript object containing network preferences. 610 | */ 611 | CSInterface.prototype.getNetworkPreferences = function () { 612 | var result = window.__adobe_cep__.getNetworkPreferences(); 613 | var networkPre = JSON.parse(result); 614 | 615 | return networkPre; 616 | }; 617 | 618 | /** 619 | * Initializes the resource bundle for this extension with property values 620 | * for the current application and locale. 621 | * To support multiple locales, you must define a property file for each locale, 622 | * containing keyed display-string values for that locale. 623 | * See localization documentation for Extension Builder and related products. 624 | * 625 | * Keys can be in the 626 | * form key.value="localized string", for use in HTML text elements. 627 | * For example, in this input element, the localized \c key.value string is displayed 628 | * instead of the empty \c value string: 629 | * 630 | * 631 | * 632 | * @return An object containing the resource bundle information. 633 | */ 634 | CSInterface.prototype.initResourceBundle = function () { 635 | var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); 636 | var resElms = document.querySelectorAll('[data-locale]'); 637 | for (var n = 0; n < resElms.length; n++) { 638 | var resEl = resElms[n]; 639 | // Get the resource key from the element. 640 | var resKey = resEl.getAttribute('data-locale'); 641 | if (resKey) { 642 | // Get all the resources that start with the key. 643 | for (var key in resourceBundle) { 644 | if (key.indexOf(resKey) === 0) { 645 | var resValue = resourceBundle[key]; 646 | if (key.length == resKey.length) { 647 | resEl.innerHTML = resValue; 648 | } 649 | else if ('.' == key.charAt(resKey.length)) { 650 | var attrKey = key.substring(resKey.length + 1); 651 | resEl[attrKey] = resValue; 652 | } 653 | } 654 | } 655 | } 656 | } 657 | return resourceBundle; 658 | }; 659 | 660 | /** 661 | * Writes installation information to a file. 662 | * 663 | * @return The file path. 664 | */ 665 | CSInterface.prototype.dumpInstallationInfo = function () { 666 | return window.__adobe_cep__.dumpInstallationInfo(); 667 | }; 668 | 669 | /** 670 | * Retrieves version information for the current Operating System, 671 | * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. 672 | * 673 | * @return A string containing the OS version, or "unknown Operation System". 674 | * If user customizes the User Agent by setting CEF command parameter "--user-agent", only 675 | * "Mac OS X" or "Windows" will be returned. 676 | */ 677 | CSInterface.prototype.getOSInformation = function () { 678 | var userAgent = navigator.userAgent; 679 | 680 | if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) { 681 | var winVersion = "Windows"; 682 | var winBit = ""; 683 | if (userAgent.indexOf("Windows") > -1) { 684 | if (userAgent.indexOf("Windows NT 5.0") > -1) { 685 | winVersion = "Windows 2000"; 686 | } 687 | else if (userAgent.indexOf("Windows NT 5.1") > -1) { 688 | winVersion = "Windows XP"; 689 | } 690 | else if (userAgent.indexOf("Windows NT 5.2") > -1) { 691 | winVersion = "Windows Server 2003"; 692 | } 693 | else if (userAgent.indexOf("Windows NT 6.0") > -1) { 694 | winVersion = "Windows Vista"; 695 | } 696 | else if (userAgent.indexOf("Windows NT 6.1") > -1) { 697 | winVersion = "Windows 7"; 698 | } 699 | else if (userAgent.indexOf("Windows NT 6.2") > -1) { 700 | winVersion = "Windows 8"; 701 | } 702 | else if (userAgent.indexOf("Windows NT 6.3") > -1) { 703 | winVersion = "Windows 8.1"; 704 | } 705 | else if (userAgent.indexOf("Windows NT 10") > -1) { 706 | winVersion = "Windows 10"; 707 | } 708 | 709 | if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1) { 710 | winBit = " 64-bit"; 711 | } 712 | else { 713 | winBit = " 32-bit"; 714 | } 715 | } 716 | 717 | return winVersion + winBit; 718 | } 719 | else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) { 720 | var result = "Mac OS X"; 721 | 722 | if (userAgent.indexOf("Mac OS X") > -1) { 723 | result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")")); 724 | result = result.replace(/_/g, "."); 725 | } 726 | 727 | return result; 728 | } 729 | 730 | return "Unknown Operation System"; 731 | }; 732 | 733 | /** 734 | * Opens a page in the default system browser. 735 | * 736 | * Since 4.2.0 737 | * 738 | * @param url The URL of the page/file to open, or the email address. 739 | * Must use HTTP/HTTPS/file/mailto protocol. For example: 740 | * "http://www.adobe.com" 741 | * "https://github.com" 742 | * "file:///C:/log.txt" 743 | * "mailto:test@adobe.com" 744 | * 745 | * @return One of these error codes:\n 746 | * \n 752 | */ 753 | CSInterface.prototype.openURLInDefaultBrowser = function (url) { 754 | return cep.util.openURLInDefaultBrowser(url); 755 | }; 756 | 757 | /** 758 | * Retrieves extension ID. 759 | * 760 | * Since 4.2.0 761 | * 762 | * @return extension ID. 763 | */ 764 | CSInterface.prototype.getExtensionID = function () { 765 | return window.__adobe_cep__.getExtensionId(); 766 | }; 767 | 768 | /** 769 | * Retrieves the scale factor of screen. 770 | * On Windows platform, the value of scale factor might be different from operating system's scale factor, 771 | * since host application may use its self-defined scale factor. 772 | * 773 | * Since 4.2.0 774 | * 775 | * @return One of the following float number. 776 | * \n 781 | */ 782 | CSInterface.prototype.getScaleFactor = function () { 783 | return window.__adobe_cep__.getScaleFactor(); 784 | }; 785 | 786 | /** 787 | * Set a handler to detect any changes of scale factor. This only works on Mac. 788 | * 789 | * Since 4.2.0 790 | * 791 | * @param handler The function to be called when scale factor is changed. 792 | * 793 | */ 794 | CSInterface.prototype.setScaleFactorChangedHandler = function (handler) { 795 | window.__adobe_cep__.setScaleFactorChangedHandler(handler); 796 | }; 797 | 798 | /** 799 | * Retrieves current API version. 800 | * 801 | * Since 4.2.0 802 | * 803 | * @return ApiVersion object. 804 | * 805 | */ 806 | CSInterface.prototype.getCurrentApiVersion = function () { 807 | var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); 808 | return apiVersion; 809 | }; 810 | 811 | /** 812 | * Set panel flyout menu by an XML. 813 | * 814 | * Since 5.2.0 815 | * 816 | * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a 817 | * menu item is clicked. 818 | * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. 819 | * 820 | * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" 821 | * respectively to get notified when flyout menu is opened or closed. 822 | * 823 | * @param menu A XML string which describes menu structure. 824 | * An example menu XML: 825 | * 826 | * 827 | * 828 | * 829 | * 830 | * 831 | * 832 | * 833 | * 834 | * 835 | * 836 | * 837 | */ 838 | CSInterface.prototype.setPanelFlyoutMenu = function (menu) { 839 | if ("string" != typeof menu) { 840 | return; 841 | } 842 | 843 | window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); 844 | }; 845 | 846 | /** 847 | * Updates a menu item in the extension window's flyout menu, by setting the enabled 848 | * and selection status. 849 | * 850 | * Since 5.2.0 851 | * 852 | * @param menuItemLabel The menu item label. 853 | * @param enabled True to enable the item, false to disable it (gray it out). 854 | * @param checked True to select the item, false to deselect it. 855 | * 856 | * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). 857 | * Fails silently if menu label is invalid. 858 | * 859 | * @see HostCapabilities.EXTENDED_PANEL_MENU 860 | */ 861 | CSInterface.prototype.updatePanelMenuItem = function (menuItemLabel, enabled, checked) { 862 | var ret = false; 863 | if (this.getHostCapabilities().EXTENDED_PANEL_MENU) { 864 | var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); 865 | ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); 866 | } 867 | return ret; 868 | }; 869 | 870 | 871 | /** 872 | * Set context menu by XML string. 873 | * 874 | * Since 5.2.0 875 | * 876 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 877 | * - an item without menu ID or menu name is disabled and is not shown. 878 | * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 879 | * - Checkable attribute takes precedence over Checked attribute. 880 | * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. 881 | The Chrome extension contextMenus API was taken as a reference. 882 | https://developer.chrome.com/extensions/contextMenus 883 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 884 | * 885 | * @param menu A XML string which describes menu structure. 886 | * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. 887 | * 888 | * @description An example menu XML: 889 | * 890 | * 891 | * 892 | * 893 | * 894 | * 895 | * 896 | * 897 | * 898 | * 899 | * 900 | */ 901 | CSInterface.prototype.setContextMenu = function (menu, callback) { 902 | if ("string" != typeof menu) { 903 | return; 904 | } 905 | 906 | window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); 907 | }; 908 | 909 | /** 910 | * Set context menu by JSON string. 911 | * 912 | * Since 6.0.0 913 | * 914 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 915 | * - an item without menu ID or menu name is disabled and is not shown. 916 | * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 917 | * - Checkable attribute takes precedence over Checked attribute. 918 | * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. 919 | The Chrome extension contextMenus API was taken as a reference. 920 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 921 | https://developer.chrome.com/extensions/contextMenus 922 | * 923 | * @param menu A JSON string which describes menu structure. 924 | * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. 925 | * 926 | * @description An example menu JSON: 927 | * 928 | * { 929 | * "menu": [ 930 | * { 931 | * "id": "menuItemId1", 932 | * "label": "testExample1", 933 | * "enabled": true, 934 | * "checkable": true, 935 | * "checked": false, 936 | * "icon": "./image/small_16X16.png" 937 | * }, 938 | * { 939 | * "id": "menuItemId2", 940 | * "label": "testExample2", 941 | * "menu": [ 942 | * { 943 | * "id": "menuItemId2-1", 944 | * "label": "testExample2-1", 945 | * "menu": [ 946 | * { 947 | * "id": "menuItemId2-1-1", 948 | * "label": "testExample2-1-1", 949 | * "enabled": false, 950 | * "checkable": true, 951 | * "checked": true 952 | * } 953 | * ] 954 | * }, 955 | * { 956 | * "id": "menuItemId2-2", 957 | * "label": "testExample2-2", 958 | * "enabled": true, 959 | * "checkable": true, 960 | * "checked": true 961 | * } 962 | * ] 963 | * }, 964 | * { 965 | * "label": "---" 966 | * }, 967 | * { 968 | * "id": "menuItemId3", 969 | * "label": "testExample3", 970 | * "enabled": false, 971 | * "checkable": true, 972 | * "checked": false 973 | * } 974 | * ] 975 | * } 976 | * 977 | */ 978 | CSInterface.prototype.setContextMenuByJSON = function (menu, callback) { 979 | if ("string" != typeof menu) { 980 | return; 981 | } 982 | 983 | window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); 984 | }; 985 | 986 | /** 987 | * Updates a context menu item by setting the enabled and selection status. 988 | * 989 | * Since 5.2.0 990 | * 991 | * @param menuItemID The menu item ID. 992 | * @param enabled True to enable the item, false to disable it (gray it out). 993 | * @param checked True to select the item, false to deselect it. 994 | */ 995 | CSInterface.prototype.updateContextMenuItem = function (menuItemID, enabled, checked) { 996 | var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); 997 | ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); 998 | }; 999 | 1000 | /** 1001 | * Get the visibility status of an extension window. 1002 | * 1003 | * Since 6.0.0 1004 | * 1005 | * @return true if the extension window is visible; false if the extension window is hidden. 1006 | */ 1007 | CSInterface.prototype.isWindowVisible = function () { 1008 | return window.__adobe_cep__.invokeSync("isWindowVisible", ""); 1009 | }; 1010 | 1011 | /** 1012 | * Resize extension's content to the specified dimensions. 1013 | * 1. Works with modal and modeless extensions in all Adobe products. 1014 | * 2. Extension's manifest min/max size constraints apply and take precedence. 1015 | * 3. For panel extensions 1016 | * 3.1 This works in all Adobe products except: 1017 | * * Premiere Pro 1018 | * * Prelude 1019 | * * After Effects 1020 | * 3.2 When the panel is in certain states (especially when being docked), 1021 | * it will not change to the desired dimensions even when the 1022 | * specified size satisfies min/max constraints. 1023 | * 1024 | * Since 6.0.0 1025 | * 1026 | * @param width The new width 1027 | * @param height The new height 1028 | */ 1029 | CSInterface.prototype.resizeContent = function (width, height) { 1030 | window.__adobe_cep__.resizeContent(width, height); 1031 | }; 1032 | 1033 | /** 1034 | * Register the invalid certificate callback for an extension. 1035 | * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame. 1036 | * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown. 1037 | * 1038 | * Since 6.1.0 1039 | * 1040 | * @param callback the callback function 1041 | */ 1042 | CSInterface.prototype.registerInvalidCertificateCallback = function (callback) { 1043 | return window.__adobe_cep__.registerInvalidCertificateCallback(callback); 1044 | }; 1045 | 1046 | /** 1047 | * Register an interest in some key events to prevent them from being sent to the host application. 1048 | * 1049 | * This function works with modeless extensions and panel extensions. 1050 | * Generally all the key events will be sent to the host application for these two extensions if the current focused element 1051 | * is not text input or dropdown, 1052 | * If you want to intercept some key events and want them to be handled in the extension, please call this function 1053 | * in advance to prevent them being sent to the host application. 1054 | * 1055 | * Since 6.1.0 1056 | * 1057 | * @param keyEventsInterest A JSON string describing those key events you are interested in. A null object or 1058 | an empty string will lead to removing the interest 1059 | * 1060 | * This JSON string should be an array, each object has following keys: 1061 | * 1062 | * keyCode: [Required] represents an OS system dependent virtual key code identifying 1063 | * the unmodified value of the pressed key. 1064 | * ctrlKey: [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred. 1065 | * altKey: [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred. 1066 | * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred. 1067 | * metaKey: [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred. 1068 | * On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead. 1069 | * An example JSON string: 1070 | * 1071 | * [ 1072 | * { 1073 | * "keyCode": 48 1074 | * }, 1075 | * { 1076 | * "keyCode": 123, 1077 | * "ctrlKey": true 1078 | * }, 1079 | * { 1080 | * "keyCode": 123, 1081 | * "ctrlKey": true, 1082 | * "metaKey": true 1083 | * } 1084 | * ] 1085 | * 1086 | */ 1087 | CSInterface.prototype.registerKeyEventsInterest = function (keyEventsInterest) { 1088 | return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest); 1089 | }; 1090 | 1091 | /** 1092 | * Set the title of the extension window. 1093 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1094 | * 1095 | * Since 6.1.0 1096 | * 1097 | * @param title The window title. 1098 | */ 1099 | CSInterface.prototype.setWindowTitle = function (title) { 1100 | window.__adobe_cep__.invokeSync("setWindowTitle", title); 1101 | }; 1102 | 1103 | /** 1104 | * Get the title of the extension window. 1105 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1106 | * 1107 | * Since 6.1.0 1108 | * 1109 | * @return The window title. 1110 | */ 1111 | CSInterface.prototype.getWindowTitle = function () { 1112 | return window.__adobe_cep__.invokeSync("getWindowTitle", ""); 1113 | }; -------------------------------------------------------------------------------- /client/libs/CSInterface9.0.js: -------------------------------------------------------------------------------- 1 | /************************************************************************************************** 2 | * 3 | * ADOBE SYSTEMS INCORPORATED 4 | * Copyright 2013 Adobe Systems Incorporated 5 | * All Rights Reserved. 6 | * 7 | * NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the 8 | * terms of the Adobe license agreement accompanying it. If you have received this file from a 9 | * source other than Adobe, then your use, modification, or distribution of it requires the prior 10 | * written permission of Adobe. 11 | * 12 | **************************************************************************************************/ 13 | 14 | /** CSInterface - v9.2.0 */ 15 | 16 | /** 17 | * Stores constants for the window types supported by the CSXS infrastructure. 18 | */ 19 | function CSXSWindowType() { 20 | } 21 | 22 | /** Constant for the CSXS window type Panel. */ 23 | CSXSWindowType._PANEL = "Panel"; 24 | 25 | /** Constant for the CSXS window type Modeless. */ 26 | CSXSWindowType._MODELESS = "Modeless"; 27 | 28 | /** Constant for the CSXS window type ModalDialog. */ 29 | CSXSWindowType._MODAL_DIALOG = "ModalDialog"; 30 | 31 | /** EvalScript error message */ 32 | EvalScript_ErrMessage = "EvalScript error."; 33 | 34 | /** 35 | * @class Version 36 | * Defines a version number with major, minor, micro, and special 37 | * components. The major, minor and micro values are numeric; the special 38 | * value can be any string. 39 | * 40 | * @param major The major version component, a positive integer up to nine digits long. 41 | * @param minor The minor version component, a positive integer up to nine digits long. 42 | * @param micro The micro version component, a positive integer up to nine digits long. 43 | * @param special The special version component, an arbitrary string. 44 | * 45 | * @return A new \c Version object. 46 | */ 47 | function Version(major, minor, micro, special) { 48 | this.major = major; 49 | this.minor = minor; 50 | this.micro = micro; 51 | this.special = special; 52 | } 53 | 54 | /** 55 | * The maximum value allowed for a numeric version component. 56 | * This reflects the maximum value allowed in PlugPlug and the manifest schema. 57 | */ 58 | Version.MAX_NUM = 999999999; 59 | 60 | /** 61 | * @class VersionBound 62 | * Defines a boundary for a version range, which associates a \c Version object 63 | * with a flag for whether it is an inclusive or exclusive boundary. 64 | * 65 | * @param version The \c #Version object. 66 | * @param inclusive True if this boundary is inclusive, false if it is exclusive. 67 | * 68 | * @return A new \c VersionBound object. 69 | */ 70 | function VersionBound(version, inclusive) { 71 | this.version = version; 72 | this.inclusive = inclusive; 73 | } 74 | 75 | /** 76 | * @class VersionRange 77 | * Defines a range of versions using a lower boundary and optional upper boundary. 78 | * 79 | * @param lowerBound The \c #VersionBound object. 80 | * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. 81 | * 82 | * @return A new \c VersionRange object. 83 | */ 84 | function VersionRange(lowerBound, upperBound) { 85 | this.lowerBound = lowerBound; 86 | this.upperBound = upperBound; 87 | } 88 | 89 | /** 90 | * @class Runtime 91 | * Represents a runtime related to the CEP infrastructure. 92 | * Extensions can declare dependencies on particular 93 | * CEP runtime versions in the extension manifest. 94 | * 95 | * @param name The runtime name. 96 | * @param version A \c #VersionRange object that defines a range of valid versions. 97 | * 98 | * @return A new \c Runtime object. 99 | */ 100 | function Runtime(name, versionRange) { 101 | this.name = name; 102 | this.versionRange = versionRange; 103 | } 104 | 105 | /** 106 | * @class Extension 107 | * Encapsulates a CEP-based extension to an Adobe application. 108 | * 109 | * @param id The unique identifier of this extension. 110 | * @param name The localizable display name of this extension. 111 | * @param mainPath The path of the "index.html" file. 112 | * @param basePath The base path of this extension. 113 | * @param windowType The window type of the main window of this extension. 114 | Valid values are defined by \c #CSXSWindowType. 115 | * @param width The default width in pixels of the main window of this extension. 116 | * @param height The default height in pixels of the main window of this extension. 117 | * @param minWidth The minimum width in pixels of the main window of this extension. 118 | * @param minHeight The minimum height in pixels of the main window of this extension. 119 | * @param maxWidth The maximum width in pixels of the main window of this extension. 120 | * @param maxHeight The maximum height in pixels of the main window of this extension. 121 | * @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. 122 | * @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. 123 | * @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. 124 | * @param isAutoVisible True if this extension is visible on loading. 125 | * @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. 126 | * 127 | * @return A new \c Extension object. 128 | */ 129 | function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, 130 | defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) { 131 | this.id = id; 132 | this.name = name; 133 | this.mainPath = mainPath; 134 | this.basePath = basePath; 135 | this.windowType = windowType; 136 | this.width = width; 137 | this.height = height; 138 | this.minWidth = minWidth; 139 | this.minHeight = minHeight; 140 | this.maxWidth = maxWidth; 141 | this.maxHeight = maxHeight; 142 | this.defaultExtensionDataXml = defaultExtensionDataXml; 143 | this.specialExtensionDataXml = specialExtensionDataXml; 144 | this.requiredRuntimeList = requiredRuntimeList; 145 | this.isAutoVisible = isAutoVisible; 146 | this.isPluginExtension = isPluginExtension; 147 | } 148 | 149 | /** 150 | * @class CSEvent 151 | * A standard JavaScript event, the base class for CEP events. 152 | * 153 | * @param type The name of the event type. 154 | * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". 155 | * @param appId The unique identifier of the application that generated the event. 156 | * @param extensionId The unique identifier of the extension that generated the event. 157 | * 158 | * @return A new \c CSEvent object 159 | */ 160 | function CSEvent(type, scope, appId, extensionId) { 161 | this.type = type; 162 | this.scope = scope; 163 | this.appId = appId; 164 | this.extensionId = extensionId; 165 | } 166 | 167 | /** Event-specific data. */ 168 | CSEvent.prototype.data = ""; 169 | 170 | /** 171 | * @class SystemPath 172 | * Stores operating-system-specific location constants for use in the 173 | * \c #CSInterface.getSystemPath() method. 174 | * @return A new \c SystemPath object. 175 | */ 176 | function SystemPath() { 177 | } 178 | 179 | /** The path to user data. */ 180 | SystemPath.USER_DATA = "userData"; 181 | 182 | /** The path to common files for Adobe applications. */ 183 | SystemPath.COMMON_FILES = "commonFiles"; 184 | 185 | /** The path to the user's default document folder. */ 186 | SystemPath.MY_DOCUMENTS = "myDocuments"; 187 | 188 | /** @deprecated. Use \c #SystemPath.Extension. */ 189 | SystemPath.APPLICATION = "application"; 190 | 191 | /** The path to current extension. */ 192 | SystemPath.EXTENSION = "extension"; 193 | 194 | /** The path to hosting application's executable. */ 195 | SystemPath.HOST_APPLICATION = "hostApplication"; 196 | 197 | /** 198 | * @class ColorType 199 | * Stores color-type constants. 200 | */ 201 | function ColorType() { 202 | } 203 | 204 | /** RGB color type. */ 205 | ColorType.RGB = "rgb"; 206 | 207 | /** Gradient color type. */ 208 | ColorType.GRADIENT = "gradient"; 209 | 210 | /** Null color type. */ 211 | ColorType.NONE = "none"; 212 | 213 | /** 214 | * @class RGBColor 215 | * Stores an RGB color with red, green, blue, and alpha values. 216 | * All values are in the range [0.0 to 255.0]. Invalid numeric values are 217 | * converted to numbers within this range. 218 | * 219 | * @param red The red value, in the range [0.0 to 255.0]. 220 | * @param green The green value, in the range [0.0 to 255.0]. 221 | * @param blue The blue value, in the range [0.0 to 255.0]. 222 | * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. 223 | * The default, 255.0, means that the color is fully opaque. 224 | * 225 | * @return A new RGBColor object. 226 | */ 227 | function RGBColor(red, green, blue, alpha) { 228 | this.red = red; 229 | this.green = green; 230 | this.blue = blue; 231 | this.alpha = alpha; 232 | } 233 | 234 | /** 235 | * @class Direction 236 | * A point value in which the y component is 0 and the x component 237 | * is positive or negative for a right or left direction, 238 | * or the x component is 0 and the y component is positive or negative for 239 | * an up or down direction. 240 | * 241 | * @param x The horizontal component of the point. 242 | * @param y The vertical component of the point. 243 | * 244 | * @return A new \c Direction object. 245 | */ 246 | function Direction(x, y) { 247 | this.x = x; 248 | this.y = y; 249 | } 250 | 251 | /** 252 | * @class GradientStop 253 | * Stores gradient stop information. 254 | * 255 | * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. 256 | * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. 257 | * 258 | * @return GradientStop object. 259 | */ 260 | function GradientStop(offset, rgbColor) { 261 | this.offset = offset; 262 | this.rgbColor = rgbColor; 263 | } 264 | 265 | /** 266 | * @class GradientColor 267 | * Stores gradient color information. 268 | * 269 | * @param type The gradient type, must be "linear". 270 | * @param direction A \c #Direction object for the direction of the gradient 271 | (up, down, right, or left). 272 | * @param numStops The number of stops in the gradient. 273 | * @param gradientStopList An array of \c #GradientStop objects. 274 | * 275 | * @return A new \c GradientColor object. 276 | */ 277 | function GradientColor(type, direction, numStops, arrGradientStop) { 278 | this.type = type; 279 | this.direction = direction; 280 | this.numStops = numStops; 281 | this.arrGradientStop = arrGradientStop; 282 | } 283 | 284 | /** 285 | * @class UIColor 286 | * Stores color information, including the type, anti-alias level, and specific color 287 | * values in a color object of an appropriate type. 288 | * 289 | * @param type The color type, 1 for "rgb" and 2 for "gradient". 290 | The supplied color object must correspond to this type. 291 | * @param antialiasLevel The anti-alias level constant. 292 | * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. 293 | * 294 | * @return A new \c UIColor object. 295 | */ 296 | function UIColor(type, antialiasLevel, color) { 297 | this.type = type; 298 | this.antialiasLevel = antialiasLevel; 299 | this.color = color; 300 | } 301 | 302 | /** 303 | * @class AppSkinInfo 304 | * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. 305 | * 306 | * @param baseFontFamily The base font family of the application. 307 | * @param baseFontSize The base font size of the application. 308 | * @param appBarBackgroundColor The application bar background color. 309 | * @param panelBackgroundColor The background color of the extension panel. 310 | * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. 311 | * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. 312 | * @param systemHighlightColor The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color. 313 | * 314 | * @return AppSkinInfo object. 315 | */ 316 | function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) { 317 | this.baseFontFamily = baseFontFamily; 318 | this.baseFontSize = baseFontSize; 319 | this.appBarBackgroundColor = appBarBackgroundColor; 320 | this.panelBackgroundColor = panelBackgroundColor; 321 | this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; 322 | this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; 323 | this.systemHighlightColor = systemHighlightColor; 324 | } 325 | 326 | /** 327 | * @class HostEnvironment 328 | * Stores information about the environment in which the extension is loaded. 329 | * 330 | * @param appName The application's name. 331 | * @param appVersion The application's version. 332 | * @param appLocale The application's current license locale. 333 | * @param appUILocale The application's current UI locale. 334 | * @param appId The application's unique identifier. 335 | * @param isAppOnline True if the application is currently online. 336 | * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. 337 | * 338 | * @return A new \c HostEnvironment object. 339 | */ 340 | function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) { 341 | this.appName = appName; 342 | this.appVersion = appVersion; 343 | this.appLocale = appLocale; 344 | this.appUILocale = appUILocale; 345 | this.appId = appId; 346 | this.isAppOnline = isAppOnline; 347 | this.appSkinInfo = appSkinInfo; 348 | } 349 | 350 | /** 351 | * @class HostCapabilities 352 | * Stores information about the host capabilities. 353 | * 354 | * @param EXTENDED_PANEL_MENU True if the application supports panel menu. 355 | * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. 356 | * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. 357 | * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. 358 | * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. 359 | * 360 | * @return A new \c HostCapabilities object. 361 | */ 362 | function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) { 363 | this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; 364 | this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; 365 | this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; 366 | this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; 367 | this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 368 | } 369 | 370 | /** 371 | * @class ApiVersion 372 | * Stores current api version. 373 | * 374 | * Since 4.2.0 375 | * 376 | * @param major The major version 377 | * @param minor The minor version. 378 | * @param micro The micro version. 379 | * 380 | * @return ApiVersion object. 381 | */ 382 | function ApiVersion(major, minor, micro) { 383 | this.major = major; 384 | this.minor = minor; 385 | this.micro = micro; 386 | } 387 | 388 | /** 389 | * @class MenuItemStatus 390 | * Stores flyout menu item status 391 | * 392 | * Since 5.2.0 393 | * 394 | * @param menuItemLabel The menu item label. 395 | * @param enabled True if user wants to enable the menu item. 396 | * @param checked True if user wants to check the menu item. 397 | * 398 | * @return MenuItemStatus object. 399 | */ 400 | function MenuItemStatus(menuItemLabel, enabled, checked) { 401 | this.menuItemLabel = menuItemLabel; 402 | this.enabled = enabled; 403 | this.checked = checked; 404 | } 405 | 406 | /** 407 | * @class ContextMenuItemStatus 408 | * Stores the status of the context menu item. 409 | * 410 | * Since 5.2.0 411 | * 412 | * @param menuItemID The menu item id. 413 | * @param enabled True if user wants to enable the menu item. 414 | * @param checked True if user wants to check the menu item. 415 | * 416 | * @return MenuItemStatus object. 417 | */ 418 | function ContextMenuItemStatus(menuItemID, enabled, checked) { 419 | this.menuItemID = menuItemID; 420 | this.enabled = enabled; 421 | this.checked = checked; 422 | } 423 | //------------------------------ CSInterface ---------------------------------- 424 | 425 | /** 426 | * @class CSInterface 427 | * This is the entry point to the CEP extensibility infrastructure. 428 | * Instantiate this object and use it to: 429 | * 434 | * 435 | * @return A new \c CSInterface object 436 | */ 437 | function CSInterface() { 438 | } 439 | 440 | /** 441 | * User can add this event listener to handle native application theme color changes. 442 | * Callback function gives extensions ability to fine-tune their theme color after the 443 | * global theme color has been changed. 444 | * The callback function should be like below: 445 | * 446 | * @example 447 | * // event is a CSEvent object, but user can ignore it. 448 | * function OnAppThemeColorChanged(event) 449 | * { 450 | * // Should get a latest HostEnvironment object from application. 451 | * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; 452 | * // Gets the style information such as color info from the skinInfo, 453 | * // and redraw all UI controls of your extension according to the style info. 454 | * } 455 | */ 456 | CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; 457 | 458 | /** The host environment data object. */ 459 | CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null; 460 | 461 | /** Retrieves information about the host environment in which the 462 | * extension is currently running. 463 | * 464 | * @return A \c #HostEnvironment object. 465 | */ 466 | CSInterface.prototype.getHostEnvironment = function () { 467 | this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); 468 | return this.hostEnvironment; 469 | }; 470 | 471 | /** Closes this extension. */ 472 | CSInterface.prototype.closeExtension = function () { 473 | window.__adobe_cep__.closeExtension(); 474 | }; 475 | 476 | /** 477 | * Retrieves a path for which a constant is defined in the system. 478 | * 479 | * @param pathType The path-type constant defined in \c #SystemPath , 480 | * 481 | * @return The platform-specific system path string. 482 | */ 483 | CSInterface.prototype.getSystemPath = function (pathType) { 484 | var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); 485 | var OSVersion = this.getOSInformation(); 486 | if (OSVersion.indexOf("Windows") >= 0) { 487 | path = path.replace("file:///", ""); 488 | } 489 | else if (OSVersion.indexOf("Mac") >= 0) { 490 | path = path.replace("file://", ""); 491 | } 492 | return path; 493 | }; 494 | 495 | /** 496 | * Evaluates a JavaScript script, which can use the JavaScript DOM 497 | * of the host application. 498 | * 499 | * @param script The JavaScript script. 500 | * @param callback Optional. A callback function that receives the result of execution. 501 | * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. 502 | */ 503 | CSInterface.prototype.evalScript = function (script, callback) { 504 | if (callback === null || callback === undefined) { 505 | callback = function (result) { }; 506 | } 507 | window.__adobe_cep__.evalScript(script, callback); 508 | }; 509 | 510 | /** 511 | * Retrieves the unique identifier of the application. 512 | * in which the extension is currently running. 513 | * 514 | * @return The unique ID string. 515 | */ 516 | CSInterface.prototype.getApplicationID = function () { 517 | var appId = this.hostEnvironment.appId; 518 | return appId; 519 | }; 520 | 521 | /** 522 | * Retrieves host capability information for the application 523 | * in which the extension is currently running. 524 | * 525 | * @return A \c #HostCapabilities object. 526 | */ 527 | CSInterface.prototype.getHostCapabilities = function () { 528 | var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities()); 529 | return hostCapabilities; 530 | }; 531 | 532 | /** 533 | * Triggers a CEP event programmatically. Yoy can use it to dispatch 534 | * an event of a predefined type, or of a type you have defined. 535 | * 536 | * @param event A \c CSEvent object. 537 | */ 538 | CSInterface.prototype.dispatchEvent = function (event) { 539 | if (typeof event.data == "object") { 540 | event.data = JSON.stringify(event.data); 541 | } 542 | 543 | window.__adobe_cep__.dispatchEvent(event); 544 | }; 545 | 546 | /** 547 | * Registers an interest in a CEP event of a particular type, and 548 | * assigns an event handler. 549 | * The event infrastructure notifies your extension when events of this type occur, 550 | * passing the event object to the registered handler function. 551 | * 552 | * @param type The name of the event type of interest. 553 | * @param listener The JavaScript handler function or method. 554 | * @param obj Optional, the object containing the handler method, if any. 555 | * Default is null. 556 | */ 557 | CSInterface.prototype.addEventListener = function (type, listener, obj) { 558 | window.__adobe_cep__.addEventListener(type, listener, obj); 559 | }; 560 | 561 | /** 562 | * Removes a registered event listener. 563 | * 564 | * @param type The name of the event type of interest. 565 | * @param listener The JavaScript handler function or method that was registered. 566 | * @param obj Optional, the object containing the handler method, if any. 567 | * Default is null. 568 | */ 569 | CSInterface.prototype.removeEventListener = function (type, listener, obj) { 570 | window.__adobe_cep__.removeEventListener(type, listener, obj); 571 | }; 572 | 573 | /** 574 | * Loads and launches another extension, or activates the extension if it is already loaded. 575 | * 576 | * @param extensionId The extension's unique identifier. 577 | * @param startupParams Not currently used, pass "". 578 | * 579 | * @example 580 | * To launch the extension "help" with ID "HLP" from this extension, call: 581 | * requestOpenExtension("HLP", ""); 582 | * 583 | */ 584 | CSInterface.prototype.requestOpenExtension = function (extensionId, params) { 585 | window.__adobe_cep__.requestOpenExtension(extensionId, params); 586 | }; 587 | 588 | /** 589 | * Retrieves the list of extensions currently loaded in the current host application. 590 | * The extension list is initialized once, and remains the same during the lifetime 591 | * of the CEP session. 592 | * 593 | * @param extensionIds Optional, an array of unique identifiers for extensions of interest. 594 | * If omitted, retrieves data for all extensions. 595 | * 596 | * @return Zero or more \c #Extension objects. 597 | */ 598 | CSInterface.prototype.getExtensions = function (extensionIds) { 599 | var extensionIdsStr = JSON.stringify(extensionIds); 600 | var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); 601 | 602 | var extensions = JSON.parse(extensionsStr); 603 | return extensions; 604 | }; 605 | 606 | /** 607 | * Retrieves network-related preferences. 608 | * 609 | * @return A JavaScript object containing network preferences. 610 | */ 611 | CSInterface.prototype.getNetworkPreferences = function () { 612 | var result = window.__adobe_cep__.getNetworkPreferences(); 613 | var networkPre = JSON.parse(result); 614 | 615 | return networkPre; 616 | }; 617 | 618 | /** 619 | * Initializes the resource bundle for this extension with property values 620 | * for the current application and locale. 621 | * To support multiple locales, you must define a property file for each locale, 622 | * containing keyed display-string values for that locale. 623 | * See localization documentation for Extension Builder and related products. 624 | * 625 | * Keys can be in the 626 | * form key.value="localized string", for use in HTML text elements. 627 | * For example, in this input element, the localized \c key.value string is displayed 628 | * instead of the empty \c value string: 629 | * 630 | * 631 | * 632 | * @return An object containing the resource bundle information. 633 | */ 634 | CSInterface.prototype.initResourceBundle = function () { 635 | var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); 636 | var resElms = document.querySelectorAll('[data-locale]'); 637 | for (var n = 0; n < resElms.length; n++) { 638 | var resEl = resElms[n]; 639 | // Get the resource key from the element. 640 | var resKey = resEl.getAttribute('data-locale'); 641 | if (resKey) { 642 | // Get all the resources that start with the key. 643 | for (var key in resourceBundle) { 644 | if (key.indexOf(resKey) === 0) { 645 | var resValue = resourceBundle[key]; 646 | if (key.length == resKey.length) { 647 | resEl.innerHTML = resValue; 648 | } 649 | else if ('.' == key.charAt(resKey.length)) { 650 | var attrKey = key.substring(resKey.length + 1); 651 | resEl[attrKey] = resValue; 652 | } 653 | } 654 | } 655 | } 656 | } 657 | return resourceBundle; 658 | }; 659 | 660 | /** 661 | * Writes installation information to a file. 662 | * 663 | * @return The file path. 664 | */ 665 | CSInterface.prototype.dumpInstallationInfo = function () { 666 | return window.__adobe_cep__.dumpInstallationInfo(); 667 | }; 668 | 669 | /** 670 | * Retrieves version information for the current Operating System, 671 | * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. 672 | * 673 | * @return A string containing the OS version, or "unknown Operation System". 674 | * If user customizes the User Agent by setting CEF command parameter "--user-agent", only 675 | * "Mac OS X" or "Windows" will be returned. 676 | */ 677 | CSInterface.prototype.getOSInformation = function () { 678 | var userAgent = navigator.userAgent; 679 | 680 | if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) { 681 | var winVersion = "Windows"; 682 | var winBit = ""; 683 | if (userAgent.indexOf("Windows") > -1) { 684 | if (userAgent.indexOf("Windows NT 5.0") > -1) { 685 | winVersion = "Windows 2000"; 686 | } 687 | else if (userAgent.indexOf("Windows NT 5.1") > -1) { 688 | winVersion = "Windows XP"; 689 | } 690 | else if (userAgent.indexOf("Windows NT 5.2") > -1) { 691 | winVersion = "Windows Server 2003"; 692 | } 693 | else if (userAgent.indexOf("Windows NT 6.0") > -1) { 694 | winVersion = "Windows Vista"; 695 | } 696 | else if (userAgent.indexOf("Windows NT 6.1") > -1) { 697 | winVersion = "Windows 7"; 698 | } 699 | else if (userAgent.indexOf("Windows NT 6.2") > -1) { 700 | winVersion = "Windows 8"; 701 | } 702 | else if (userAgent.indexOf("Windows NT 6.3") > -1) { 703 | winVersion = "Windows 8.1"; 704 | } 705 | else if (userAgent.indexOf("Windows NT 10") > -1) { 706 | winVersion = "Windows 10"; 707 | } 708 | 709 | if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1) { 710 | winBit = " 64-bit"; 711 | } 712 | else { 713 | winBit = " 32-bit"; 714 | } 715 | } 716 | 717 | return winVersion + winBit; 718 | } 719 | else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) { 720 | var result = "Mac OS X"; 721 | 722 | if (userAgent.indexOf("Mac OS X") > -1) { 723 | result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")")); 724 | result = result.replace(/_/g, "."); 725 | } 726 | 727 | return result; 728 | } 729 | 730 | return "Unknown Operation System"; 731 | }; 732 | 733 | /** 734 | * Opens a page in the default system browser. 735 | * 736 | * Since 4.2.0 737 | * 738 | * @param url The URL of the page/file to open, or the email address. 739 | * Must use HTTP/HTTPS/file/mailto protocol. For example: 740 | * "http://www.adobe.com" 741 | * "https://github.com" 742 | * "file:///C:/log.txt" 743 | * "mailto:test@adobe.com" 744 | * 745 | * @return One of these error codes:\n 746 | * \n 752 | */ 753 | CSInterface.prototype.openURLInDefaultBrowser = function (url) { 754 | return cep.util.openURLInDefaultBrowser(url); 755 | }; 756 | 757 | /** 758 | * Retrieves extension ID. 759 | * 760 | * Since 4.2.0 761 | * 762 | * @return extension ID. 763 | */ 764 | CSInterface.prototype.getExtensionID = function () { 765 | return window.__adobe_cep__.getExtensionId(); 766 | }; 767 | 768 | /** 769 | * Retrieves the scale factor of screen. 770 | * On Windows platform, the value of scale factor might be different from operating system's scale factor, 771 | * since host application may use its self-defined scale factor. 772 | * 773 | * Since 4.2.0 774 | * 775 | * @return One of the following float number. 776 | * \n 781 | */ 782 | CSInterface.prototype.getScaleFactor = function () { 783 | return window.__adobe_cep__.getScaleFactor(); 784 | }; 785 | 786 | /** 787 | * Retrieves the scale factor of Monitor. 788 | * 789 | * Since 8.5.0 790 | * 791 | * @return value >= 1.0f 792 | * only available for windows machine 793 | */ 794 | if (navigator.appVersion.toLowerCase().indexOf("windows") >= 0) { 795 | CSInterface.prototype.getMonitorScaleFactor = function () { 796 | return window.__adobe_cep__.getMonitorScaleFactor(); 797 | }; 798 | } 799 | 800 | /** 801 | * Set a handler to detect any changes of scale factor. This only works on Mac. 802 | * 803 | * Since 4.2.0 804 | * 805 | * @param handler The function to be called when scale factor is changed. 806 | * 807 | */ 808 | CSInterface.prototype.setScaleFactorChangedHandler = function (handler) { 809 | window.__adobe_cep__.setScaleFactorChangedHandler(handler); 810 | }; 811 | 812 | /** 813 | * Retrieves current API version. 814 | * 815 | * Since 4.2.0 816 | * 817 | * @return ApiVersion object. 818 | * 819 | */ 820 | CSInterface.prototype.getCurrentApiVersion = function () { 821 | var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); 822 | return apiVersion; 823 | }; 824 | 825 | /** 826 | * Set panel flyout menu by an XML. 827 | * 828 | * Since 5.2.0 829 | * 830 | * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a 831 | * menu item is clicked. 832 | * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. 833 | * 834 | * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" 835 | * respectively to get notified when flyout menu is opened or closed. 836 | * 837 | * @param menu A XML string which describes menu structure. 838 | * An example menu XML: 839 | * 840 | * 841 | * 842 | * 843 | * 844 | * 845 | * 846 | * 847 | * 848 | * 849 | * 850 | * 851 | */ 852 | CSInterface.prototype.setPanelFlyoutMenu = function (menu) { 853 | if ("string" != typeof menu) { 854 | return; 855 | } 856 | 857 | window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); 858 | }; 859 | 860 | /** 861 | * Updates a menu item in the extension window's flyout menu, by setting the enabled 862 | * and selection status. 863 | * 864 | * Since 5.2.0 865 | * 866 | * @param menuItemLabel The menu item label. 867 | * @param enabled True to enable the item, false to disable it (gray it out). 868 | * @param checked True to select the item, false to deselect it. 869 | * 870 | * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). 871 | * Fails silently if menu label is invalid. 872 | * 873 | * @see HostCapabilities.EXTENDED_PANEL_MENU 874 | */ 875 | CSInterface.prototype.updatePanelMenuItem = function (menuItemLabel, enabled, checked) { 876 | var ret = false; 877 | if (this.getHostCapabilities().EXTENDED_PANEL_MENU) { 878 | var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); 879 | ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); 880 | } 881 | return ret; 882 | }; 883 | 884 | 885 | /** 886 | * Set context menu by XML string. 887 | * 888 | * Since 5.2.0 889 | * 890 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 891 | * - an item without menu ID or menu name is disabled and is not shown. 892 | * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 893 | * - Checkable attribute takes precedence over Checked attribute. 894 | * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. 895 | The Chrome extension contextMenus API was taken as a reference. 896 | https://developer.chrome.com/extensions/contextMenus 897 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 898 | * 899 | * @param menu A XML string which describes menu structure. 900 | * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. 901 | * 902 | * @description An example menu XML: 903 | * 904 | * 905 | * 906 | * 907 | * 908 | * 909 | * 910 | * 911 | * 912 | * 913 | * 914 | */ 915 | CSInterface.prototype.setContextMenu = function (menu, callback) { 916 | if ("string" != typeof menu) { 917 | return; 918 | } 919 | 920 | window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); 921 | }; 922 | 923 | /** 924 | * Set context menu by JSON string. 925 | * 926 | * Since 6.0.0 927 | * 928 | * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. 929 | * - an item without menu ID or menu name is disabled and is not shown. 930 | * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. 931 | * - Checkable attribute takes precedence over Checked attribute. 932 | * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. 933 | The Chrome extension contextMenus API was taken as a reference. 934 | * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. 935 | https://developer.chrome.com/extensions/contextMenus 936 | * 937 | * @param menu A JSON string which describes menu structure. 938 | * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. 939 | * 940 | * @description An example menu JSON: 941 | * 942 | * { 943 | * "menu": [ 944 | * { 945 | * "id": "menuItemId1", 946 | * "label": "testExample1", 947 | * "enabled": true, 948 | * "checkable": true, 949 | * "checked": false, 950 | * "icon": "./image/small_16X16.png" 951 | * }, 952 | * { 953 | * "id": "menuItemId2", 954 | * "label": "testExample2", 955 | * "menu": [ 956 | * { 957 | * "id": "menuItemId2-1", 958 | * "label": "testExample2-1", 959 | * "menu": [ 960 | * { 961 | * "id": "menuItemId2-1-1", 962 | * "label": "testExample2-1-1", 963 | * "enabled": false, 964 | * "checkable": true, 965 | * "checked": true 966 | * } 967 | * ] 968 | * }, 969 | * { 970 | * "id": "menuItemId2-2", 971 | * "label": "testExample2-2", 972 | * "enabled": true, 973 | * "checkable": true, 974 | * "checked": true 975 | * } 976 | * ] 977 | * }, 978 | * { 979 | * "label": "---" 980 | * }, 981 | * { 982 | * "id": "menuItemId3", 983 | * "label": "testExample3", 984 | * "enabled": false, 985 | * "checkable": true, 986 | * "checked": false 987 | * } 988 | * ] 989 | * } 990 | * 991 | */ 992 | CSInterface.prototype.setContextMenuByJSON = function (menu, callback) { 993 | if ("string" != typeof menu) { 994 | return; 995 | } 996 | 997 | window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); 998 | }; 999 | 1000 | /** 1001 | * Updates a context menu item by setting the enabled and selection status. 1002 | * 1003 | * Since 5.2.0 1004 | * 1005 | * @param menuItemID The menu item ID. 1006 | * @param enabled True to enable the item, false to disable it (gray it out). 1007 | * @param checked True to select the item, false to deselect it. 1008 | */ 1009 | CSInterface.prototype.updateContextMenuItem = function (menuItemID, enabled, checked) { 1010 | var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); 1011 | ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); 1012 | }; 1013 | 1014 | /** 1015 | * Get the visibility status of an extension window. 1016 | * 1017 | * Since 6.0.0 1018 | * 1019 | * @return true if the extension window is visible; false if the extension window is hidden. 1020 | */ 1021 | CSInterface.prototype.isWindowVisible = function () { 1022 | return window.__adobe_cep__.invokeSync("isWindowVisible", ""); 1023 | }; 1024 | 1025 | /** 1026 | * Resize extension's content to the specified dimensions. 1027 | * 1. Works with modal and modeless extensions in all Adobe products. 1028 | * 2. Extension's manifest min/max size constraints apply and take precedence. 1029 | * 3. For panel extensions 1030 | * 3.1 This works in all Adobe products except: 1031 | * * Premiere Pro 1032 | * * Prelude 1033 | * * After Effects 1034 | * 3.2 When the panel is in certain states (especially when being docked), 1035 | * it will not change to the desired dimensions even when the 1036 | * specified size satisfies min/max constraints. 1037 | * 1038 | * Since 6.0.0 1039 | * 1040 | * @param width The new width 1041 | * @param height The new height 1042 | */ 1043 | CSInterface.prototype.resizeContent = function (width, height) { 1044 | window.__adobe_cep__.resizeContent(width, height); 1045 | }; 1046 | 1047 | /** 1048 | * Register the invalid certificate callback for an extension. 1049 | * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame. 1050 | * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown. 1051 | * 1052 | * Since 6.1.0 1053 | * 1054 | * @param callback the callback function 1055 | */ 1056 | CSInterface.prototype.registerInvalidCertificateCallback = function (callback) { 1057 | return window.__adobe_cep__.registerInvalidCertificateCallback(callback); 1058 | }; 1059 | 1060 | /** 1061 | * Register an interest in some key events to prevent them from being sent to the host application. 1062 | * 1063 | * This function works with modeless extensions and panel extensions. 1064 | * Generally all the key events will be sent to the host application for these two extensions if the current focused element 1065 | * is not text input or dropdown, 1066 | * If you want to intercept some key events and want them to be handled in the extension, please call this function 1067 | * in advance to prevent them being sent to the host application. 1068 | * 1069 | * Since 6.1.0 1070 | * 1071 | * @param keyEventsInterest A JSON string describing those key events you are interested in. A null object or 1072 | an empty string will lead to removing the interest 1073 | * 1074 | * This JSON string should be an array, each object has following keys: 1075 | * 1076 | * keyCode: [Required] represents an OS system dependent virtual key code identifying 1077 | * the unmodified value of the pressed key. 1078 | * ctrlKey: [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred. 1079 | * altKey: [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred. 1080 | * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred. 1081 | * metaKey: [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred. 1082 | * On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead. 1083 | * An example JSON string: 1084 | * 1085 | * [ 1086 | * { 1087 | * "keyCode": 48 1088 | * }, 1089 | * { 1090 | * "keyCode": 123, 1091 | * "ctrlKey": true 1092 | * }, 1093 | * { 1094 | * "keyCode": 123, 1095 | * "ctrlKey": true, 1096 | * "metaKey": true 1097 | * } 1098 | * ] 1099 | * 1100 | */ 1101 | CSInterface.prototype.registerKeyEventsInterest = function (keyEventsInterest) { 1102 | return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest); 1103 | }; 1104 | 1105 | /** 1106 | * Set the title of the extension window. 1107 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1108 | * 1109 | * Since 6.1.0 1110 | * 1111 | * @param title The window title. 1112 | */ 1113 | CSInterface.prototype.setWindowTitle = function (title) { 1114 | window.__adobe_cep__.invokeSync("setWindowTitle", title); 1115 | }; 1116 | 1117 | /** 1118 | * Get the title of the extension window. 1119 | * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. 1120 | * 1121 | * Since 6.1.0 1122 | * 1123 | * @return The window title. 1124 | */ 1125 | CSInterface.prototype.getWindowTitle = function () { 1126 | return window.__adobe_cep__.invokeSync("getWindowTitle", ""); 1127 | }; -------------------------------------------------------------------------------- /client/libs/events.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var csInterface = new CSInterface(); 5 | 6 | // csInterface.addEventListener('console', function(evt) { 7 | // console.log('JSX > ' + evt.data); 8 | // }); 9 | 10 | csInterface.addEventListener('mighty.rollcall', function(evt) { 11 | dispatchEvent('mighty.rollanswer', extFolder()) 12 | }); 13 | 14 | function dispatchEvent(name, data) { 15 | var event = new CSEvent(name, 'APPLICATION'); 16 | event.data = data; 17 | csInterface.dispatchEvent(event); 18 | } 19 | 20 | }()); 21 | -------------------------------------------------------------------------------- /client/libs/menus.js: -------------------------------------------------------------------------------- 1 | var csInterface = new CSInterface(); 2 | // var isFlipped = false; 3 | 4 | var menu_FlyoutXML = ' \ 5 | \ 6 | '; 7 | // \ 8 | // \ 9 | // \ 10 | 11 | csInterface.setPanelFlyoutMenu(menu_FlyoutXML); 12 | csInterface.addEventListener("com.adobe.csxs.events.flyoutMenuClicked", setPanelCallback); 13 | 14 | 15 | function setPanelCallback(event) { 16 | if (event.data.menuId == "refresh") { 17 | location.reload(); 18 | } 19 | } 20 | 21 | // var menu_ContextXML = ' \ 22 | // \ 23 | // \ 24 | // \ 25 | // \ 26 | // '; 27 | // 28 | // csInterface.setContextMenu(menu_ContextXML, setContextMenuCallback); 29 | // 30 | // function setContextMenuCallback(event) { 31 | // if (event == "refresh") { 32 | // location.reload(); 33 | // } else if (event == "width") { 34 | // alert(window.innerWidth); 35 | // } else if (event === 'resize') { 36 | // // csInterface.resizeContent(200, 200) 37 | // } else { 38 | // console.log(event); 39 | // } 40 | // } 41 | -------------------------------------------------------------------------------- /client/libs/preStyle.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-size: 12px; 3 | --quad: cubic-bezier(0.48, 0.04, 0.52, 0.96); 4 | --quart: cubic-bezier(0.76, 0.00, 0.24, 1.00); 5 | --quint: cubic-bezier(0.84, 0.00, 0.16, 1.00); 6 | --color-bg: #323232; 7 | --color-selected: #46a0f5; 8 | --color-border: #3e3e3e; 9 | --color-hover: #292929; 10 | --tab-margin: .75rem; 11 | --font-size: .875rem; 12 | font-family: Rubik; 13 | color: #a1a1a1; 14 | margin: .5rem .25rem 0px .25rem; 15 | background-color: var(--color-bg); 16 | } 17 | -------------------------------------------------------------------------------- /client/libs/reference.js: -------------------------------------------------------------------------------- 1 | var csInterface = new CSInterface(); 2 | 3 | function extFolder(){ 4 | var str = csInterface.getSystemPath(SystemPath.EXTENSION); 5 | var parent = str.substring(str.lastIndexOf('/') + 1, str.length); 6 | return parent; 7 | } 8 | 9 | function loadJSX(fileName) { 10 | var root = csInterface.getSystemPath(SystemPath.EXTENSION) + "/host/"; 11 | csInterface.evalScript('$.evalFile("' + root + fileName + '")'); 12 | } 13 | 14 | function loadUniversalJSXLibraries() { 15 | var libs = ["json2.jsx", "Console.jsx"]; 16 | var root = csInterface.getSystemPath(SystemPath.EXTENSION) + "/host/universal/"; 17 | for (var i = 0; i < libs.length; i++) 18 | csInterface.evalScript('$.evalFile("' + root + libs[i] + '")'); 19 | } 20 | 21 | /** 22 | * Premiere Pro Panel 23 | */ 24 | function toHex(color, delta) { 25 | function computeValue(value, delta) { 26 | var computedValue = !isNaN(delta) ? value + delta : value; 27 | if (computedValue < 0) { 28 | computedValue = 0; 29 | } else if (computedValue > 255) { 30 | computedValue = 255; 31 | } 32 | 33 | computedValue = Math.round(computedValue).toString(16); 34 | return computedValue.length == 1 ? "0" + computedValue : computedValue; 35 | } 36 | 37 | var hex = ""; 38 | if (color) { 39 | with (color) { 40 | hex = computeValue(red, delta) + computeValue(green, delta) + computeValue(blue, delta); 41 | }; 42 | } 43 | return "#" + hex; 44 | } 45 | 46 | // https://stackoverflow.com/a/11923973 47 | function rgbToHsl(c) { 48 | var r = c[0]/255, g = c[1]/255, b = c[2]/255; 49 | var max = Math.max(r, g, b), min = Math.min(r, g, b); 50 | var h, s, l = (max + min) / 2; 51 | 52 | if(max == min) { 53 | h = s = 0; // achromatic 54 | } else { 55 | var d = max - min; 56 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 57 | switch(max){ 58 | case r: h = (g - b) / d + (g < b ? 6 : 0); break; 59 | case g: h = (b - r) / d + 2; break; 60 | case b: h = (r - g) / d + 4; break; 61 | } 62 | h /= 6; 63 | } 64 | // return new Array(h, s, l); 65 | return new Array(h * 360, s * 100, l * 100); 66 | } 67 | 68 | // https://stackoverflow.com/a/44134328 69 | function hslToHex(h, s, l) { 70 | h /= 360; 71 | s /= 100; 72 | l /= 100; 73 | let r, g, b; 74 | if (s === 0) { 75 | r = g = b = l; // achromatic 76 | } else { 77 | const hue2rgb = (p, q, t) => { 78 | if (t < 0) t += 1; 79 | if (t > 1) t -= 1; 80 | if (t < 1 / 6) return p + (q - p) * 6 * t; 81 | if (t < 1 / 2) return q; 82 | if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; 83 | return p; 84 | }; 85 | const q = l < 0.5 ? l * (1 + s) : l + s - l * s; 86 | const p = 2 * l - q; 87 | r = hue2rgb(p, q, h + 1 / 3); 88 | g = hue2rgb(p, q, h); 89 | b = hue2rgb(p, q, h - 1 / 3); 90 | } 91 | const toHex = x => { 92 | const hex = Math.round(x * 255).toString(16); 93 | return hex.length === 1 ? '0' + hex : hex; 94 | }; 95 | return `#${toHex(r)}${toHex(g)}${toHex(b)}`; 96 | } 97 | 98 | /// https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb 99 | function componentToHex(c) { 100 | var hex = c.toString(16); 101 | return hex.length == 1 ? "0" + hex : hex; 102 | } 103 | 104 | function rgbToHex(r, g, b) { 105 | return componentToHex(r) + componentToHex(g) + componentToHex(b); 106 | } 107 | 108 | function hexToRgb(hex) { 109 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 110 | return result ? { 111 | r: parseInt(result[1], 16), 112 | g: parseInt(result[2], 16), 113 | b: parseInt(result[3], 16) 114 | } : null; 115 | } 116 | -------------------------------------------------------------------------------- /client/libs/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /client/libs/v-outside-events.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-outside-events @ 1.1.3 3 | * Nicholas Hutchind 4 | * 5 | * Vue directive to react to various events outside the current element 6 | * 7 | * License: MIT 8 | */ 9 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e["vue-outside-events"]=t()}(this,function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(t,i){var n={};return n.directiveName=t,n.eventName=i,n.bind=function(n,o,u){var d=void 0!==console.error?console.error:console.log,r=null,v=void 0;if("function"!=typeof o.value)if("object"===e(o.value)&&o.value.hasOwnProperty("handler")&&"function"==typeof o.value.handler)r=o.value.handler,delete(v=Object.assign({},o.value)).handler;else{var a="["+t+"]: provided expression '"+o.expression+"' must be a function or an object containing a property named 'handler' that is a function.";u.context.name&&(a+="\nFound in component '"+u.context.name+"'"),d(a)}else r=o.value;var c=function(e){n.contains(e.target)||n===e.target||r(e,n,v)};n["__vueEventOutside__"+i]=c,document.addEventListener(i,c)},n.unbind=function(e,t){document.removeEventListener(i,e["__vueEventOutside__"+i]),e["__vueEventOutside__"+i]=null},n},i={directiveName:"event-outside",bind:function(t,i,n){var o=void 0!==console.error?console.error:console.log,u=void 0;if("object"!==e(i.value)||void 0===i.value.name||"string"!=typeof i.value.name||void 0===i.value.handler||"function"!=typeof i.value.handler){var d="[v-event-outside]: provided expression '"+i.expression+'\' must be an object containing a "name" string and a "handler" function.';return n.context.name&&(d+="\nFound in component '"+n.context.name+"'"),void o(d)}if(delete(u=Object.assign({},i.value)).name,delete u.handler,i.modifiers.jquery&&void 0===window.$&&void 0===window.jQuery){var r="[v-event-outside]: jQuery is not present in window.";return n.context.name&&(r+="\nFound in component '"+n.context.name+"'"),void o(r)}var v=function(e){t.contains(e.target)||t===e.target||i.value.handler(e,t,u)};t["__vueEventOutside__"+i.value.name]=v,i.modifiers.jquery?jQuery(document).on(i.value.name,v):document.addEventListener(i.value.name,v)},unbind:function(e,t){t.modifiers.jquery?jQuery(document).off(t.value.name,e["__vueEventOutside__"+t.value.name]):document.removeEventListener(t.value.name,e["__vueEventOutside__"+t.value.name]),e["__vueEventOutside__"+t.value.name]=null}},n=t("click-outside","click"),o=t("dblclick-outside","dblclick"),u=t("focus-outside","focusin"),d=t("blur-outside","focusout"),r=t("mousemove-outside","mousemove"),v=t("mousedown-outside","mousedown"),a=t("mouseup-outside","mouseup"),c=t("mouseover-outside","mouseover"),s=t("mouseout-outside","mouseout"),m=t("change-outside","change"),l=t("select-outside","select"),f=t("submit-outside","submit"),p=t("keydown-outside","keydown"),y=t("keypress-outside","keypress"),_=t("keyup-outside","keyup"),b={install:function(e){e.directive(n.directiveName,n),e.directive(o.directiveName,o),e.directive(u.directiveName,u),e.directive(d.directiveName,d),e.directive(r.directiveName,r),e.directive(v.directiveName,v),e.directive(a.directiveName,a),e.directive(c.directiveName,c),e.directive(s.directiveName,s),e.directive(m.directiveName,m),e.directive(l.directiveName,l),e.directive(f.directiveName,f),e.directive(p.directiveName,p),e.directive(y.directiveName,y),e.directive(y.directiveName,y),e.directive(_.directiveName,_),e.directive(i.directiveName,i)}};return"undefined"!=typeof window&&window.Vue&&window.Vue.use(b),b}); 10 | -------------------------------------------------------------------------------- /client/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-size: 12px; 3 | --quad: cubic-bezier(0.48, 0.04, 0.52, 0.96); 4 | --quart: cubic-bezier(0.76, 0.00, 0.24, 1.00); 5 | --quint: cubic-bezier(0.84, 0.00, 0.16, 1.00); 6 | --color-bg: #323232; 7 | --color-scroll: #2a2a2a; 8 | --color-scroll-thumb: #3e3e3e; 9 | --color-scroll-thumb-hover: #525252; 10 | 11 | --color-ui-idle: #3d3d3d; 12 | --color-ui-active: #4b4b4b; 13 | --color-ui-ultra: #797979; 14 | --color-text-idle: #b9b9b9; 15 | --color-text-hover: #c0c0c0; 16 | --color-text-active: #d0d0d0; 17 | --color-text: #a1a1a1; 18 | 19 | --color-ui-selected: #46a0f5; 20 | --color-ui-border: #3e3e3e; 21 | --color-ui-hover: #292929; 22 | 23 | --color-def-stroke: #444444; 24 | --color-def-fill: #333333; 25 | --color-def-stroke-frame: #1f1f1f; 26 | --color-def-fill-frame: #1f1f1f; 27 | 28 | --color-R: #eb6d5a; 29 | --color-G: #66ff3b; 30 | --color-B: #3593eb; 31 | --thumb-width: 10px; 32 | --scroll-radius: 20px; 33 | --swatch-height: 1.25rem; 34 | --swatchList-height: auto; 35 | --swatchLength: 3; 36 | --tab-margin: .75rem; 37 | --font-size: .875rem; 38 | --panel-height: 200px; 39 | font-family: Rubik; 40 | color: #a1a1a1; 41 | margin: .5rem .25rem 0px .25rem; 42 | background-color: var(--color-bg); 43 | } 44 | 45 | svg {width: 100%;} 46 | 47 | @font-face { 48 | font-family: 'protocolors'; 49 | src: 50 | url('../assets/fonts/protocolors.ttf?u444x7') format('truetype'), 51 | url('../assets/fonts/protocolors.woff?u444x7') format('woff'), 52 | url('../assets/fonts/protocolors.svg?u444x7#protocolors') format('svg'); 53 | font-weight: normal; 54 | font-style: normal; 55 | } 56 | [class^="protocolor-icon-"], [class*=" protocolor-icon-"] { 57 | font-family: 'protocolors' !important; 58 | speak: none; 59 | font-style: normal; 60 | font-weight: normal; 61 | font-variant: normal; 62 | text-transform: none; 63 | line-height: 1; 64 | -webkit-font-smoothing: antialiased; 65 | -moz-osx-font-smoothing: grayscale; 66 | } 67 | .protocolor-icon-arrow:before { content: "\e900"; } 68 | .protocolor-icon-cancel:before { content: "\e901"; } 69 | .protocolor-icon-cursor:before { content: "\e902"; } 70 | .protocolor-icon-doublearrow:before { content: "\e903"; } 71 | .protocolor-icon-dropper:before { content: "\e904"; } 72 | .protocolor-icon-find:before { content: "\e905"; } 73 | .protocolor-icon-minus:before { content: "\e906"; } 74 | .protocolor-icon-plus:before { content: "\e907"; } 75 | 76 | 77 | .bbox { box-sizing: border-box; } 78 | 79 | #app { 80 | max-width: 50px; 81 | min-width: 30px; 82 | box-sizing: border-box; 83 | height: var(--panel-height); 84 | } 85 | 86 | /* @media only screen and (max-width: 120px){ 87 | #app { 88 | background-color: blue; 89 | } 90 | } 91 | 92 | @media only screen and (max-width: 66px){ 93 | #app { 94 | background-color: red; 95 | } 96 | } 97 | 98 | @media only screen and (max-width: 32px){ 99 | #app { 100 | background-color: green; 101 | } 102 | } */ 103 | 104 | /* Scrollbar */ 105 | ::-webkit-scrollbar { 106 | width: 10px; 107 | background: var(--color-scroll); 108 | } 109 | 110 | ::-webkit-scrollbar-thumb { 111 | width: var(--thumb-width); 112 | background: var(--color-scroll-thumb); 113 | border-radius: var(--scroll-radius); 114 | } 115 | ::-webkit-scrollbar-thumb:hover { 116 | background: var(--color-scroll-thumb-hover); 117 | } 118 | 119 | ::-webkit-scrollbar-button { 120 | display: none; 121 | } 122 | 123 | ::-webkit-scrollbar:single-button { 124 | /* margin: 1rem 0px; */ 125 | } 126 | 127 | ::-webkit-scrollbar-button:start { 128 | /* background-image: url('./scrollbarUpBtnAlt.png'); */ 129 | } 130 | 131 | ::-webkit-scrollbar-button:end { 132 | /* background-image: url('./scrollbarDownBtnAlt.png'); */ 133 | } 134 | 135 | ::-webkit-scrollbar-button:start:hover { 136 | /* background-image: url('./scrollbarUpBtnAltHover.png'); */ 137 | } 138 | 139 | ::-webkit-scrollbar-button:end:hover { 140 | /* background-image: url('./scrollbarDownBtnAltHover.png'); */ 141 | } 142 | 143 | 144 | 145 | 146 | .appGrid { 147 | box-sizing: border-box; 148 | height: var(--panel-height); 149 | display: grid; 150 | grid-template-rows: 18fr 0fr; 151 | grid-row-gap: .5rem; 152 | overflow: hidden; 153 | } 154 | 155 | [class^="mainTop"] { 156 | display: grid; 157 | grid-row-gap: .5rem; 158 | } 159 | .mainTop-ILST { 160 | display: flex; 161 | flex-wrap: wrap; 162 | /* grid-template-rows: 1fr 4fr; */ 163 | } 164 | .mainTop-PHXS { 165 | display: flex; 166 | flex-wrap: wrap; 167 | /* grid-template-rows: .75fr 4fr; */ 168 | } 169 | .mainTop-AEFT { 170 | display: flex; 171 | flex-wrap: wrap; 172 | /* grid-template-rows: 1fr 4fr; */ 173 | } 174 | 175 | 176 | .end { 177 | /* box-sizing: border-box; */ 178 | /* border: 2px solid red; */ 179 | font-size: .75rem; 180 | width: 100%; 181 | /* margin-top: -1rem; */ 182 | /* height: 1rem; */ 183 | color: var(color-ui-idle); 184 | display: flex; 185 | justify-content: flex-start; 186 | align-items: flex-start; 187 | margin-left: .5rem; 188 | } 189 | 190 | .resetSwatchList { 191 | width: 100%; 192 | height: 2rem; 193 | display: flex; 194 | justify-content: center; 195 | align-items: center; 196 | cursor: pointer; 197 | border-radius: .0625rem; 198 | background-color: var(--color-ui-hover); 199 | color: var(--color-light-idle); 200 | } 201 | .resetSwatchList:hover { 202 | background-color: var(--color-ui-active); 203 | } 204 | 205 | [class^="headerMain"] { 206 | /* border: 2px solid red; */ 207 | width: 100%; 208 | height: 6rem; 209 | box-sizing: border-box; 210 | display: grid; 211 | grid-row-gap: .25rem; 212 | grid-template-rows: 0fr 2fr; 213 | } 214 | 215 | .headerInSelection { 216 | display: grid; 217 | grid-template-columns: 1fr; 218 | } 219 | .inSelectionGrid { 220 | box-sizing: border-box; 221 | display: grid; 222 | background-color: var(--color-ui-hover); 223 | } 224 | 225 | .inSelectionCell { 226 | box-sizing: border-box; 227 | background-color: transparent; 228 | } 229 | 230 | [class^="headerVisualizers"] { 231 | box-sizing: border-box; 232 | display: grid; 233 | grid-row-gap: .25rem; 234 | } 235 | 236 | .headerVisualizers-ILST { 237 | grid-template-rows: .5fr 6fr 1fr; 238 | } 239 | .headerVisualizers-PHXS { 240 | grid-template-rows: .5fr 6fr 0fr; 241 | } 242 | .headerVisualizers-AEFT { 243 | grid-template-rows: .5fr 6fr 1fr; 244 | } 245 | 246 | .visualizerModKeys { 247 | display: grid; 248 | grid-column-gap: .25rem; 249 | background-color: var(--color-ui-hover); 250 | } 251 | [class^="modKey"] { 252 | box-sizing: border-box; 253 | display: flex; 254 | justify-content: center; 255 | align-items: center; 256 | } 257 | .modKey-Shift-Active { background-color: var(--color-G);} 258 | .modKey-Ctrl-Active { background-color: var(--color-R);} 259 | .modKey-Alt-Active { background-color: var(--color-B);} 260 | 261 | .visualizerFillStroke { 262 | width: 100%; 263 | display: flex; 264 | justify-content: center; 265 | align-items: center; 266 | background-color: var(--color-bg); 267 | } 268 | 269 | .fillstroke-mask {fill: var(--color-bg);} 270 | .fillstroke-bg {fill: var(--color-bg);} 271 | .fillstroke-fill {fill: var(--color-def-fill);} 272 | .fillstroke-stroke {fill: var(--color-def-stroke);} 273 | 274 | .multiClass { 275 | fill: #fff; 276 | } 277 | 278 | .fillstroke-cancel, .fillstroke-frame { 279 | fill: none; 280 | stroke-miterlimit: 10; 281 | stroke-width: 2px; 282 | } 283 | 284 | .fillstroke-cancel {stroke: red;} 285 | .fillstroke-fill-frame { 286 | stroke: var(--color-def-fill-frame); 287 | stroke-linejoin: round; 288 | stroke-width: 2px; 289 | fill: none; 290 | } 291 | .fillstroke-stroke-frame { 292 | stroke: var(--color-def-stroke-frame); 293 | stroke-linejoin: round; 294 | stroke-width: 2px; 295 | fill: none; 296 | } 297 | 298 | 299 | 300 | .bodyMain { 301 | display: flex; 302 | box-sizing: border-box; 303 | /* border: 1px solid red; */ 304 | width: 100%; 305 | flex-direction: column; 306 | justify-content: flex-start; 307 | background-color: var(--color-bg); 308 | overflow: auto; 309 | height: calc(var(--panel-height) - 90px); 310 | } 311 | 312 | 313 | 314 | .bodySwatches { 315 | /* border: 2px solid green; */ 316 | box-sizing: border-box; 317 | width: 100%; 318 | height: var(--swatchList-height); 319 | } 320 | 321 | [class^="swatchMain"] { 322 | box-sizing: border-box; 323 | width: 100%; 324 | display: flex; 325 | justify-content: center; 326 | align-items: center; 327 | flex-wrap: nowrap; 328 | } 329 | 330 | 331 | .swatchList { 332 | /* border: 1px solid green; */ 333 | width: 100%; 334 | display: grid; 335 | grid-template: repeat(var(--swatchLength), 1fr); 336 | /* grid-auto-flow: column; */ 337 | /* grid-template-rows: repeat(3, 1fr) */ 338 | /* grid-template-columns: ; */ 339 | } 340 | [class^="swatch-idle"] { 341 | box-sizing: border-box; 342 | height: var(--swatch-height); 343 | cursor: pointer; 344 | display: grid; 345 | } 346 | .swatch-idle-ILST { 347 | /* grid-template-columns: 5fr .5fr 1fr; */ 348 | grid-template-columns: 5fr 0fr 0fr; 349 | } 350 | .swatch-idle-PHXS { 351 | grid-template-columns: 5fr 0fr 0fr; 352 | } 353 | .swatch-idle-AEFT { 354 | grid-template-columns: 5fr 0fr 0fr; 355 | } 356 | 357 | .blank { background-color: var(--color-bg); } 358 | 359 | .swatch-tag-icon { 360 | height: 0px; 361 | width: 0px; 362 | border: 3px solid var(--color-ui-selected); 363 | } 364 | 365 | .swatch-tag-active { 366 | /* margin-right: .25rem; */ 367 | /* background-color: var(--color-ui-selected); */ 368 | display: flex; 369 | justify-content: center; 370 | align-items: center; 371 | background-color: var(--color-bg); 372 | } 373 | 374 | .swatch-tag-idle { 375 | /* margin-right: .25rem; */ 376 | /* border-color: transparent; */ 377 | background-color: var(--color-bg); 378 | } 379 | 380 | .swatch-idle { 381 | border-color: transparent; 382 | } 383 | 384 | 385 | [class^="swatchPrefix"] { 386 | box-sizing: border-box; 387 | height: 1.25rem; 388 | transition: width 60ms var(--quart) 0ms 389 | opacity 80ms var(--quart) 20ms; 390 | user-select: none; 391 | } 392 | .swatchPrefix-Def { 393 | background-color: var(--color-bg); 394 | transition: width 60ms var(--quart) 0ms 395 | opacity 80ms var(--quart) 20ms; 396 | } 397 | 398 | 399 | .swatchSuffix { 400 | /* margin-left: .25rem; */ 401 | box-sizing: border-box; 402 | height: auto; 403 | transition: width 60ms var(--quart) 0ms; 404 | display: flex; 405 | justify-content: center; 406 | align-items: center; 407 | } 408 | 409 | .swatch-icon-min { 410 | margin-top: .25rem; 411 | } 412 | 413 | .swatch-icon { 414 | color: var(--color-font); 415 | font-size: .75rem; 416 | display: flex; 417 | justify-content: center; 418 | align-items: center; 419 | width: 100%; 420 | } 421 | -------------------------------------------------------------------------------- /host/AEFT/host.jsx: -------------------------------------------------------------------------------- 1 | var hasSelection = app.project.activeItem.selectedLayers.length > 0; 2 | var exist = app.project.items.length > 0; 3 | // Being run with SetInterval every 500ms, pretty light 4 | function scanSelection() { 5 | if (exist) { 6 | var activeItem = app.project.activeItem, result = []; 7 | if (activeItem != null && activeItem instanceof CompItem) { 8 | if (activeItem.selectedLayers.length > 0) { 9 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 10 | var layer = activeItem.selectedLayers[i]; 11 | if (layer.property("sourceText") === null) { 12 | result.push(layer.index); 13 | if (layer.selectedProperties.length > 0) { 14 | for (var e = 0; e < layer.selectedProperties.length; e++) { 15 | var prop = layer.selectedProperties[e]; 16 | result.push(prop.propertyIndex); 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | return result; 24 | } 25 | } 26 | function scanSelectionforColors() { 27 | var activeItem = app.project.activeItem, result = []; 28 | if (activeItem != null && activeItem instanceof CompItem) { 29 | if (activeItem.selectedLayers.length > 0) { 30 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 31 | var layer = activeItem.selectedLayers[i]; 32 | if (layer.property("sourceText") === null) { 33 | if (layer.selectedProperties.length > 0) { 34 | for (var e = 0; e < layer.selectedProperties.length; e++) { 35 | var prop = layer.selectedProperties[e]; 36 | result.push(scanColor(prop, [])); 37 | } 38 | } 39 | else { 40 | result.push(scanColor(layer, [])); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | return result; 47 | } 48 | function scanColor(propGroup, colorList) { 49 | var i, prop; 50 | for (i = 1; i <= propGroup.numProperties; i++) { 51 | prop = propGroup.property(i); 52 | if ((prop.propertyType === PropertyType.PROPERTY) 53 | && (/(ADBE\sVector\s(Fill|Stroke)\sColor)/i.test(prop.matchName))) { 54 | var temp = rgbToHex(prop.value[0] * 255, prop.value[1] * 255, prop.value[2] * 255); 55 | colorList.push(temp); 56 | } 57 | else if ((prop.propertyType === PropertyType.INDEXED_GROUP) || (prop.propertyType === PropertyType.NAMED_GROUP)) { 58 | scanColor(prop, colorList); 59 | } 60 | } 61 | return colorList; 62 | } 63 | function scanAllColors() { 64 | if (exist) { 65 | var activeItem = app.project.activeItem, result = []; 66 | if (activeItem != null && activeItem instanceof CompItem) { 67 | if (activeItem.layers.length > 0) { 68 | for (var i = 1; i <= activeItem.layers.length; i++) { 69 | var layer = activeItem.layers[i]; 70 | if (layer.property("sourceText") === null) { 71 | if (layer.selectedProperties.length > 0) { 72 | for (var e = 0; e < layer.selectedProperties.length; e++) { 73 | var prop = layer.selectedProperties[e]; 74 | result.push(scanColor(prop, [])); 75 | } 76 | } 77 | else { 78 | result.push(scanColor(layer, [])); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | return result; 85 | } 86 | } 87 | function clearSelection() { 88 | // app.project.activeItem.selection = ''; 89 | var activeItem = app.project.activeItem; 90 | if (activeItem != null && activeItem instanceof CompItem) { 91 | if (activeItem.selectedLayers.length > 0) { 92 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 93 | var layer = activeItem.selectedLayers[i]; 94 | if (layer.property("sourceText") === null) { 95 | if (layer.selectedProperties.length > 0) { 96 | for (var e = 0; e < layer.selectedProperties.length; e++) { 97 | var prop = layer.selectedProperties[e]; 98 | prop.selected = false; 99 | } 100 | } 101 | layer.selected = false; 102 | } 103 | } 104 | } 105 | } 106 | return true; 107 | } 108 | function startColorSelection(color, add) { 109 | if (add === void 0) { add = false; } 110 | if (exist) { 111 | if (!add) { 112 | clearSelection(); 113 | } 114 | var activeItem = app.project.activeItem; 115 | if (activeItem != null && activeItem instanceof CompItem) { 116 | if (activeItem.layers.length > 0) { 117 | for (var i = 1; i <= activeItem.layers.length; i++) { 118 | var layer = activeItem.layers[i]; 119 | selectColor(layer, color); 120 | } 121 | } 122 | } 123 | } 124 | } 125 | function selectColor(propGroup, color) { 126 | var i, prop; 127 | for (i = 1; i <= propGroup.numProperties; i++) { 128 | prop = propGroup.property(i); 129 | if ((prop.propertyType === PropertyType.PROPERTY) 130 | && (/(ADBE\sVector\s(Fill|Stroke)\sColor)/i.test(prop.matchName))) { 131 | var temp = rgbToHex(prop.value[0] * 255, prop.value[1] * 255, prop.value[2] * 255); 132 | if (temp == color) { 133 | prop.selected = true; 134 | } 135 | } 136 | else if ((prop.propertyType === PropertyType.INDEXED_GROUP) || (prop.propertyType === PropertyType.NAMED_GROUP)) { 137 | selectColor(prop, color); 138 | } 139 | } 140 | return true; 141 | } 142 | -------------------------------------------------------------------------------- /host/AEFT/host.ts: -------------------------------------------------------------------------------- 1 | var hasSelection = app.project.activeItem.selectedLayers.length > 0; 2 | var exist = app.project.items.length > 0; 3 | 4 | // Being run with SetInterval every 500ms, pretty light 5 | function scanSelection() { 6 | if (exist) { 7 | var activeItem = app.project.activeItem, result = []; 8 | if (activeItem != null && activeItem instanceof CompItem) { 9 | if (activeItem.selectedLayers.length > 0) { 10 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 11 | var layer = activeItem.selectedLayers[i]; 12 | if (layer.property("sourceText") === null) { 13 | result.push(layer.index); 14 | if (layer.selectedProperties.length > 0) { 15 | for (var e = 0; e < layer.selectedProperties.length; e++) { 16 | var prop = layer.selectedProperties[e]; 17 | result.push(prop.propertyIndex); 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | return result; 25 | } 26 | } 27 | 28 | function scanSelectionforColors() { 29 | var activeItem = app.project.activeItem, result = []; 30 | if (activeItem != null && activeItem instanceof CompItem) { 31 | if (activeItem.selectedLayers.length > 0) { 32 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 33 | var layer = activeItem.selectedLayers[i]; 34 | if (layer.property("sourceText") === null) { 35 | if (layer.selectedProperties.length > 0) { 36 | for (var e = 0; e < layer.selectedProperties.length; e++) { 37 | var prop = layer.selectedProperties[e]; 38 | result.push(scanColor(prop, [])); 39 | } 40 | } else { 41 | result.push(scanColor(layer, [])); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | return result; 48 | } 49 | 50 | function scanColor(propGroup, colorList) { 51 | var i, prop; 52 | for (i = 1; i <= propGroup.numProperties; i++) { 53 | prop = propGroup.property(i); 54 | if ((prop.propertyType === PropertyType.PROPERTY) 55 | && (/(ADBE\sVector\s(Fill|Stroke)\sColor)/i.test(prop.matchName))) { 56 | var temp = rgbToHex(prop.value[0] * 255, prop.value[1] * 255, prop.value[2] * 255); 57 | colorList.push(temp); 58 | } else if ((prop.propertyType === PropertyType.INDEXED_GROUP) || (prop.propertyType === PropertyType.NAMED_GROUP)) { 59 | scanColor(prop, colorList); 60 | } 61 | } 62 | return colorList; 63 | } 64 | 65 | function scanAllColors() { 66 | if (exist) { 67 | var activeItem = app.project.activeItem, result = []; 68 | if (activeItem != null && activeItem instanceof CompItem) { 69 | if (activeItem.layers.length > 0) { 70 | for (var i = 1; i <= activeItem.layers.length; i++) { 71 | var layer = activeItem.layers[i]; 72 | if (layer.property("sourceText") === null) { 73 | if (layer.selectedProperties.length > 0) { 74 | for (var e = 0; e < layer.selectedProperties.length; e++) { 75 | var prop = layer.selectedProperties[e]; 76 | result.push(scanColor(prop, [])); 77 | } 78 | } else { 79 | result.push(scanColor(layer, [])); 80 | } 81 | } 82 | } 83 | } 84 | } 85 | return result; 86 | } 87 | } 88 | 89 | function clearSelection() { 90 | // app.project.activeItem.selection = ''; 91 | var activeItem = app.project.activeItem; 92 | if (activeItem != null && activeItem instanceof CompItem) { 93 | if (activeItem.selectedLayers.length > 0) { 94 | for (var i = 0; i < activeItem.selectedLayers.length; i++) { 95 | var layer = activeItem.selectedLayers[i]; 96 | if (layer.property("sourceText") === null) { 97 | if (layer.selectedProperties.length > 0) { 98 | for (var e = 0; e < layer.selectedProperties.length; e++) { 99 | var prop = layer.selectedProperties[e]; 100 | prop.selected = false; 101 | } 102 | } 103 | layer.selected = false; 104 | } 105 | } 106 | } 107 | } 108 | return true; 109 | } 110 | 111 | function startColorSelection(color, add=false) { 112 | if (exist) { 113 | if (!add) { 114 | clearSelection(); 115 | } 116 | var activeItem = app.project.activeItem; 117 | if (activeItem != null && activeItem instanceof CompItem) { 118 | if (activeItem.layers.length > 0) { 119 | for (var i = 1; i <= activeItem.layers.length; i++) { 120 | var layer = activeItem.layers[i]; 121 | selectColor(layer, color); 122 | } 123 | } 124 | } 125 | } 126 | } 127 | 128 | function selectColor(propGroup, color) { 129 | var i, prop; 130 | for (i = 1; i <= propGroup.numProperties; i++) { 131 | prop = propGroup.property(i); 132 | if ((prop.propertyType === PropertyType.PROPERTY) 133 | && (/(ADBE\sVector\s(Fill|Stroke)\sColor)/i.test(prop.matchName))) { 134 | var temp = rgbToHex(prop.value[0] * 255, prop.value[1] * 255, prop.value[2] * 255); 135 | if (temp == color) { 136 | prop.selected = true; 137 | } 138 | } else if ((prop.propertyType === PropertyType.INDEXED_GROUP) || (prop.propertyType === PropertyType.NAMED_GROUP)) { 139 | selectColor(prop, color); 140 | } 141 | } 142 | return true; 143 | } -------------------------------------------------------------------------------- /host/AEFT/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outFile": "./host.jsx", 4 | "allowJs": true, 5 | "noLib": true, 6 | "module": "amd", 7 | "types": [ 8 | "types-for-adobe/AfterEffects/2018" 9 | ] 10 | }, 11 | "files": [ 12 | "host.ts" 13 | ], 14 | "exclude": [ 15 | "node_modules" 16 | ] 17 | } -------------------------------------------------------------------------------- /host/ILST/host.jsx: -------------------------------------------------------------------------------- 1 | var exist = app.documents.length > 0; 2 | // something 3 | function scanSelection() { 4 | var doc = app.documents[0]; 5 | var result = []; 6 | if (doc.pageItems.length) { 7 | for (var i = 0; i < doc.pageItems.length; i++) { 8 | var child = doc.pageItems[i]; 9 | if (child.selected) 10 | result.push(i); 11 | } 12 | } 13 | if (doc.textFrames.length) { 14 | for (var i = 0; i < doc.textFrames.length; i++) { 15 | var child = doc.textFrames[i]; 16 | if (child.selected) 17 | result.push(i); 18 | } 19 | } 20 | return result; 21 | } 22 | function scanFillActive() { 23 | return app.isFillActive(); 24 | } 25 | function setDefaultFill(hex) { 26 | var doc = app.documents[0]; 27 | doc.defaultFillColor = colorToIllustrator(hex); 28 | } 29 | function setDefaultStroke(hex) { 30 | var doc = app.documents[0]; 31 | doc.defaultStrokeColor = colorToIllustrator(hex); 32 | } 33 | function colorToIllustrator(newColor) { 34 | var type = app.documents[0].documentColorSpace; 35 | if (type == DocumentColorSpace.RGB) { 36 | var nColor = new RGBColor; 37 | nColor.red = hexToRgb(newColor).r; 38 | nColor.green = hexToRgb(newColor).g; 39 | nColor.blue = hexToRgb(newColor).b; 40 | } 41 | else if (type == DocumentColorSpace.CMYK) { 42 | var nColor = new CMYKColor; 43 | nColor.cyan = hexToCMYK(hex).c; 44 | nColor.magenta = hexToCMYK(hex).m; 45 | nColor.yellow = hexToCMYK(hex).y; 46 | nColor.black = hexToCMYK(hex).k; 47 | } 48 | return nColor; 49 | } 50 | function colorFromIllustrator() { 51 | if (app.isFillActive()) 52 | defaultColor = fillColorFromAI(); 53 | else 54 | defaultColor = strokeColorFromAI(); 55 | return defaultColor; 56 | } 57 | // alert(app.activeDocument.colorProfileName) 58 | function masterColorToAI(color) { 59 | var type = app.documents[0].documentColorSpace, result; 60 | if (type == DocumentColorSpace.RGB) { 61 | result = rgbToHex(color.red, color.green, color.blue); 62 | } 63 | else if (type == DocumentColorSpace.CMYK) { 64 | convert = app.convertSampleColor(ImageColorSpace.CMYK, [color.cyan, color.magenta, color.yellow, color.black], ImageColorSpace.RGB, ColorConvertPurpose.defaultpurpose); 65 | result = rgbToHex(convert[0], convert[1], convert[2]); 66 | } 67 | return result; 68 | } 69 | function validateArray(arrs) { 70 | var valid = true, anno = ''; 71 | if (!/./.test(arrs)) { 72 | valid = false; 73 | } 74 | else if (/\,/.test(arrs)) { 75 | arrs = arrs.split(','); 76 | } 77 | else { 78 | arrs = [arrs]; 79 | } 80 | if (valid) { 81 | return arrs; 82 | } 83 | else { 84 | return []; 85 | } 86 | // return valid; 87 | } 88 | function selectSameFill(color) { 89 | clearSelection(); 90 | var result = [], doc = app.documents[0]; 91 | for (var i = 0; i < doc.pageItems.length; i++) { 92 | var child = doc.pageItems[i]; 93 | if ((child.filled) && (color == masterColorToAI(child.fillColor))) 94 | child.selected = true; 95 | } 96 | } 97 | function selectSameStroke(color) { 98 | clearSelection(); 99 | var result = [], doc = app.documents[0]; 100 | for (var i = 0; i < doc.pageItems.length; i++) { 101 | var child = doc.pageItems[i]; 102 | if ((child.stroked) && (color == masterColorToAI(child.strokeColor))) 103 | child.selected = true; 104 | } 105 | } 106 | function addSameFill(color) { 107 | var result = [], doc = app.documents[0]; 108 | for (var i = 0; i < doc.pageItems.length; i++) { 109 | var child = doc.pageItems[i]; 110 | if ((child.filled) && (color == masterColorToAI(child.fillColor))) 111 | child.selected = true; 112 | } 113 | } 114 | function addSameStroke(color) { 115 | var result = [], doc = app.documents[0]; 116 | for (var i = 0; i < doc.pageItems.length; i++) { 117 | var child = doc.pageItems[i]; 118 | if ((child.stroked) && (color == masterColorToAI(child.strokeColor))) 119 | child.selected = true; 120 | } 121 | } 122 | function clearSelection() { 123 | app.selection = ''; 124 | } 125 | function scanSelectedColors(arrs) { 126 | var result = []; 127 | arrs = validateArray(arrs); 128 | if (arrs.length) { 129 | for (var i = 0; i < arrs.length; i++) { 130 | var target = Number(arrs[i]); 131 | var child = app.documents[0].pageItems[target]; 132 | if (child.selected) { 133 | var clone = { fill: 'none', stroke: 'none', index: target }; 134 | if (child.filled) { 135 | clone.fill = masterColorToAI(child.fillColor); 136 | } 137 | if (child.stroked) { 138 | clone.stroke = masterColorToAI(child.strokeColor); 139 | } 140 | } 141 | result.push(clone); 142 | } 143 | } 144 | return JSON.stringify(result); 145 | } 146 | function scanAllColors() { 147 | var result = [], doc = app.documents[0]; 148 | for (var i = 0; i < doc.pageItems.length; i++) { 149 | var child = doc.pageItems[i]; 150 | var clone = { fill: 'none', stroke: 'none', index: i }; 151 | if (child.filled) 152 | clone.fill = masterColorToAI(child.fillColor); 153 | if (child.stroked) 154 | clone.stroke = masterColorToAI(child.strokeColor); 155 | result.push(clone); 156 | } 157 | return JSON.stringify(result); 158 | } 159 | function scanFillStroke() { 160 | var doc = app.documents[0]; 161 | var child = { 162 | fill: { 163 | active: false, 164 | color: 'white', 165 | hasColor: false 166 | }, 167 | stroke: { 168 | active: false, 169 | color: 'white', 170 | hasColor: false 171 | } 172 | }; 173 | if (app.isStrokeActive()) { 174 | child.stroke.active = true; 175 | } 176 | else { 177 | child.fill.active = true; 178 | } 179 | try { 180 | child.fill.color = masterColorToAI(doc.defaultFillColor); 181 | } 182 | catch (e) { 183 | child.fill.color = 'white'; 184 | } 185 | try { 186 | child.stroke.color = masterColorToAI(doc.defaultStrokeColor); 187 | } 188 | catch (e) { 189 | child.stroke.color = 'white'; 190 | } 191 | if (!/white/.test(child.fill.color)) 192 | child.fill.hasColor = true; 193 | if (!/white/.test(child.stroke.color)) 194 | child.stroke.hasColor = true; 195 | return JSON.stringify(child); 196 | } 197 | // function swapStrokes(color1, color2) { 198 | // var result = [], doc = app.documents[0]; 199 | // for (var i = 0; i < doc.pageItems.length; i++) { 200 | // var child = doc.pageItems[i]; 201 | // if ((child.stroked) && (color1 == masterColorToAI(child.strokeColor))) 202 | // child.strokeColor = colorToIllustrator(color2); 203 | // if ((child.stroked) && (color2 == masterColorToAI(child.strokeColor))) 204 | // child.strokeColor = colorToIllustrator(color1); 205 | // } 206 | // } 207 | // 208 | // function swapFills(color1, color2) { 209 | // var result = [], doc = app.documents[0]; 210 | // for (var i = 0; i < doc.pageItems.length; i++) { 211 | // var child = doc.pageItems[i]; 212 | // if ((child.filled) && (color1 == masterColorToAI(child.fillColor))) 213 | // child.fillColor = colorToIllustrator(color2); 214 | // if ((child.filled) && (color2 == masterColorToAI(child.fillColor))) 215 | // child.fillColor = colorToIllustrator(color1); 216 | // } 217 | // } 218 | -------------------------------------------------------------------------------- /host/ILST/host.ts: -------------------------------------------------------------------------------- 1 | var exist = app.documents.length > 0; 2 | 3 | function scanSelection() { 4 | var doc = app.documents[0]; 5 | var result = []; 6 | if (doc.pageItems.length) { 7 | for (var i = 0; i < doc.pageItems.length; i++) { 8 | var child = doc.pageItems[i]; 9 | if (child.selected) 10 | result.push(i) 11 | } 12 | } 13 | if (doc.textFrames.length) { 14 | for (var i = 0; i < doc.textFrames.length; i++) { 15 | var child = doc.textFrames[i]; 16 | if (child.selected) 17 | result.push(i) 18 | } 19 | } 20 | return result; 21 | } 22 | 23 | function scanFillActive() { 24 | return app.isFillActive(); 25 | } 26 | 27 | function setDefaultFill(hex) { 28 | var doc = app.documents[0]; 29 | doc.defaultFillColor = colorToIllustrator(hex); 30 | } 31 | 32 | function setDefaultStroke(hex) { 33 | var doc = app.documents[0]; 34 | doc.defaultStrokeColor = colorToIllustrator(hex); 35 | } 36 | 37 | function colorToIllustrator(newColor){ 38 | var type = app.documents[0].documentColorSpace; 39 | if (type == DocumentColorSpace.RGB) { 40 | var nColor = new RGBColor; 41 | nColor.red = hexToRgb(newColor).r; 42 | nColor.green = hexToRgb(newColor).g; 43 | nColor.blue = hexToRgb(newColor).b; 44 | } else if (type == DocumentColorSpace.CMYK) { 45 | var nColor = new CMYKColor; 46 | nColor.cyan = hexToCMYK(hex).c; 47 | nColor.magenta = hexToCMYK(hex).m; 48 | nColor.yellow = hexToCMYK(hex).y; 49 | nColor.black = hexToCMYK(hex).k; 50 | } 51 | return nColor; 52 | } 53 | 54 | function colorFromIllustrator() { 55 | if (app.isFillActive()) 56 | defaultColor = fillColorFromAI(); 57 | else 58 | defaultColor = strokeColorFromAI(); 59 | return defaultColor; 60 | } 61 | 62 | // alert(app.activeDocument.colorProfileName) 63 | 64 | function masterColorToAI(color) { 65 | var type = app.documents[0].documentColorSpace, result; 66 | if (type == DocumentColorSpace.RGB) { 67 | result = rgbToHex(color.red, color.green, color.blue); 68 | } else if (type == DocumentColorSpace.CMYK) { 69 | convert = app.convertSampleColor(ImageColorSpace.CMYK, [color.cyan, color.magenta, color.yellow, color.black], ImageColorSpace.RGB, ColorConvertPurpose.defaultpurpose) 70 | result = rgbToHex(convert[0], convert[1], convert[2]); 71 | } 72 | return result; 73 | } 74 | 75 | function validateArray(arrs) { 76 | var valid = true, anno = ''; 77 | if (!/./.test(arrs)) { 78 | valid = false; 79 | } else if (/\,/.test(arrs)) { 80 | arrs = arrs.split(','); 81 | } else { 82 | arrs = [arrs]; 83 | } 84 | if (valid) { 85 | return arrs; 86 | } else { 87 | return []; 88 | } 89 | // return valid; 90 | } 91 | 92 | function selectSameFill(color) { 93 | clearSelection(); 94 | var result = [], doc = app.documents[0]; 95 | for (var i = 0; i < doc.pageItems.length; i++) { 96 | var child = doc.pageItems[i]; 97 | if ((child.filled) && (color == masterColorToAI(child.fillColor))) 98 | child.selected = true; 99 | } 100 | } 101 | 102 | function selectSameStroke(color) { 103 | clearSelection(); 104 | var result = [], doc = app.documents[0]; 105 | for (var i = 0; i < doc.pageItems.length; i++) { 106 | var child = doc.pageItems[i]; 107 | if ((child.stroked) && (color == masterColorToAI(child.strokeColor))) 108 | child.selected = true; 109 | } 110 | } 111 | 112 | function addSameFill(color) { 113 | var result = [], doc = app.documents[0]; 114 | for (var i = 0; i < doc.pageItems.length; i++) { 115 | var child = doc.pageItems[i]; 116 | if ((child.filled) && (color == masterColorToAI(child.fillColor))) 117 | child.selected = true; 118 | } 119 | } 120 | 121 | function addSameStroke(color) { 122 | var result = [], doc = app.documents[0]; 123 | for (var i = 0; i < doc.pageItems.length; i++) { 124 | var child = doc.pageItems[i]; 125 | if ((child.stroked) && (color == masterColorToAI(child.strokeColor))) 126 | child.selected = true; 127 | } 128 | } 129 | 130 | function clearSelection() { 131 | app.selection = ''; 132 | } 133 | 134 | function scanSelectedColors(arrs) { 135 | var result = []; 136 | arrs = validateArray(arrs); 137 | if (arrs.length) { 138 | for (var i = 0; i < arrs.length; i++) { 139 | var target = Number(arrs[i]); 140 | var child = app.documents[0].pageItems[target]; 141 | if (child.selected) { 142 | var clone = {fill: 'none', stroke: 'none', index: target} 143 | if (child.filled) { 144 | clone.fill = masterColorToAI(child.fillColor); 145 | } 146 | if (child.stroked) { 147 | clone.stroke = masterColorToAI(child.strokeColor); 148 | } 149 | } 150 | result.push(clone); 151 | } 152 | } 153 | return JSON.stringify(result); 154 | } 155 | 156 | 157 | 158 | function scanAllColors() { 159 | var result = [], doc = app.documents[0]; 160 | for (var i = 0; i < doc.pageItems.length; i++) { 161 | var child = doc.pageItems[i]; 162 | var clone = {fill: 'none', stroke: 'none', index: i} 163 | if (child.filled) 164 | clone.fill = masterColorToAI(child.fillColor); 165 | if (child.stroked) 166 | clone.stroke = masterColorToAI(child.strokeColor); 167 | result.push(clone); 168 | } 169 | return JSON.stringify(result); 170 | } 171 | 172 | function scanFillStroke() { 173 | var doc = app.documents[0]; 174 | var child = { 175 | fill: { 176 | active: false, 177 | color: 'white', 178 | hasColor: false, 179 | }, 180 | stroke: { 181 | active: false, 182 | color: 'white', 183 | hasColor: false, 184 | } 185 | }; 186 | if (app.isStrokeActive()) {child.stroke.active = true;} 187 | else {child.fill.active = true;} 188 | 189 | try { child.fill.color = masterColorToAI(doc.defaultFillColor);} 190 | catch(e) { child.fill.color = 'white';} 191 | try { child.stroke.color = masterColorToAI(doc.defaultStrokeColor);} 192 | catch(e) { child.stroke.color = 'white';} 193 | 194 | if (!/white/.test(child.fill.color)) 195 | child.fill.hasColor = true; 196 | if (!/white/.test(child.stroke.color)) 197 | child.stroke.hasColor = true; 198 | 199 | return JSON.stringify(child); 200 | } 201 | 202 | // function swapStrokes(color1, color2) { 203 | // var result = [], doc = app.documents[0]; 204 | // for (var i = 0; i < doc.pageItems.length; i++) { 205 | // var child = doc.pageItems[i]; 206 | // if ((child.stroked) && (color1 == masterColorToAI(child.strokeColor))) 207 | // child.strokeColor = colorToIllustrator(color2); 208 | // if ((child.stroked) && (color2 == masterColorToAI(child.strokeColor))) 209 | // child.strokeColor = colorToIllustrator(color1); 210 | // } 211 | // } 212 | // 213 | // function swapFills(color1, color2) { 214 | // var result = [], doc = app.documents[0]; 215 | // for (var i = 0; i < doc.pageItems.length; i++) { 216 | // var child = doc.pageItems[i]; 217 | // if ((child.filled) && (color1 == masterColorToAI(child.fillColor))) 218 | // child.fillColor = colorToIllustrator(color2); 219 | // if ((child.filled) && (color2 == masterColorToAI(child.fillColor))) 220 | // child.fillColor = colorToIllustrator(color1); 221 | // } 222 | // } 223 | -------------------------------------------------------------------------------- /host/ILST/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outFile": "./host.jsx", 4 | "allowJs": true, 5 | "noLib": true, 6 | "module": "amd", 7 | "types": [ 8 | "types-for-adobe/illustrator/2015.3" 9 | ] 10 | }, 11 | "files": [ 12 | "host.ts" 13 | ], 14 | "exclude": [ 15 | "node_modules" 16 | ] 17 | } -------------------------------------------------------------------------------- /host/PHXS/host.jsx: -------------------------------------------------------------------------------- 1 | // Compile on save successful 2 | function scanFGBG() { 3 | // alert('hello') 4 | return 'hello'; 5 | } 6 | function scanAllColors() { 7 | return "#" + app.foregroundColor.rgb.hexValue + ",#" + app.backgroundColor.rgb.hexValue; 8 | } 9 | function setFG(color) { 10 | app.foregroundColor.rgb.hexValue = color; 11 | } 12 | function setBG(color) { 13 | app.backgroundColor.rgb.hexValue = color; 14 | } 15 | function scanFGBG() { 16 | var doc = app.documents[0]; 17 | var child = { 18 | fill: { 19 | active: true, 20 | color: 'white', 21 | hasColor: false 22 | }, 23 | stroke: { 24 | active: false, 25 | color: 'white', 26 | hasColor: false 27 | } 28 | }; 29 | try { 30 | child.fill.color = '#' + app.foregroundColor.rgb.hexValue; 31 | } 32 | catch (e) { 33 | child.fill.color = 'white'; 34 | } 35 | try { 36 | child.stroke.color = '#' + app.backgroundColor.rgb.hexValue; 37 | } 38 | catch (e) { 39 | child.stroke.color = 'white'; 40 | } 41 | if (!/white/.test(child.fill.color)) 42 | child.fill.hasColor = true; 43 | if (!/white/.test(child.stroke.color)) 44 | child.stroke.hasColor = true; 45 | return JSON.stringify(child); 46 | } 47 | -------------------------------------------------------------------------------- /host/PHXS/host.ts: -------------------------------------------------------------------------------- 1 | function scanFGBG() { 2 | // alert('hello') 3 | return 'hello'; 4 | } 5 | 6 | function scanAllColors() { 7 | return "#" + app.foregroundColor.rgb.hexValue + ",#" + app.backgroundColor.rgb.hexValue; 8 | } 9 | 10 | function setFG(color) { 11 | app.foregroundColor.rgb.hexValue = color; 12 | } 13 | 14 | function setBG(color) { 15 | app.backgroundColor.rgb.hexValue = color; 16 | } 17 | 18 | function scanFGBG() { 19 | var doc = app.documents[0]; 20 | var child = { 21 | fill: { 22 | active: true, 23 | color: 'white', 24 | hasColor: false, 25 | }, 26 | stroke: { 27 | active: false, 28 | color: 'white', 29 | hasColor: false, 30 | } 31 | } 32 | try { child.fill.color = '#' + app.foregroundColor.rgb.hexValue; } 33 | catch (e) { child.fill.color = 'white'; } 34 | try { child.stroke.color = '#' + app.backgroundColor.rgb.hexValue; } 35 | catch (e) { child.stroke.color = 'white'; } 36 | 37 | if (!/white/.test(child.fill.color)) 38 | child.fill.hasColor = true; 39 | if (!/white/.test(child.stroke.color)) 40 | child.stroke.hasColor = true; 41 | return JSON.stringify(child); 42 | } -------------------------------------------------------------------------------- /host/PHXS/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outFile": "./host.jsx", 4 | "allowJs": true, 5 | "noLib": true, 6 | "module": "amd", 7 | "types": [ 8 | "types-for-adobe/Photoshop/2015.5" 9 | ] 10 | }, 11 | "files": [ 12 | "host.ts" 13 | ], 14 | "exclude": [ 15 | "node_modules" 16 | ] 17 | } -------------------------------------------------------------------------------- /host/universal/Console.jsx: -------------------------------------------------------------------------------- 1 | JSXEvent('Loading...', 'console'); 2 | 3 | function runScript(path) { 4 | try { 5 | $.evalFile(path) 6 | } catch (e) { 7 | JSXEvent(e.name + "," + e.line + "," + e + "," + e.message, "console") 8 | } 9 | } 10 | 11 | function JSXEvent(payload, eventType) { 12 | try { 13 | var xLib = new ExternalObject("lib:\PlugPlugExternalObject"); 14 | } catch (e) { 15 | JSXEvent(e, 'console') 16 | } 17 | if (xLib) { 18 | var eventObj = new CSXSEvent(); 19 | eventObj.type = eventType; 20 | eventObj.data = payload; 21 | eventObj.dispatch(); 22 | } 23 | return; 24 | } 25 | 26 | var console = { 27 | log : function(data) {JSXEvent(data, 'console')} 28 | }; 29 | 30 | /// https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb 31 | function componentToHex(c) { 32 | var hex = c.toString(16); 33 | return hex.length == 1 ? "0" + hex : hex; 34 | } 35 | 36 | function rgbToHex(r, g, b) { 37 | return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b); 38 | } 39 | 40 | function hexToRgb(hex) { 41 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 42 | return result ? { 43 | r: parseInt(result[1], 16), 44 | g: parseInt(result[2], 16), 45 | b: parseInt(result[3], 16) 46 | } : null; 47 | } 48 | 49 | // https://github.com/Qix-/color-convert/blob/HEAD/conversions.js 50 | function hexToCMYK(hex) { 51 | var rgb = hexToRgb(hex); 52 | var r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255; 53 | var c, m, y, k; 54 | 55 | k = Math.min(1 - r, 1 - g, 1 - b); 56 | c = (1 - r - k) / (1 - k) || 0; 57 | m = (1 - g - k) / (1 - k) || 0; 58 | y = (1 - b - k) / (1 - k) || 0; 59 | var color = { 60 | c: c * 100, 61 | m: m * 100, 62 | y: y * 100, 63 | k: k * 100, 64 | } 65 | // return [c * 100, m * 100, y * 100, k * 100]; 66 | return color; 67 | }; 68 | 69 | function cmykToHex(color) { 70 | var convert = cmykToRGB2(color.cyan, color.magenta, color.yellow, color.black); 71 | var mirror = [convert.r, convert.g, convert.b] 72 | return rgbToHex(convert[0], convert[1], convert[2]) 73 | } 74 | 75 | function cmykToRGB2(C,M,Y,K) { 76 | // alert(C + " " + M + " " + Y + " " + K) 77 | var r = 255 * (1 - C) * (1 - K); 78 | var g = 255 * (1 - M) * (1 - K); 79 | var b = 255 * (1 - Y) * (1 - K); 80 | return [r,g,b] 81 | } 82 | 83 | // // https://www.standardabweichung.de/code/javascript/cmyk-rgb-conversion-javascript 84 | function cmykToRGB(color){ 85 | color.cyan = (color.cyan / 100); 86 | color.magenta = (color.magenta / 100); 87 | color.yellow = (color.yellow / 100); 88 | color.black = (color.black / 100); 89 | 90 | color.cyan = color.cyan * (1 - color.black) + color.black; 91 | color.magenta = color.magenta * (1 - color.black) + color.black; 92 | color.yellow = color.yellow * (1 - color.black) + color.black; 93 | 94 | var r = 1 - color.cyan; 95 | var g = 1 - color.magenta; 96 | var b = 1 - color.yellow; 97 | 98 | return { 99 | r: r, 100 | g: g, 101 | b: b 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /host/universal/json2.jsx: -------------------------------------------------------------------------------- 1 | // https://github.com/douglascrockford/JSON-js/blob/master/json2.js 2 | // json2.js 3 | // 2017-06-12 4 | // Public Domain. 5 | // NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 6 | 7 | // USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 8 | // NOT CONTROL. 9 | 10 | // This file creates a global JSON object containing two methods: stringify 11 | // and parse. This file provides the ES5 JSON capability to ES3 systems. 12 | // If a project might run on IE8 or earlier, then this file should be included. 13 | // This file does nothing on ES5 systems. 14 | 15 | // JSON.stringify(value, replacer, space) 16 | // value any JavaScript value, usually an object or array. 17 | // replacer an optional parameter that determines how object 18 | // values are stringified for objects. It can be a 19 | // function or an array of strings. 20 | // space an optional parameter that specifies the indentation 21 | // of nested structures. If it is omitted, the text will 22 | // be packed without extra whitespace. If it is a number, 23 | // it will specify the number of spaces to indent at each 24 | // level. If it is a string (such as "\t" or " "), 25 | // it contains the characters used to indent at each level. 26 | // This method produces a JSON text from a JavaScript value. 27 | // When an object value is found, if the object contains a toJSON 28 | // method, its toJSON method will be called and the result will be 29 | // stringified. A toJSON method does not serialize: it returns the 30 | // value represented by the name/value pair that should be serialized, 31 | // or undefined if nothing should be serialized. The toJSON method 32 | // will be passed the key associated with the value, and this will be 33 | // bound to the value. 34 | 35 | // For example, this would serialize Dates as ISO strings. 36 | 37 | // Date.prototype.toJSON = function (key) { 38 | // function f(n) { 39 | // // Format integers to have at least two digits. 40 | // return (n < 10) 41 | // ? "0" + n 42 | // : n; 43 | // } 44 | // return this.getUTCFullYear() + "-" + 45 | // f(this.getUTCMonth() + 1) + "-" + 46 | // f(this.getUTCDate()) + "T" + 47 | // f(this.getUTCHours()) + ":" + 48 | // f(this.getUTCMinutes()) + ":" + 49 | // f(this.getUTCSeconds()) + "Z"; 50 | // }; 51 | 52 | // You can provide an optional replacer method. It will be passed the 53 | // key and value of each member, with this bound to the containing 54 | // object. The value that is returned from your method will be 55 | // serialized. If your method returns undefined, then the member will 56 | // be excluded from the serialization. 57 | 58 | // If the replacer parameter is an array of strings, then it will be 59 | // used to select the members to be serialized. It filters the results 60 | // such that only members with keys listed in the replacer array are 61 | // stringified. 62 | 63 | // Values that do not have JSON representations, such as undefined or 64 | // functions, will not be serialized. Such values in objects will be 65 | // dropped; in arrays they will be replaced with null. You can use 66 | // a replacer function to replace those with JSON values. 67 | 68 | // JSON.stringify(undefined) returns undefined. 69 | 70 | // The optional space parameter produces a stringification of the 71 | // value that is filled with line breaks and indentation to make it 72 | // easier to read. 73 | 74 | // If the space parameter is a non-empty string, then that string will 75 | // be used for indentation. If the space parameter is a number, then 76 | // the indentation will be that many spaces. 77 | 78 | // Example: 79 | 80 | // text = JSON.stringify(["e", {pluribus: "unum"}]); 81 | // // text is '["e",{"pluribus":"unum"}]' 82 | 83 | // text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t"); 84 | // // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 85 | 86 | // text = JSON.stringify([new Date()], function (key, value) { 87 | // return this[key] instanceof Date 88 | // ? "Date(" + this[key] + ")" 89 | // : value; 90 | // }); 91 | // // text is '["Date(---current time---)"]' 92 | 93 | // JSON.parse(text, reviver) 94 | // This method parses a JSON text to produce an object or array. 95 | // It can throw a SyntaxError exception. 96 | 97 | // The optional reviver parameter is a function that can filter and 98 | // transform the results. It receives each of the keys and values, 99 | // and its return value is used instead of the original value. 100 | // If it returns what it received, then the structure is not modified. 101 | // If it returns undefined then the member is deleted. 102 | 103 | // Example: 104 | 105 | // // Parse the text. Values that look like ISO date strings will 106 | // // be converted to Date objects. 107 | 108 | // myData = JSON.parse(text, function (key, value) { 109 | // var a; 110 | // if (typeof value === "string") { 111 | // a = 112 | // /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 113 | // if (a) { 114 | // return new Date(Date.UTC( 115 | // +a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6] 116 | // )); 117 | // } 118 | // return value; 119 | // } 120 | // }); 121 | 122 | // myData = JSON.parse( 123 | // "[\"Date(09/09/2001)\"]", 124 | // function (key, value) { 125 | // var d; 126 | // if ( 127 | // typeof value === "string" 128 | // && value.slice(0, 5) === "Date(" 129 | // && value.slice(-1) === ")" 130 | // ) { 131 | // d = new Date(value.slice(5, -1)); 132 | // if (d) { 133 | // return d; 134 | // } 135 | // } 136 | // return value; 137 | // } 138 | // ); 139 | 140 | // This is a reference implementation. You are free to copy, modify, or 141 | // redistribute. 142 | 143 | /*jslint 144 | eval, for, this 145 | */ 146 | 147 | /*property 148 | JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, 149 | getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, 150 | lastIndex, length, parse, prototype, push, replace, slice, stringify, 151 | test, toJSON, toString, valueOf 152 | */ 153 | 154 | 155 | // Create a JSON object only if one does not already exist. We create the 156 | // methods in a closure to avoid creating global variables. 157 | 158 | if (typeof JSON !== "object") { 159 | JSON = {}; 160 | } 161 | 162 | (function () { 163 | "use strict"; 164 | 165 | var rx_one = /^[\],:{}\s]*$/; 166 | var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g; 167 | var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g; 168 | var rx_four = /(?:^|:|,)(?:\s*\[)+/g; 169 | var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; 170 | var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; 171 | 172 | function f(n) { 173 | // Format integers to have at least two digits. 174 | return (n < 10) 175 | ? "0" + n 176 | : n; 177 | } 178 | 179 | function this_value() { 180 | return this.valueOf(); 181 | } 182 | 183 | if (typeof Date.prototype.toJSON !== "function") { 184 | 185 | Date.prototype.toJSON = function () { 186 | 187 | return isFinite(this.valueOf()) 188 | ? ( 189 | this.getUTCFullYear() 190 | + "-" 191 | + f(this.getUTCMonth() + 1) 192 | + "-" 193 | + f(this.getUTCDate()) 194 | + "T" 195 | + f(this.getUTCHours()) 196 | + ":" 197 | + f(this.getUTCMinutes()) 198 | + ":" 199 | + f(this.getUTCSeconds()) 200 | + "Z" 201 | ) 202 | : null; 203 | }; 204 | 205 | Boolean.prototype.toJSON = this_value; 206 | Number.prototype.toJSON = this_value; 207 | String.prototype.toJSON = this_value; 208 | } 209 | 210 | var gap; 211 | var indent; 212 | var meta; 213 | var rep; 214 | 215 | 216 | function quote(string) { 217 | 218 | // If the string contains no control characters, no quote characters, and no 219 | // backslash characters, then we can safely slap some quotes around it. 220 | // Otherwise we must also replace the offending characters with safe escape 221 | // sequences. 222 | 223 | rx_escapable.lastIndex = 0; 224 | return rx_escapable.test(string) 225 | ? "\"" + string.replace(rx_escapable, function (a) { 226 | var c = meta[a]; 227 | return typeof c === "string" 228 | ? c 229 | : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4); 230 | }) + "\"" 231 | : "\"" + string + "\""; 232 | } 233 | 234 | 235 | function str(key, holder) { 236 | 237 | // Produce a string from holder[key]. 238 | 239 | var i; // The loop counter. 240 | var k; // The member key. 241 | var v; // The member value. 242 | var length; 243 | var mind = gap; 244 | var partial; 245 | var value = holder[key]; 246 | 247 | // If the value has a toJSON method, call it to obtain a replacement value. 248 | 249 | if ( 250 | value 251 | && typeof value === "object" 252 | && typeof value.toJSON === "function" 253 | ) { 254 | value = value.toJSON(key); 255 | } 256 | 257 | // If we were called with a replacer function, then call the replacer to 258 | // obtain a replacement value. 259 | 260 | if (typeof rep === "function") { 261 | value = rep.call(holder, key, value); 262 | } 263 | 264 | // What happens next depends on the value's type. 265 | 266 | switch (typeof value) { 267 | case "string": 268 | return quote(value); 269 | 270 | case "number": 271 | 272 | // JSON numbers must be finite. Encode non-finite numbers as null. 273 | 274 | return (isFinite(value)) 275 | ? String(value) 276 | : "null"; 277 | 278 | case "boolean": 279 | case "null": 280 | 281 | // If the value is a boolean or null, convert it to a string. Note: 282 | // typeof null does not produce "null". The case is included here in 283 | // the remote chance that this gets fixed someday. 284 | 285 | return String(value); 286 | 287 | // If the type is "object", we might be dealing with an object or an array or 288 | // null. 289 | 290 | case "object": 291 | 292 | // Due to a specification blunder in ECMAScript, typeof null is "object", 293 | // so watch out for that case. 294 | 295 | if (!value) { 296 | return "null"; 297 | } 298 | 299 | // Make an array to hold the partial results of stringifying this object value. 300 | 301 | gap += indent; 302 | partial = []; 303 | 304 | // Is the value an array? 305 | 306 | if (Object.prototype.toString.apply(value) === "[object Array]") { 307 | 308 | // The value is an array. Stringify every element. Use null as a placeholder 309 | // for non-JSON values. 310 | 311 | length = value.length; 312 | for (i = 0; i < length; i += 1) { 313 | partial[i] = str(i, value) || "null"; 314 | } 315 | 316 | // Join all of the elements together, separated with commas, and wrap them in 317 | // brackets. 318 | 319 | v = partial.length === 0 320 | ? "[]" 321 | : gap 322 | ? ( 323 | "[\n" 324 | + gap 325 | + partial.join(",\n" + gap) 326 | + "\n" 327 | + mind 328 | + "]" 329 | ) 330 | : "[" + partial.join(",") + "]"; 331 | gap = mind; 332 | return v; 333 | } 334 | 335 | // If the replacer is an array, use it to select the members to be stringified. 336 | 337 | if (rep && typeof rep === "object") { 338 | length = rep.length; 339 | for (i = 0; i < length; i += 1) { 340 | if (typeof rep[i] === "string") { 341 | k = rep[i]; 342 | v = str(k, value); 343 | if (v) { 344 | partial.push(quote(k) + ( 345 | (gap) 346 | ? ": " 347 | : ":" 348 | ) + v); 349 | } 350 | } 351 | } 352 | } else { 353 | 354 | // Otherwise, iterate through all of the keys in the object. 355 | 356 | for (k in value) { 357 | if (Object.prototype.hasOwnProperty.call(value, k)) { 358 | v = str(k, value); 359 | if (v) { 360 | partial.push(quote(k) + ( 361 | (gap) 362 | ? ": " 363 | : ":" 364 | ) + v); 365 | } 366 | } 367 | } 368 | } 369 | 370 | // Join all of the member texts together, separated with commas, 371 | // and wrap them in braces. 372 | 373 | v = partial.length === 0 374 | ? "{}" 375 | : gap 376 | ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" 377 | : "{" + partial.join(",") + "}"; 378 | gap = mind; 379 | return v; 380 | } 381 | } 382 | 383 | // If the JSON object does not yet have a stringify method, give it one. 384 | 385 | if (typeof JSON.stringify !== "function") { 386 | meta = { // table of character substitutions 387 | "\b": "\\b", 388 | "\t": "\\t", 389 | "\n": "\\n", 390 | "\f": "\\f", 391 | "\r": "\\r", 392 | "\"": "\\\"", 393 | "\\": "\\\\" 394 | }; 395 | JSON.stringify = function (value, replacer, space) { 396 | 397 | // The stringify method takes a value and an optional replacer, and an optional 398 | // space parameter, and returns a JSON text. The replacer can be a function 399 | // that can replace values, or an array of strings that will select the keys. 400 | // A default replacer method can be provided. Use of the space parameter can 401 | // produce text that is more easily readable. 402 | 403 | var i; 404 | gap = ""; 405 | indent = ""; 406 | 407 | // If the space parameter is a number, make an indent string containing that 408 | // many spaces. 409 | 410 | if (typeof space === "number") { 411 | for (i = 0; i < space; i += 1) { 412 | indent += " "; 413 | } 414 | 415 | // If the space parameter is a string, it will be used as the indent string. 416 | 417 | } else if (typeof space === "string") { 418 | indent = space; 419 | } 420 | 421 | // If there is a replacer, it must be a function or an array. 422 | // Otherwise, throw an error. 423 | 424 | rep = replacer; 425 | if (replacer && typeof replacer !== "function" && ( 426 | typeof replacer !== "object" 427 | || typeof replacer.length !== "number" 428 | )) { 429 | throw new Error("JSON.stringify"); 430 | } 431 | 432 | // Make a fake root object containing our value under the key of "". 433 | // Return the result of stringifying the value. 434 | 435 | return str("", {"": value}); 436 | }; 437 | } 438 | 439 | 440 | // If the JSON object does not yet have a parse method, give it one. 441 | 442 | if (typeof JSON.parse !== "function") { 443 | JSON.parse = function (text, reviver) { 444 | 445 | // The parse method takes a text and an optional reviver function, and returns 446 | // a JavaScript value if the text is a valid JSON text. 447 | 448 | var j; 449 | 450 | function walk(holder, key) { 451 | 452 | // The walk method is used to recursively walk the resulting structure so 453 | // that modifications can be made. 454 | 455 | var k; 456 | var v; 457 | var value = holder[key]; 458 | if (value && typeof value === "object") { 459 | for (k in value) { 460 | if (Object.prototype.hasOwnProperty.call(value, k)) { 461 | v = walk(value, k); 462 | if (v !== undefined) { 463 | value[k] = v; 464 | } else { 465 | delete value[k]; 466 | } 467 | } 468 | } 469 | } 470 | return reviver.call(holder, key, value); 471 | } 472 | 473 | 474 | // Parsing happens in four stages. In the first stage, we replace certain 475 | // Unicode characters with escape sequences. JavaScript handles many characters 476 | // incorrectly, either silently deleting them, or treating them as line endings. 477 | 478 | text = String(text); 479 | rx_dangerous.lastIndex = 0; 480 | if (rx_dangerous.test(text)) { 481 | text = text.replace(rx_dangerous, function (a) { 482 | return ( 483 | "\\u" 484 | + ("0000" + a.charCodeAt(0).toString(16)).slice(-4) 485 | ); 486 | }); 487 | } 488 | 489 | // In the second stage, we run the text against regular expressions that look 490 | // for non-JSON patterns. We are especially concerned with "()" and "new" 491 | // because they can cause invocation, and "=" because it can cause mutation. 492 | // But just to be safe, we want to reject all unexpected forms. 493 | 494 | // We split the second stage into 4 regexp operations in order to work around 495 | // crippling inefficiencies in IE's and Safari's regexp engines. First we 496 | // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we 497 | // replace all simple value tokens with "]" characters. Third, we delete all 498 | // open brackets that follow a colon or comma or that begin the text. Finally, 499 | // we look to see that the remaining characters are only whitespace or "]" or 500 | // "," or ":" or "{" or "}". If that is so, then the text is safe for eval. 501 | 502 | if ( 503 | rx_one.test( 504 | text 505 | .replace(rx_two, "@") 506 | .replace(rx_three, "]") 507 | .replace(rx_four, "") 508 | ) 509 | ) { 510 | 511 | // In the third stage we use the eval function to compile the text into a 512 | // JavaScript structure. The "{" operator is subject to a syntactic ambiguity 513 | // in JavaScript: it can begin a block or an object literal. We wrap the text 514 | // in parens to eliminate the ambiguity. 515 | 516 | j = eval("(" + text + ")"); 517 | 518 | // In the optional fourth stage, we recursively walk the new structure, passing 519 | // each name/value pair to a reviver function for possible transformation. 520 | 521 | return (typeof reviver === "function") 522 | ? walk({"": j}, "") 523 | : j; 524 | } 525 | 526 | // If the text is not JSON parseable, then a SyntaxError is thrown. 527 | 528 | throw new SyntaxError("JSON.parse"); 529 | }; 530 | } 531 | }()); 532 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protoColors", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "types-for-adobe": { 8 | "version": "github:pravdomil/types-for-adobe#981aaf9569475a096a7358b1e4936018b2340e33", 9 | "from": "github:pravdomil/types-for-adobe" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "protoColors", 3 | "version": "1.0.0", 4 | "description": "``` bash\r # ...User/AppData/Roaming/Adobe/CEP/extensions\r git clone https://github.com/Inventsable/protoColors.git\r ```", 5 | "main": "index.js", 6 | "dependencies": { 7 | "types-for-adobe": "github:pravdomil/types-for-adobe" 8 | }, 9 | "devDependencies": {}, 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1", 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/Inventsable/protoColors.git" 16 | }, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/Inventsable/protoColors/issues" 22 | }, 23 | "homepage": "https://github.com/Inventsable/protoColors#readme" 24 | } 25 | -------------------------------------------------------------------------------- /sandbox/fillstroke.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/sandbox/fillstroke.ai -------------------------------------------------------------------------------- /sandbox/font.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/sandbox/font.ai -------------------------------------------------------------------------------- /sandbox/mock.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/sandbox/mock.ai -------------------------------------------------------------------------------- /sandbox/spectrum.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Inventsable/protoColors/fdd75777e1753d722df90d6cbf2899451a92b514/sandbox/spectrum.ai -------------------------------------------------------------------------------- /todo.md: -------------------------------------------------------------------------------- 1 | # todo 2 | 3 | * Textframes don't respond to SelectSame -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | // "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | 38 | /* Module Resolution Options */ 39 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 40 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 46 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | 49 | /* Source Map Options */ 50 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 51 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 52 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 53 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 54 | 55 | /* Experimental Options */ 56 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 57 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 58 | } 59 | } --------------------------------------------------------------------------------