├── README.md ├── css ├── prism-themes │ └── prism-onedark.css └── styles.css ├── index.html ├── lib ├── constants.js └── prism.js ├── main.js └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # Parse Action Descriptor Code 2 | [![npm-image](https://img.shields.io/badge/parse--action--descriptor--code-v1.1.0-09bc00.svg)](https://github.com/JavierAroche/parse-action-descriptor-code) 3 | 4 | ## Description 5 | Parse your Photoshop Action Descriptor code from the Scripting Listener into a more readable format, or into a flexible function. 6 | 7 | ## Install 8 | * Git clone this repository 9 | * Open .`/index.html` 10 | 11 | ## Usage 12 | Open [parse-action-descriptor-code](https://javieraroche.github.io/parse-action-descriptor-code/) 13 | 14 | Copy and paste your output from the Scripting Listener into the `Input` text area. Select the desired function. Click `Parse`, and your parsed code will be shown in the `Output` text area. 15 | 16 | ## Example 17 | Input from the Scripting Listener (`Make new document`) 18 | ```javascript 19 | var idMk = charIDToTypeID( "Mk " ); 20 | var desc36 = new ActionDescriptor(); 21 | var idNw = charIDToTypeID( "Nw " ); 22 | var desc37 = new ActionDescriptor(); 23 | var idNm = charIDToTypeID( "Nm " ); 24 | desc37.putString( idNm, """New File""" ); 25 | var idartboard = stringIDToTypeID( "artboard" ); 26 | desc37.putBoolean( idartboard, false ); 27 | var idMd = charIDToTypeID( "Md " ); 28 | var idRGBM = charIDToTypeID( "RGBM" ); 29 | desc37.putClass( idMd, idRGBM ); 30 | var idWdth = charIDToTypeID( "Wdth" ); 31 | var idRlt = charIDToTypeID( "#Rlt" ); 32 | desc37.putUnitDouble( idWdth, idRlt, 480.000000 ); 33 | var idHght = charIDToTypeID( "Hght" ); 34 | var idRlt = charIDToTypeID( "#Rlt" ); 35 | desc37.putUnitDouble( idHght, idRlt, 360.000000 ); 36 | var idRslt = charIDToTypeID( "Rslt" ); 37 | var idRsl = charIDToTypeID( "#Rsl" ); 38 | desc37.putUnitDouble( idRslt, idRsl, 300.000000 ); 39 | var idpixelScaleFactor = stringIDToTypeID( "pixelScaleFactor" ); 40 | desc37.putDouble( idpixelScaleFactor, 1.000000 ); 41 | var idFl = charIDToTypeID( "Fl " ); 42 | var idFl = charIDToTypeID( "Fl " ); 43 | var idTrns = charIDToTypeID( "Trns" ); 44 | desc37.putEnumerated( idFl, idFl, idTrns ); 45 | var idDpth = charIDToTypeID( "Dpth" ); 46 | desc37.putInteger( idDpth, 8 ); 47 | var idprofile = stringIDToTypeID( "profile" ); 48 | desc37.putString( idprofile, """sRGB IEC61966-2.1""" ); 49 | var idDcmn = charIDToTypeID( "Dcmn" ); 50 | desc36.putObject( idNw, idDcmn, desc37 ); 51 | var idDocI = charIDToTypeID( "DocI" ); 52 | desc36.putInteger( idDocI, 208 ); 53 | executeAction( idMk, desc36, DialogModes.NO ); 54 | ``` 55 | 56 | **Clean JSX | clean variables ✔︎ clean params ✔︎** 57 | ```javascript 58 | var desc1 = new ActionDescriptor(); 59 | var desc2 = new ActionDescriptor(); 60 | desc2.putString( charIDToTypeID( "Nm " ), """New File""" ); 61 | desc2.putBoolean( stringIDToTypeID( "artboard" ), false ); 62 | desc2.putClass( charIDToTypeID( "Md " ), charIDToTypeID( "RGBM" ) ); 63 | desc2.putUnitDouble( charIDToTypeID( "Wdth" ), charIDToTypeID( "#Rlt" ), 480.000000 ); 64 | desc2.putUnitDouble( charIDToTypeID( "Hght" ), charIDToTypeID( "#Rlt" ), 360.000000 ); 65 | desc2.putUnitDouble( charIDToTypeID( "Rslt" ), charIDToTypeID( "#Rsl" ), 300.000000 ); 66 | desc2.putDouble( stringIDToTypeID( "pixelScaleFactor" ), 1.000000 ); 67 | desc2.putEnumerated( charIDToTypeID( "Fl " ), charIDToTypeID( "Fl " ), charIDToTypeID( "Trns" ) ); 68 | desc2.putInteger( charIDToTypeID( "Dpth" ), 8 ); 69 | desc2.putString( stringIDToTypeID( "profile" ), """sRGB IEC61966-2.1""" ); 70 | desc1.putObject( charIDToTypeID( "Nw " ), charIDToTypeID( "Dcmn" ), desc2 ); 71 | desc1.putInteger( charIDToTypeID( "DocI" ), 208 ); 72 | executeAction( charIDToTypeID( "Mk " ), desc1, DialogModes.NO ); 73 | ``` 74 | **Sort IDs | clean variables ✔︎ clean params ✔︎** 75 | ```javascript 76 | var idMk = charIDToTypeID( "Mk " ); 77 | var idNw = charIDToTypeID( "Nw " ); 78 | var idNm = charIDToTypeID( "Nm " ); 79 | var idartboard = stringIDToTypeID( "artboard" ); 80 | var idMd = charIDToTypeID( "Md " ); 81 | var idRGBM = charIDToTypeID( "RGBM" ); 82 | var idWdth = charIDToTypeID( "Wdth" ); 83 | var idRlt = charIDToTypeID( "#Rlt" ); 84 | var idHght = charIDToTypeID( "Hght" ); 85 | var idRslt = charIDToTypeID( "Rslt" ); 86 | var idRsl = charIDToTypeID( "#Rsl" ); 87 | var idpixelScaleFactor = stringIDToTypeID( "pixelScaleFactor" ); 88 | var idFl = charIDToTypeID( "Fl " ); 89 | var idTrns = charIDToTypeID( "Trns" ); 90 | var idDpth = charIDToTypeID( "Dpth" ); 91 | var idprofile = stringIDToTypeID( "profile" ); 92 | var idDcmn = charIDToTypeID( "Dcmn" ); 93 | var idDocI = charIDToTypeID( "DocI" ); 94 | 95 | var desc1 = new ActionDescriptor(); 96 | var desc2 = new ActionDescriptor(); 97 | desc2.putString( idNm, """New File""" ); 98 | desc2.putBoolean( idartboard, false ); 99 | desc2.putClass( idMd, idRGBM ); 100 | desc2.putUnitDouble( idWdth, idRlt, 480.000000 ); 101 | desc2.putUnitDouble( idHght, idRlt, 360.000000 ); 102 | desc2.putUnitDouble( idRslt, idRsl, 300.000000 ); 103 | desc2.putDouble( idpixelScaleFactor, 1.000000 ); 104 | desc2.putEnumerated( idFl, idFl, idTrns ); 105 | desc2.putInteger( idDpth, 8 ); 106 | desc2.putString( idprofile, """sRGB IEC61966-2.1""" ); 107 | desc1.putObject( idNw, idDcmn, desc2 ); 108 | desc1.putInteger( idDocI, 208 ); 109 | executeAction( idMk, desc1, DialogModes.NO ); 110 | ``` 111 | **Create function | clean variables ✔︎ clean params ✔︎** 112 | ```javascript 113 | function makeNewDocument(params) { 114 | var desc1 = new ActionDescriptor(); 115 | var desc2 = new ActionDescriptor(); 116 | desc2.putString( charIDToTypeID( "Nm " ), params.name); 117 | desc2.putBoolean( stringIDToTypeID( "artboard" ), params.artboard); 118 | desc2.putClass( charIDToTypeID( "Md " ), charIDToTypeID( "RGBM" ) ); 119 | desc2.putUnitDouble( charIDToTypeID( "Wdth" ), charIDToTypeID( "#Rlt" ), params.width); 120 | desc2.putUnitDouble( charIDToTypeID( "Hght" ), charIDToTypeID( "#Rlt" ), params.height); 121 | desc2.putUnitDouble( charIDToTypeID( "Rslt" ), charIDToTypeID( "#Rsl" ), params.resolution); 122 | desc2.putDouble( stringIDToTypeID( "pixelScaleFactor" ), params.pixelScaleFactor); 123 | desc2.putEnumerated( charIDToTypeID( "Fl " ), charIDToTypeID( "Fl " ), charIDToTypeID( "Trns" ) ); 124 | desc2.putInteger( charIDToTypeID( "Dpth" ), params.depth); 125 | desc2.putString( stringIDToTypeID( "profile" ), params.profile); 126 | desc1.putObject( charIDToTypeID( "Nw " ), charIDToTypeID( "Dcmn" ), desc2 ); 127 | desc1.putInteger( charIDToTypeID( "DocI" ), params.docID); 128 | executeAction( charIDToTypeID( "Mk " ), desc1, DialogModes.NO ); 129 | } 130 | 131 | var params = { 132 | name: "New File" , 133 | artboard: false , 134 | width: 480.000000 , 135 | height: 360.000000 , 136 | resolution: 300.000000 , 137 | pixelScaleFactor: 1.000000 , 138 | depth: 8 , 139 | profile: "sRGB IEC61966-2.1" , 140 | docID: 208 141 | }; 142 | 143 | makeNewDocument(params); 144 | ``` 145 | 146 | ## Changelog 147 | **v1.1.0 (Dec 07 2017)** 148 | * Replaced prism node module with min version 149 | 150 | **v1.0.0 (Dec 03 2017)** 151 | * First release 152 | * Feature: "Clean JSX" 153 | * Feature: "Sort IDs" 154 | * Feature: "Create Function" 155 | * Feature: "Clean variables" 156 | * Feature: "Clean params" 157 | * Added Prism for easy readability 158 | 159 | **v0.0.0 (Aug 16 2017)** 160 | * Initial development. 161 | 162 | ## License 163 | MIT © Javier Aroche 164 | -------------------------------------------------------------------------------- /css/prism-themes/prism-onedark.css: -------------------------------------------------------------------------------- 1 | /** 2 | * prism.js default theme for JavaScript, CSS and HTML 3 | * Based on dabblet (http://dabblet.com) 4 | * @author Lea Verou 5 | */ 6 | code[class*="language-"], 7 | pre[class*="language-"] { 8 | color: #ABB2BF; 9 | background: none; 10 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 11 | text-align: left; 12 | white-space: pre; 13 | word-spacing: normal; 14 | word-break: normal; 15 | word-wrap: normal; 16 | line-height: 1.5; 17 | -moz-tab-size: 4; 18 | -o-tab-size: 4; 19 | tab-size: 4; 20 | -webkit-hyphens: none; 21 | -moz-hyphens: none; 22 | -ms-hyphens: none; 23 | hyphens: none; 24 | } 25 | 26 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 27 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 28 | text-shadow: none; 29 | background: #383e49; 30 | } 31 | 32 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 33 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 34 | text-shadow: none; 35 | background: #9aa2b1; 36 | } 37 | 38 | @media print { 39 | code[class*="language-"], 40 | pre[class*="language-"] { 41 | text-shadow: none; 42 | } 43 | } 44 | /* Code blocks */ 45 | pre[class*="language-"] { 46 | padding: 1em; 47 | margin: .5em 0; 48 | overflow: auto; 49 | } 50 | 51 | :not(pre) > code[class*="language-"], 52 | pre[class*="language-"] { 53 | background: #282c34; 54 | } 55 | 56 | /* Inline code */ 57 | :not(pre) > code[class*="language-"] { 58 | padding: .1em; 59 | border-radius: .3em; 60 | white-space: normal; 61 | } 62 | 63 | .token.comment, 64 | .token.prolog, 65 | .token.doctype, 66 | .token.cdata { 67 | color: #5C6370; 68 | } 69 | 70 | .token.punctuation { 71 | color: #abb2bf; 72 | } 73 | 74 | .token.selector, 75 | .token.tag { 76 | color: #e06c75; 77 | } 78 | 79 | .token.property, 80 | .token.boolean, 81 | .token.number, 82 | .token.constant, 83 | .token.symbol, 84 | .token.attr-name, 85 | .token.deleted { 86 | color: #d19a66; 87 | } 88 | 89 | .token.string, 90 | .token.char, 91 | .token.attr-value, 92 | .token.builtin, 93 | .token.inserted { 94 | color: #98c379; 95 | } 96 | 97 | .token.operator, 98 | .token.entity, 99 | .token.url, 100 | .language-css .token.string, 101 | .style .token.string { 102 | color: #56b6c2; 103 | } 104 | 105 | .token.atrule, 106 | .token.keyword { 107 | color: #c678dd; 108 | } 109 | 110 | .token.function { 111 | color: #61afef; 112 | } 113 | 114 | .token.regex, 115 | .token.important, 116 | .token.variable { 117 | color: #c678dd; 118 | } 119 | 120 | .token.important, 121 | .token.bold { 122 | font-weight: bold; 123 | } 124 | 125 | .token.italic { 126 | font-style: italic; 127 | } 128 | 129 | .token.entity { 130 | cursor: help; 131 | } 132 | 133 | pre.line-numbers { 134 | position: relative; 135 | padding-left: 3.8em; 136 | counter-reset: linenumber; 137 | } 138 | 139 | pre.line-numbers > code { 140 | position: relative; 141 | } 142 | 143 | .line-numbers .line-numbers-rows { 144 | position: absolute; 145 | pointer-events: none; 146 | top: 0; 147 | font-size: 100%; 148 | left: -3.8em; 149 | width: 3em; /* works for line-numbers below 1000 lines */ 150 | letter-spacing: -1px; 151 | border-right: 0; 152 | 153 | -webkit-user-select: none; 154 | -moz-user-select: none; 155 | -ms-user-select: none; 156 | user-select: none; 157 | 158 | } 159 | 160 | .line-numbers-rows > span { 161 | pointer-events: none; 162 | display: block; 163 | counter-increment: linenumber; 164 | } 165 | 166 | .line-numbers-rows > span:before { 167 | content: counter(linenumber); 168 | color: #5C6370; 169 | display: block; 170 | padding-right: 0.8em; 171 | text-align: right; 172 | } 173 | -------------------------------------------------------------------------------- /css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Quicksand', sans-serif !important; 3 | width: 900px; 4 | border-style: none; 5 | margin-left: auto; 6 | margin-right: auto; 7 | background-color: #16181C; 8 | color: #DCDCDC; 9 | font-size: 14px; 10 | } 11 | 12 | h1 { 13 | text-align: center; 14 | font-size: 18px; 15 | font-weight: lighter; 16 | margin: 30px 0 8px 0; 17 | } 18 | 19 | h3 { 20 | text-align: center; 21 | font-size: 12px;; 22 | font-weight: lighter; 23 | margin: 8px 0 10px 0; 24 | } 25 | 26 | textarea { 27 | width: 100%; 28 | height: 300px; 29 | padding: 4px 7px; 30 | font-size: 12px; 31 | font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier; 32 | border: none; 33 | border-radius: 4px; 34 | color: #FFFFFF; 35 | margin: 0 0 15px 0; 36 | background-color: #282C34; 37 | outline: none; 38 | resize: vertical; 39 | } 40 | 41 | #buttons { 42 | width: 600px; 43 | text-align: center; 44 | margin: 10px auto 0 auto; 45 | } 46 | 47 | #parse, #clear { 48 | width: 75px; 49 | margin: 0 2px 0 2px; 50 | } 51 | 52 | .options { 53 | text-align: center; 54 | margin: 0 auto 0 auto; 55 | } 56 | 57 | #dropDown { 58 | margin: 0 5px 0 5px; 59 | outline: none; 60 | } 61 | 62 | #cleanVariablesText, #cleanParamsText { 63 | font-size: 12px; 64 | font-weight: lighter; 65 | } 66 | 67 | #functionName { 68 | width: 120px; 69 | border: none; 70 | border-radius: 2px; 71 | outline: none; 72 | text-align: center; 73 | margin: 0 5px 0 5px; 74 | } 75 | 76 | #outputTextArea { 77 | opacity: 0; 78 | height: 0; 79 | width: 0; 80 | } 81 | 82 | #outputPre { 83 | border-radius: 4px; 84 | min-height: 300px; 85 | background: #282C34 !important; 86 | } 87 | 88 | #output { 89 | font-size: 12px; 90 | font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier; 91 | } 92 | 93 | #copy { 94 | margin: 10px auto 0 auto; 95 | } 96 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | parse-action-descriptor-code 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Input

12 |

13 | Line count: 14 | 0 15 |

16 | 17 | 18 |
19 | 24 | 25 | Clean variables 26 | Clean params 27 | 28 | 29 |
30 | 31 |

Output

32 |

33 | Line count: 34 | 0 35 |

36 |
37 |
38 | 39 |
40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | const constants = { 2 | "Hrzn": "horizontal", 3 | "Vrtc": "vertical", 4 | "Wdth": "width", 5 | "Hght": "height", 6 | "Angl": "angle", 7 | "Lnkd": "linked", 8 | "Lvl": "level", 9 | "Ttl": "title", 10 | "Lyr": "layer", 11 | "MkVs": "makeVisible", 12 | "Exps": "exposure", 13 | "Ofst": "offset", 14 | "Opct": "opacity", 15 | "Btom": "bottom", 16 | "Rght": "right", 17 | "Txt": "text", 18 | "Spcn": "spacing", 19 | "FntN": "fontName", 20 | "FntS": "fontSize", 21 | "Sz": "size", 22 | "Ldng": "leading", 23 | "Trck": "tracking", 24 | "Rd": "red", 25 | "Grn": "green", 26 | "Bl": "blue", 27 | "HrzS": "horizontalScale", 28 | "VrtS": "verticalScale", 29 | "Bsln": "baseline", 30 | "Fl": "fill", 31 | "Strk": "stroke", 32 | "LyrI": "layerID", 33 | "DocI": "docID", 34 | "T": "to", 35 | "Nm": "name", 36 | "Rslt": "resolution", 37 | "Dpth": "depth" 38 | }; 39 | -------------------------------------------------------------------------------- /lib/prism.js: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.9.0 2 | http://prismjs.com/download.html?themes=prism&languages=clike+javascript */ 3 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)return;if(!(w instanceof s)){h.lastIndex=0;var _=h.exec(w),P=1;if(!_&&m&&b!=t.length-1){if(h.lastIndex=k,_=h.exec(e),!_)break;for(var A=_.index+(d?_[1].length:0),j=_.index+_[0].length,x=b,O=k,N=t.length;N>x&&(j>O||!t[x].type&&!t[x-1].greedy);++x)O+=t[x].length,A>=O&&(++b,k=O);if(t[b]instanceof s||t[x-1].greedy)continue;P=x-b,w=e.slice(k,O),_.index-=k}if(_){d&&(p=_[1].length);var A=_.index+p,_=_[0].slice(p),j=A+_.length,S=w.slice(0,A),C=w.slice(j),M=[b,P];S&&(++b,k+=S.length,M.push(S));var E=new s(g,f?n.tokenize(_,f):_,y,_,m);if(M.push(E),C&&M.push(C),Array.prototype.splice.apply(t,M),1!=P&&n.matchGrammar(e,t,r,b,k,!0,g),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+""},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); 4 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; 5 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+(?:[Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript",greedy:!0}}),Prism.languages.js=Prism.languages.javascript; 6 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Parse Action Descriptor Code 4 | * Author: Javier Aroche (https://github.com/JavierAroche) 5 | * 6 | */ 7 | 8 | const parseBtn = document.getElementById('parse'); 9 | const clearBtn = document.getElementById('clear'); 10 | const input = document.getElementById('input'); 11 | const inputCount = document.getElementById('inputCount'); 12 | const output = document.getElementById('output'); 13 | const outputTextArea = document.getElementById('outputTextArea'); 14 | const outputCount = document.getElementById('outputCount'); 15 | const dropDown = document.getElementById('dropDown'); 16 | const cleanVariables = document.getElementById('cleanVariables'); 17 | const cleanParams = document.getElementById('cleanParams'); 18 | const copyBtn = document.getElementById('copy'); 19 | 20 | input.focus(); 21 | 22 | /* 23 | * @public 24 | * Parse button click event 25 | */ 26 | parseBtn.addEventListener('click', () => { 27 | let data = input.value; 28 | let parsedData = data; 29 | 30 | if(cleanVariables.checked) { 31 | parsedData = parser.cleanVariables(parsedData); 32 | } 33 | 34 | switch(dropDown.value) { 35 | case 'cleanJSX': 36 | parsedData = parser.cleanJSX(parsedData); 37 | break; 38 | case 'sortIDs': 39 | parsedData = parser.sortIDs(parsedData); 40 | break; 41 | case 'createFunction': 42 | let functionName = document.getElementById('functionName').value; 43 | parsedData = parser.cleanJSX(parsedData); 44 | parsedData = parser.createFunction(parsedData, functionName); 45 | break; 46 | } 47 | 48 | parser.clipboard = parsedData; 49 | outputTextArea.value = parsedData; 50 | output.innerHTML = Prism.highlight(parsedData, Prism.languages.javascript); 51 | parser.getLineCounts(); 52 | }); 53 | 54 | /* 55 | * @public 56 | * Get line count on change 57 | */ 58 | input.addEventListener('input', () => { 59 | parser.getLineCounts(); 60 | }) 61 | 62 | /* 63 | * @public 64 | * Clear button click event 65 | */ 66 | clearBtn.addEventListener('click', () => { 67 | input.value = ''; 68 | parser.getLineCounts(); 69 | }); 70 | 71 | /* 72 | * @public 73 | * Copy to clipboard button click event 74 | */ 75 | copyBtn.addEventListener('click', () => { 76 | outputTextArea.select(); 77 | document.execCommand("Copy"); 78 | }); 79 | 80 | class Parser { 81 | /* 82 | * Constructor 83 | */ 84 | constructor() { 85 | this.clipboard = ''; 86 | } 87 | 88 | /* 89 | * Remove unnecessary charID and stringID variables for a shorter code 90 | */ 91 | cleanJSX(data) { 92 | let lines = data.split('\n'); 93 | let variables = {}; 94 | let actionLines = []; 95 | // Identify lines with charIDs or stringIDs 96 | lines.forEach(line => { 97 | if(line.match('var') && (line.match('charIDToTypeID') || line.match('stringIDToTypeID'))) { 98 | let variableName = line.replace(/[\s+]*var /, '').replace(/ =.+/, ''); 99 | let id = line.replace(/[\s+]*.+= /, '').replace(';', ''); 100 | variables[variableName] = id; 101 | } else if(line !== '') { 102 | let cleanLine; 103 | if(line[0] === ' ' || line[0] === ' ') { 104 | cleanLine = line.replace(/\s+/, ''); 105 | } else { 106 | cleanLine = line; 107 | } 108 | actionLines.push(cleanLine); 109 | } 110 | }); 111 | 112 | // Cleanup lines 113 | let parsedLines = []; 114 | actionLines.forEach(actionLine => { 115 | let idNames = actionLine.match(/id\w+/g); 116 | let parsedLine = actionLine; 117 | if(idNames && idNames.length > 0) { 118 | idNames.forEach(function(idName) { 119 | parsedLine = parsedLine.replace(idName, variables[idName]); 120 | }); 121 | } 122 | parsedLines.push(parsedLine); 123 | }); 124 | 125 | return parsedLines.join('\n'); 126 | } 127 | 128 | /* 129 | * Sort IDs by placing them at the top for easier readibility 130 | */ 131 | sortIDs(data) { 132 | let lines = data.split('\n'); 133 | let variables = {}; 134 | let actionLines = []; 135 | lines.forEach(line => { 136 | if(line.match('var') && (line.match('charIDToTypeID') || line.match('stringIDToTypeID'))) { 137 | let variableName = line.replace(/[\s+]*var /, '').replace(/ =.+/, ''); 138 | let id = line.replace(/[\s+]*.+= /, '').replace(';', ''); 139 | variables[variableName] = id; 140 | } else { 141 | let cleanLine = line; 142 | if(cleanLine[0] === ' ') { 143 | cleanLine = cleanLine.replace(/\s+/, ''); 144 | } 145 | actionLines.push(cleanLine); 146 | } 147 | }); 148 | 149 | let varIDs = ''; 150 | for(let i in variables) { 151 | varIDs = varIDs + 'var ' + i + ' = ' + variables[i] + ';' + '\n'; 152 | }; 153 | 154 | return varIDs + '\n' + actionLines.join('\n'); 155 | } 156 | 157 | /* 158 | * Create a function based on the action descriptor code 159 | */ 160 | createFunction(data, functionName) { 161 | let lines = data.split('\n'); 162 | let variables = []; 163 | let lists = {}; 164 | let parsedLines = []; 165 | let lineSplit, lineValue, lineProperty, parsedLine, listNumber; 166 | lines.forEach(line => { 167 | if(line.match(/list|ref/) && line.match(/putIndex|putInteger|putIdentifier/)) { 168 | // Get list/ref number and capitalize first letter 169 | listNumber = line.match(/\w+/)[0]; 170 | // Get value 171 | lineValue = Number(line.match(/ \d+ /)[0]); 172 | if(!lists.hasOwnProperty(listNumber)) { 173 | lists[listNumber] = []; 174 | } 175 | lists[listNumber].push(lineValue); 176 | // Replace found value with param value 177 | parsedLine = line.replace(/ \d+ /, ` params.${listNumber}[${lists[listNumber].length - 1}] `); 178 | parsedLines.push(parsedLine); 179 | } else if(line.match(/putBoolean|putUnitDouble|putDouble|putInteger|putIdentifier|putIndex|putString|putName|putPath/)) { 180 | lineSplit = line.split(', '); 181 | // Get value and property name 182 | lineValue = lineSplit[lineSplit.length - 1].replace(/\);/, ''); 183 | lineProperty = lineSplit[0].replace(/.+(stringIDToTypeID|charIDToTypeID)/, '').match(/\w+/)[0]; 184 | if(cleanParams.checked) { 185 | lineProperty = this.replaceConstant(lineProperty); 186 | } 187 | // Add to array which will become the params object 188 | variables.push(`${lineProperty}: ${lineValue.replace(/"""/g,'"')}`); 189 | // Replace found value with param value 190 | parsedLine = line.replace(lineValue, `params.${lineProperty}`); 191 | parsedLines.push(parsedLine); 192 | } else { 193 | parsedLines.push(line); 194 | } 195 | }); 196 | 197 | // Add lists as variables 198 | for(let key in lists) { 199 | variables.push(`${key}: [${lists[key].join(',')}]`); 200 | } 201 | 202 | // Create function string 203 | let functionString = 204 | `function ${functionName}(params) { 205 | ${parsedLines.join('\n ')} 206 | } 207 | 208 | var params = { 209 | ${variables.join(',\n ')} 210 | }; 211 | 212 | ${functionName}(params);`; 213 | 214 | return functionString; 215 | } 216 | 217 | /* 218 | * Replace constant from list 219 | */ 220 | replaceConstant(variable) { 221 | if(constants.hasOwnProperty(variable)) { 222 | return constants[variable]; 223 | } else { 224 | return variable.charAt(0).toLowerCase() + variable.slice(1); 225 | } 226 | } 227 | 228 | /* 229 | * Clean variables to start count from 1 230 | */ 231 | cleanVariables(data) { 232 | let lines = data.split('\n'); 233 | let variables = {}; 234 | let actionLines = []; 235 | let descCount = 1; 236 | let refCount = 1; 237 | let listCount = 1; 238 | // Identify lines with variables 239 | lines.forEach(line => { 240 | if(line.match('var') && (line.match('ActionDescriptor') || line.match('ActionReference') || line.match('ActionList'))) { 241 | actionLines.push(line); 242 | let variableName = line.replace(/[\s+]*var /, '').replace(/ =.+/, ''); 243 | let newVariableName; 244 | if(line.match('ActionDescriptor')) { 245 | newVariableName = 'desc' + descCount; 246 | descCount = descCount + 1; 247 | } else if(line.match('ActionReference')) { 248 | newVariableName = 'ref' + refCount; 249 | refCount = refCount + 1; 250 | } else if(line.match('ActionList')) { 251 | newVariableName = 'list' + listCount; 252 | listCount = listCount + 1; 253 | } 254 | variables[variableName] = newVariableName; 255 | } else { 256 | let cleanLine = line; 257 | if(cleanLine[0] === ' ') { 258 | cleanLine = cleanLine.replace(/\s+/, ''); 259 | } 260 | actionLines.push(cleanLine); 261 | } 262 | }); 263 | 264 | // Cleanup variable names 265 | let parsedLines = []; 266 | actionLines.forEach(actionLine => { 267 | let parsedLine = actionLine; 268 | 269 | let descVars = actionLine.match(/desc\w+/g); 270 | if(descVars && descVars.length > 0) { 271 | descVars.forEach(function(descVar) { 272 | parsedLine = parsedLine.replace(descVar, variables[descVar]); 273 | }); 274 | } 275 | 276 | let refVars = actionLine.match(/ref\w+/g); 277 | if(refVars && refVars.length > 0) { 278 | refVars.forEach(function(refVar) { 279 | parsedLine = parsedLine.replace(refVar, variables[refVar]); 280 | }); 281 | } 282 | 283 | let listVars = actionLine.match(/list\w+/g); 284 | if(listVars && listVars.length > 0) { 285 | listVars.forEach(function(listVar) { 286 | parsedLine = parsedLine.replace(listVar, variables[listVar]); 287 | }); 288 | } 289 | 290 | parsedLines.push(parsedLine); 291 | }); 292 | 293 | return parsedLines.join('\n'); 294 | } 295 | 296 | /* 297 | * Get line counts 298 | */ 299 | getLineCounts() { 300 | let inputData = input.value; 301 | let inputLines = []; 302 | if(inputData !== '') { 303 | inputLines = inputData.split('\n'); 304 | } 305 | let outputData = output.innerHTML; 306 | let outputLines = []; 307 | if(outputData !== '') { 308 | outputLines = outputData.split('\n'); 309 | } 310 | inputCount.innerHTML = inputLines.length; 311 | outputCount.innerHTML = outputLines.length; 312 | } 313 | } 314 | 315 | let parser = new Parser(); 316 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-action-descriptor-code", 3 | "version": "1.1.0", 4 | "description": "Parse your Photoshop Action Descriptor code from the Scripting Listener into a more readable format.", 5 | "main": "main.js", 6 | "scripts": {}, 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/JavierAroche/parse-action-descriptor-code.git" 10 | }, 11 | "author": "Javier Aroche", 12 | "license": "UNLICENSED", 13 | "bugs": { 14 | "url": "https://github.com/JavierAroche/parse-action-descriptor-code/issues" 15 | }, 16 | "homepage": "https://github.com/JavierAroche/parse-action-descriptor-code#readme", 17 | "dependencies": {} 18 | } 19 | --------------------------------------------------------------------------------