00001 # TKE - Advanced Programmer's Editor
00002 # Copyright (C) 2014-2019 Trevor Williams (phase1geo@gmail.com)
00003 #
00004 # This program is free software; you can redistribute it and/or modify
00005 # it under the terms of the GNU General Public License as published by
00006 # the Free Software Foundation; either version 2 of the License, or
00007 # (at your option) any later version.
00008 #
00009 # This program is distributed in the hope that it will be useful,
00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012 # GNU General Public License for more details.
00013 #
00014 # You should have received a copy of the GNU General Public License along
00015 # with this program; if not, write to the Free Software Foundation, Inc.,
00016 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00017
00018 ######################################################################
00019 # Name: emmet_css.tcl
00020 # Author: Trevor Williams (phase1geo@gmail.com)
00021 # Date: 03/17/2016
00022 # Brief: Namespace containing Emmet CSS-related functionality.
00023 ######################################################################
00024
00025 namespace eval emmet_css {
00026
00027 array set lookup {
00028 pos {{position} {{|relative}}}
00029 pos:s {{position} {static}}
00030 pos:a {{position} {absolute}}
00031 pos:r {{position} {relative}}
00032 pos:f {{position} {fixed}}
00033 t {{top} {{|}}}
00034 t:a {{top} {auto}}
00035 r {{right} {{|}}}
00036 r:a {{right} {auto}}
00037 b {{bottom} {{|}}}
00038 b:a {{bottom} {auto}}
00039 l {{left} {{|}}}
00040 l:a {{left} {auto}}
00041 z {{z-index} {{|}}}
00042 z:a {{z-index} {auto}}
00043 fl {{float} {{|left}}}
00044 fl:n {{float} {none}}
00045 fl:l {{float} {left}}
00046 fl:r {{float} {right}}
00047 cl {{clear} {{|both}}}
00048 cl:n {{clear} {none}}
00049 cl:l {{clear} {left}}
00050 cl:r {{clear} {right}}
00051 cl:b {{clear} {both}}
00052 d {{display} {{|block}}}
00053 d:n {{display} {none}}
00054 d:b {{display} {block}}
00055 d:i {{display} {inline}}
00056 d:ib {{display} {inline-block}}
00057 d:li {{display} {list-item}}
00058 d:cp {{display} {compact}}
00059 d:tb {{display} {table}}
00060 d:itb {{display} {inline-table}}
00061 d:tbcp {{display} {table-caption}}
00062 d:tbcl {{display} {table-column}}
00063 d:tbclg {{display} {table-column-group}}
00064 d:tbhg {{display} {table-header-group}}
00065 d:tbfg {{display} {table-footer-group}}
00066 d:tbr {{display} {table-row}}
00067 d:tbrg {{display} {table-row-group}}
00068 d:tbc {{display} {table-cell}}
00069 d:rb {{display} {ruby}}
00070 d:rbb {{display} {ruby-base}}
00071 d:rbbg {{display} {ruby-base-group}}
00072 d:rbt {{display} {ruby-text}}
00073 d:rbtg {{display} {ruby-text-group}}
00074 v {{visibility} {{|hidden}}}
00075 v:v {{visibility} {visible}}
00076 v:h {{visibility} {hidden}}
00077 v:c {{visibility} {collapse}}
00078 ov {{overflow} {{|hidden}}}
00079 ov:v {{overflow} {visible}}
00080 ov:h {{overflow} {hidden}}
00081 ov:s {{overflow} {scroll}}
00082 ov:a {{overflow} {auto}}
00083 ovx {{overflow-x} {{|hidden}}}
00084 ovx:v {{overflow-x} {visible}}
00085 ovx:h {{overflow-x} {hidden}}
00086 ovx:s {{overflow-x} {scroll}}
00087 ovx:a {{overflow-x} {auto}}
00088 ovy {{overflow-y} {{|hidden}}}
00089 ovy:v {{overflow-y} {visible}}
00090 ovy:h {{overflow-y} {hidden}}
00091 ovy:s {{overflow-y} {scroll}}
00092 ovy:a {{overflow-y} {auto}}
00093 ovs {{overflow-style} {{|scrollbar}}}
00094 ovs:a {{overflow-style} {auto}}
00095 ovs:s {{overflow-style} {scrollbar}}
00096 ovs:p {{overflow-style} {panner}}
00097 ovs:m {{overflow-style} {move}}
00098 ovs:mq {{overflow-style} {marquee}}
00099 zoo {{zoom} {1}}
00100 zm {{zoom} {1}}
00101 cp {{clip} {{|}}}
00102 cp:a {{clip} {auto}}
00103 cp:r {{clip} {rect({|top}, {|right}, {|bottom}, {|left})}}
00104 rsz {{resize} {{|}}}
00105 rsz:n {{resize} {none}}
00106 rsz:b {{resize} {both}}
00107 rsz:h {{resize} {horizontal}}
00108 rsz:v {{resize} {vertical}}
00109 cur {{cursor} {{|pointer}}}
00110 cur:a {{cursor} {auto}}
00111 cur:d {{cursor} {default}}
00112 cur:c {{cursor} {crosshair}}
00113 cur:ha {{cursor} {hand}}
00114 cur:he {{cursor} {help}}
00115 cur:m {{cursor} {move}}
00116 cur:p {{cursor} {pointer}}
00117 cur:t {{cursor} {text}}
00118 m {{margin} {{|}}}
00119 m:a {{margin} {auto}}
00120 mt {{margin-top} {{|}}}
00121 mt:a {{margin-top} {auto}}
00122 mr {{margin-right} {{|}}}
00123 mr:a {{margin-right} {auto}}
00124 mb {{margin-bottom} {{|}}}
00125 mb:a {{margin-bottom} {auto}}
00126 ml {{margin-left} {{|}}}
00127 ml:a {{margin-left} {auto}}
00128 p {{padding} {{|}}}
00129 pt {{padding-top} {{|}}}
00130 pr {{padding-right} {{|}}}
00131 pb {{padding-bottom} {{|}}}
00132 pl {{padding-left} {{|}}}
00133 bxz {{box-sizing} {{|border-box}}}
00134 bxz:cb {{box-sizing} {content-box}}
00135 bxz:bb {{box-sizing} {border-box}}
00136 bxsh {{box-shadow} {{|inset} {|hoff} {|voff} {|blur} {|color}}}
00137 bxsh:r {{box-shadow} {{|inset} {|hoff} {|voff} {|blur} {|spread} rgb({|0}, {|0}, {|0})}}
00138 bxsh:ra {{box-shadow} {{|inset} {|h} {|v} {|blur} {|spread} rgba({|0}, {|0}, {|0}, {|.5})}}
00139 bxsh:n {{box-shadow} {none}}
00140 w {{width} {{|}}}
00141 w:a {{width} {auto}}
00142 h {{height} {{|}}}
00143 h:a {{height} {auto}}
00144 maw {{max-width} {{|}}}
00145 maw:n {{max-width} {none}}
00146 mah {{max-height} {{|}}}
00147 mah:n {{max-height} {none}}
00148 miw {{min-width} {{|}}}
00149 mih {{min-height} {{|}}}
00150 f {{font} {{|}}}
00151 f+ {{font} {{|1em} {|Arial,sans-serif}}}
00152 fw {{font-weight} {{|}}}
00153 fw:n {{font-weight} {none}}
00154 fw:b {{font-weight} {bold}}
00155 fw:br {{font-weight} {bolder}}
00156 fw:lr {{font-weight} {lighter}}
00157 fs {{font-style} {{|italic}}}
00158 fs:n {{font-style} {normal}}
00159 fs:i {{font-style} {italic}}
00160 fs:o {{font-style} {oblique}}
00161 fv {{font-variant} {{|}}}
00162 fv:sc {{font-variant} {small-caps}}
00163 fz {{font-size} {{|}}}
00164 fza {{font-size-adjust} {{|}}}
00165 fza:n {{font-size-adjust} {none}}
00166 ff {{font-family} {{|}}}
00167 ff:s {{font-family} {serif}}
00168 ff:ss {{font-family} {sans-serif}}
00169 ff:c {{font-family} {cursive}}
00170 ff:f {{font-family} {fantasy}}
00171 ff:m {{font-family} {monospace}}
00172 ff:a {{font-family} {Arial, "Helvetica Neue", Helvetica, sans-serif}}
00173 fef {{font-effect} {{|}}}
00174 fef:n {{font-effect} {none}}
00175 fef:eg {{font-effect} {engrave}}
00176 fef:eb {{font-effect} {emboss}}
00177 fef:o {{font-effect} {outline}}
00178 fem {{font-emphasize} {{|}}}
00179 femp {{font-emphasize-position} {{|}}}
00180 femp:b {{font-emphasize-position} {before}}
00181 femp:a {{font-emphasize-position} {after}}
00182 fems {{font-emphasize-style} {{|}}}
00183 fems:n {{font-emphasize-style} {none}}
00184 fems:ac {{font-emphasize-style} {accent}}
00185 fems:dt {{font-emphasize-style} {dot}}
00186 fems:c {{font-emphasize-style} {circle}}
00187 fems:ds {{font-emphasize-style} {disc}}
00188 fsm {{font-smooth} {{|}}}
00189 fsm:a {{font-smooth} {auto}}
00190 fsm:n {{font-smooth} {never}}
00191 fsm:aw {{font-smooth} {always}}
00192 fst {{font-stretch} {{|}}}
00193 fst:n {{font-stretch} {normal}}
00194 fst:uc {{font-stretch} {ultra-condensed}}
00195 fst:ec {{font-stretch} {extra-condensed}}
00196 fst:c {{font-stretch} {condensed}}
00197 fst:sc {{font-stretch} {semi-condensed}}
00198 fst:se {{font-stretch} {semi-expanded}}
00199 fst:e {{font-stretch} {expanded}}
00200 fst:ee {{font-stretch} {extra-expanded}}
00201 fst:ue {{font-stretch} {ultra-expanded}}
00202 va {{vertical-align} {top}}
00203 va:sup {{vertical-align} {super}}
00204 va:t {{vertical-align} {top}}
00205 va:tt {{vertical-align} {text-top}}
00206 va:m {{vertical-align} {middle}}
00207 va:bl {{vertical-align} {baseline}}
00208 va:b {{vertical-align} {bottom}}
00209 va:tb {{vertical-align} {text-bottom}}
00210 va:sub {{vertical-align} {sub}}
00211 ta {{text-align} {{|left}}}
00212 ta:l {{text-align} {left}}
00213 ta:c {{text-align} {center}}
00214 ta:r {{text-align} {right}}
00215 ta:j {{text-align} {justify}}
00216 ta-lst {{text-align-last} {{|}}}
00217 tal:a {{text-align-last} {auto}}
00218 tal:l {{text-align-last} {left}}
00219 tal:c {{text-align-last} {center}}
00220 tal:r {{text-align-last} {right}}
00221 td {{text-decoration} {{|none}}}
00222 td:n {{text-decoration} {none}}
00223 td:u {{text-decoration} {underline}}
00224 td:o {{text-decoration} {overline}}
00225 td:l {{text-decoration} {line-through}}
00226 te {{text-emphasis} {{|}}}
00227 te:n {{text-emphasis} {none}}
00228 te:ac {{text-emphasis} {accent}}
00229 te:dt {{text-emphasis} {dot}}
00230 te:c {{text-emphasis} {circle}}
00231 te:ds {{text-emphasis} {disc}}
00232 te:b {{text-emphasis} {before}}
00233 te:a {{text-emphasis} {after}}
00234 th {{text-height} {{|}}}
00235 th:a {{text-height} {auto}}
00236 th:f {{text-height} {font-size}}
00237 th:t {{text-height} {text-size}}
00238 th:m {{text-height} {max-size}}
00239 ti {{text-indent} {{|}}}
00240 ti:- {{text-indent} {-9999px}}
00241 tj {{text-justify} {{|}}}
00242 tj:a {{text-justify} {auto}}
00243 tj:iw {{text-justify} {inter-word}}
00244 tj:ii {{text-justify} {inter-ideograph}}
00245 tj:ic {{text-justify} {inter-cluster}}
00246 tj:d {{text-justify} {distribute}}
00247 tj:k {{text-justify} {kashida}}
00248 tj:t {{text-justify} {tibetan}}
00249 to {{text-outline} {{|}}}
00250 to+ {{text-outline} {0 0 #000}}
00251 to:n {{text-outline} {none}}
00252 tr {{text-replace} {{|}}}
00253 tr:n {{text-replace} {none}}
00254 tt {{text-transform} {{|uppercase}}}
00255 tt:n {{text-transform} {none}}
00256 tt:c {{text-transform} {capitalize}}
00257 tt:u {{text-transform} {uppercase}}
00258 tt:l {{text-transform} {lowercase}}
00259 tw {{text-wrap} {{|}}}
00260 tw:n {{text-wrap} {normal}}
00261 tw:no {{text-wrap} {none}}
00262 tw:u {{text-wrap} {unrestricted}}
00263 tw:s {{text-wrap} {suppress}}
00264 tsh {{text-shadow} {{|hoff} {|voff} {|blur} {|#000}}}
00265 tsh:r {{text-shadow} {{|h} {|v} {|blur} rgb({|0}, {|0}, {|0})}}
00266 tsh:ra {{text-shadow} {{|h} {|v} {|blur} rgb({|0}, {|0}, {|0}, {|.5})}}
00267 tsh+ {{text-shadow} {{|0} {|0} {|0} {|#000}}}
00268 tsh:n {{text-shadow} {none}}
00269 lh {{line-height} {{|}}}
00270 lts {{letter-spacing} {{|}}}
00271 whs {{white-space} {{|}}}
00272 whs:n {{white-space} {normal}}
00273 whs:p {{white-space} {pre}}
00274 whs:nw {{white-space} {nowrap}}
00275 whs:pw {{white-space} {pre-wrap}}
00276 whs:pl {{white-space} {pre-line}}
00277 whsc {{white-space-collapse} {{|}}}
00278 whsc:n {{white-space-collapse} {normal}}
00279 whsc:k {{white-space-collapse} {keep-all}}
00280 whsc:l {{white-space-collapse} {loose}}
00281 whsc:bs {{white-space-collapse} {break-strict}}
00282 whsc:ba {{white-space-collapse} {break-all}}
00283 wob {{word-break} {{|}}}
00284 wob:n {{word-break} {normal}}
00285 wob:k {{word-break} {keep-all}}
00286 wob:l {{word-break} {loose}}
00287 wob:bs {{word-break} {break-strict}}
00288 wob:ba {{word-break} {break-all}}
00289 wos {{word-spacking} {{|}}}
00290 wow {{word-wrap} {{|}}}
00291 wow:nm {{word-wrap} {normal}}
00292 wow:n {{word-wrap} {none}}
00293 wow:u {{word-wrap} {unrestricted}}
00294 wow:s {{word-wrap} {suppress}}
00295 wow:b {{word-wrap} {break-word}}
00296 bg {{background} {{|}}}
00297 bg+ {{background} {{|#fff} url({|}) {|0} {|0} {|no-repeat}}}
00298 bg:n {{background} {none}}
00299 bgc {{background-color} {{|#fff}}}
00300 bgc:t {{background-color} {transparent}}
00301 bgi {{background-image} {url({|})}}
00302 bgi:n {{background-image} {none}}
00303 bgr {{background-repeat} {{|}}}
00304 bgr:n {{background-repeat} {no-repeat}}
00305 bgr:x {{background-repeat} {repeat-x}}
00306 bgr:y {{background-repeat} {repeat-y}}
00307 bgr:sp {{background-repeat} {space}}
00308 bgr:rd {{background-repeat} {round}}
00309 bga {{background-attachment} {{|}}}
00310 bga:f {{background-attachment} {fixed}}
00311 bga:s {{background-attachment} {scroll}}
00312 bgp {{background-position} {{|0} {|0}}}
00313 bgpx {{background-position-x} {{|}}}
00314 bgpy {{background-position-y} {{|}}}
00315 bgbk {{background-break} {{|}}}
00316 bgbk:bb {{background-break} {bounding-box}}
00317 bgbk:eb {{background-break} {each-box}}
00318 bgbk:c {{background-break} {continuous}}
00319 bgcp {{background-clip} {{|padding-box}}}
00320 bgcp:bb {{background-clip} {border-box}}
00321 bgcp:pb {{background-clip} {padding-box}}
00322 bgcp:cb {{background-clip} {content-box}}
00323 bgcp:nc {{background-clip} {no-clip}}
00324 bgo {{background-origin} {{|}}}
00325 bgo:pb {{background-origin} {padding-box}}
00326 bgo:bb {{background-origin} {border-box}}
00327 bgo:cb {{background-origin} {content-box}}
00328 bgsz {{background-size} {{|}}}
00329 bgsz:a {{background-size} {auto}}
00330 bgsz:ct {{background-size} {contain}}
00331 bgsz:cv {{background-size} {cover}}
00332 c {{color} {{|#000}}}
00333 c:r {{color} {rgb({|0}, {|0}, {|0})}}
00334 c:ra {{color} {rgb({|0}, {|0}, {|0}, {|.5})}}
00335 op {{opacity} {{|}}}
00336 cnt {{content} {'{|}'}}
00337 cnt:n {{content} {normal}}
00338 ct:n {{content} {normal}}
00339 cnt:oq {{content} {open-quote}}
00340 ct:oq {{content} {open-quote}}
00341 cnt:noq {{content} {no-open-quote}}
00342 ct:noq {{content} {no-open-quote}}
00343 cnt:cq {{content} {close-quote}}
00344 ct:cq {{content} {close-quote}}
00345 cnt:ncq {{content} {no-close-quote}}
00346 ct:ncq {{content} {no-close-quote}}
00347 cnt:a {{content} {attr({|})}}
00348 ct:a {{content} {attr({|})}}
00349 cnt:c {{content} {counter({|})}}
00350 ct:c {{content} {counter({|})}}
00351 cnt:cs {{content} {counters({|})}}
00352 ct:cs {{content} {counters({|})}}
00353 ct {{content} {{|}}}
00354 q {{quotes} {{|}}}
00355 q:n {{quotes} {none}}
00356 q:ru {{quotes} {'\00AB' '\00BB' '\201E' '\201C'}}
00357 q:en {{quotes} {'\201C' '\201D' '\2018' '\2019'}}
00358 coi {{counter-increment} {{|}}}
00359 cor {{counter-reset} {{|}}}
00360 ol {{outline} {{|}}}
00361 ol:n {{outline} {none}}
00362 olo {{outline-offset} {{|}}}
00363 olw {{outline-width} {{|}}}
00364 ols {{outline-style} {{|}}}
00365 olc {{outline-color} {#{|000}}}
00366 olc:i {{outline-color} {invert}}
00367 tbl {{table-layout} {{|}}}
00368 tbl:a {{table-layout} {auto}}
00369 tbl:f {{table-layout} {fixed}}
00370 cps {{caption-side} {{|}}}
00371 cps:t {{caption-side} {top}}
00372 cps:b {{caption-side} {bottom}}
00373 ec {{empty-cells} {{|}}}
00374 ec:s {{empty-cells} {show}}
00375 ec:h {{empty-cells} {hide}}
00376 bd {{border} {{|}}}
00377 bd+ {{border} {{|1px} {|solid} {|#000}}}
00378 bd:n {{border} {none}}
00379 bdbk {{border-break} {{|close}}}
00380 bdbk:c {{border-break} {close}}
00381 bdcl {{border-collapse} {{|}}}
00382 bdcl:c {{border-collapse} {collapse}}
00383 bdcl:s {{border-collapse} {separate}}
00384 bdc {{border-color} {#{|000}}}
00385 bdc:t {{border-color} {transparent}}
00386 bdi {{border-image} {url({|})}}
00387 bdi:n {{border-image} {none}}
00388 bdti {{border-top-image} {url({|})}}
00389 bdti:n {{border-top-image} {none}}
00390 bdri {{border-right-image} {url({|})}}
00391 bdri:n {{border-right-image} {none}}
00392 bdbi {{border-bottom-image} {url({|})}}
00393 bdbi:n {{border-bottom-image} {none}}
00394 bdli {{border-left-image} {url({|})}}
00395 bdli:n {{border-left-image} {none}}
00396 bdci {{border-corner-image} {url({|})}}
00397 bdci:n {{border-corner-image} {none}}
00398 bdci:c {{border-corner-image} {continue}}
00399 bdtli {{border-top-left-image} {url({|})}}
00400 bdtli:n {{border-top-left-image} {none}}
00401 bdtli:c {{border-top-left-image} {continue}}
00402 bdtri {{border-top-right-image} {url({|})}}
00403 bdtri:n {{border-top-right-image} {none}}
00404 bdtri:c {{border-top-right-image} {continue}}
00405 bdbri {{border-bottom-right-image} {url({|})}}
00406 bdbri:n {{border-bottom-right-image} {none}}
00407 bdbri:c {{border-bottom-right-image} {continue}}
00408 bdbli {{border-bottom-left-image} {url({|})}}
00409 bdbli:n {{border-bottom-left-image} {none}}
00410 bdbli:c {{border-bottom-left-image} {continue}}
00411 bdf {{border-fit} {{|repeat}}}
00412 bdf:c {{border-fit} {clip}}
00413 bdf:r {{border-fit} {repeat}}
00414 bdf:sc {{border-fit} {scale}}
00415 bdf:st {{border-fit} {stretch}}
00416 bdf:ow {{border-fit} {overwrite}}
00417 bdf:of {{border-fit} {overflow}}
00418 bdf:sp {{border-fit} {space}}
00419 bdlen {{border-length} {{|}}}
00420 bdlen:a {{border-length} {auto}}
00421 bdsp {{border-spacing} {{|}}}
00422 bds {{border-style} {{|}}}
00423 bds:n {{border-style} {none}}
00424 bds:h {{border-style} {hidden}}
00425 bds:dt {{border-style} {dotted}}
00426 bds:ds {{border-style} {dashed}}
00427 bds:s {{border-style} {solid}}
00428 bds:db {{border-style} {double}}
00429 bds:dtds {{border-style} {dot-dash}}
00430 bds:dtdtds {{border-style} {dot-dot-dash}}
00431 bds:w {{border-style} {wave}}
00432 bds:g {{border-style} {groove}}
00433 bds:r {{border-style} {ridge}}
00434 bds:i {{border-style} {inset}}
00435 bds:o {{border-style} {outset}}
00436 bdw {{border-width} {{|}}}
00437 bdt {{border-top} {{|}}}
00438 bt {{border-top} {{|}}}
00439 bdt+ {{border-top} {{|1px} {|solid} {|#000}}}
00440 bdt:n {{border-top} {none}}
00441 bdtw {{border-top-width} {{|}}}
00442 bdts {{border-top-style} {{|}}}
00443 bdts:n {{border-top-style} {none}}
00444 bdtc {{border-top-color} {#{|000}}}
00445 bdtc:t {{border-top-color} {transparent}}
00446 bdr {{border-right} {{|}}}
00447 br {{border-right} {{|}}}
00448 bdr+ {{border-right} {{|1px} {|solid} {|#000}}}
00449 bdr:n {{border-right} {none}}
00450 bdrw {{border-right-width} {{|}}}
00451 bdrst {{border-right-style} {{|}}}
00452 bdrst:n {{border-right-style} {none}}
00453 bdrc {{border-right-color} {#{|000}}}
00454 bdrc:t {{border-right-color} {transparent}}
00455 bdb {{border-bottom} {{|}}}
00456 bb {{border-bottom} {{|}}}
00457 bdb+ {{border-bottom} {{|1px} {|solid} {|#000}}}
00458 bdb:n {{border-bottom} {none}}
00459 bdbw {{border-bottom-width} {{|}}}
00460 bdbs {{border-bottom-style} {{|}}}
00461 bdbs:n {{border-bottom-style} {none}}
00462 bdbc {{border-bottom-color} {#{|000}}}
00463 bdbc:t {{border-bottom-color} {transparent}}
00464 bdl {{border-left} {{|}}}
00465 bl {{border-left} {{|}}}
00466 bdl+ {{border-left} {{|1px} {|solid} {|#000}}}
00467 bdl:n {{border-left} {none}}
00468 bdlw {{border-left-width} {{|}}}
00469 bdls {{border-left-style} {{|}}}
00470 bdls:n {{border-left-style} {none}}
00471 bdlc {{border-left-color} {#{|000}}}
00472 bdlc:t {{border-left-color} {transparent}}
00473 bdrs {{border-radius} {{|}}}
00474 bdtrrs {{border-top-right-radius} {{|}}}
00475 bdtlrs {{border-top-left-radius} {{|}}}
00476 bdbrrs {{border-bottom-right-radius} {{|}}}
00477 bdblrs {{border-bottom-left-radius} {{|}}}
00478 lis {{list-style} {{|}}}
00479 lis:n {{list-style} {none}}
00480 lisp {{list-style-position} {{|}}}
00481 lisp:i {{list-style-position} {inside}}
00482 lisp:o {{list-style-position} {outside}}
00483 list {{list-style-type} {{|}}}
00484 list:n {{list-style-type} {none}}
00485 list:d {{list-style-type} {disc}}
00486 list:c {{list-style-type} {circle}}
00487 list:s {{list-style-type} {square}}
00488 list:dc {{list-style-type} {decimal}}
00489 list:dclz {{list-style-type} {decimal-leading-zero}}
00490 list:lr {{list-style-type} {lower-roman}}
00491 list:ur {{list-style-type} {upper-roman}}
00492 lisi {{list-style-image} {{|}}}
00493 lisi:n {{list-style-image} {none}}
00494 pgbb {{page-break-before} {{|}}}
00495 pgbb:au {{page-break-before} {auto}}
00496 pgbb:al {{page-break-before} {always}}
00497 pgbb:l {{page-break-before} {left}}
00498 pgbb:r {{page-break-before} {right}}
00499 pgbi {{page-break-inside} {{|}}}
00500 pgbi:au {{page-break-inside} {auto}}
00501 pgbi:av {{page-break-inside} {avoid}}
00502 pgba {{page-break-after} {{|}}}
00503 pgba:au {{page-break-after} {auto}}
00504 pgba:al {{page-break-after} {always}}
00505 pgba:l {{page-break-after} {left}}
00506 pgba:r {{page-break-after} {right}}
00507 orp {{orphans} {{|}}}
00508 wid {{widows} {{|}}}
00509 anim {{animation} {{|}}}
00510 anim- {{animation} {{|name} {|duration} {|timing-function} {|delay} {|iteration} {|direction} {|fill-mode}}}
00511 animdel {{animation-delay} {{|time}}}
00512 animdir {{animation-direction} {{|normal}}}
00513 animdir:a {{animation-direction} {alternate}}
00514 animdir:ar {{animation-direction} {alternate-reverse}}
00515 animdir:n {{animation-direction} {normal}}
00516 animdir:r {{animation-direction} {reverse}}
00517 animdur {{animation-duration} {{|0}s}}
00518 animfm {{animation-fill-mode} {{|both}}}
00519 animfm:b {{animation-fill-mode} {backwards}}
00520 animfm:bt {{animation-fill-mode} {both}}
00521 animfm:bh {{animation-fill-mode} {both}}
00522 animfm:f {{animation-fill-mode} {forwards}}
00523 animic {{animation-iteration-count} {{|1}}}
00524 animic:i {{animation-iteration-count} {infinite}}
00525 animn {{animation-name} {{|none}}}
00526 animps {{animation-play-state} {{|running}}}
00527 animps:p {{animation-play-state} {paused}}
00528 animps:r {{animation-play-state} {running}}
00529 animtf {{animation-timing-function} {{|linear}}}
00530 animtf:cb {{animation-timing-function} {cubic-bezier({|0.1}, {|0.7}, {|1.0}, {|0.1})}}
00531 animtf:e {{animation-timing-function} {ease}}
00532 animtf:ei {{animation-timing-function} {ease-in}}
00533 animtf:eio {{animation-timing-function} {ease-in-out}}
00534 animtf:eo {{animation-timing-function} {ease-out}}
00535 animtf:l {{animation-timing-function} {linear}}
00536 ap {{appearance} {${none}}}
00537 bg:ie {{filter:progid} {DXImateTransform.Microsoft.AlphaImageLoader(src='{|x}.png', sizingMethod='{|crop}')}}
00538 colm {{columns} {{|}}}
00539 colmc {{column-count} {{|}}}
00540 colmf {{column-fill} {{|}}}
00541 colmg {{column-gap} {{|}}}
00542 colmr {{column-rule} {{|}}}
00543 colmrc {{column-rule-color} {{|}}}
00544 colmrs {{column-rule-style} {{|}}}
00545 colmrw {{column-rule-width} {{|}}}
00546 colms {{column-span} {{|}}}
00547 colmw {{column-width} {{|}}}
00548 mar {{max-resolution} {{|res}}}
00549 mir {{min-resolution} {{|res}}}
00550 op:ie {{filter:progid} {DXImageTransform.Microsoft.Alpha(Opacity=100)}}
00551 op:ms {{-ms-filter} {'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)'}}
00552 ori {{orientation} {{|}}}
00553 ori:l {{orientation} {landscape}}
00554 ori:p {{orientation} {portrait}}
00555 tov {{text-overflow} {{|ellipsis}}}
00556 tov:c {{text-overflow} {clip}}
00557 tov:e {{text-overflow} {ellipsis}}
00558 trf {{transform} {{|}}}
00559 trf:r {{transform} {rotate({|angle})}}
00560 trf:sc {{transform} {scale({|x}, {|y})}}
00561 trf:scx {{transform} {scaleX({|x})}}
00562 trf:scy {{transform} {scaleY({|y})}}
00563 trf:skx {{transform} {skewX({|angle})}}
00564 trf:sky {{transform} {skewY({|angle})}}
00565 trf:t {{transform} {translate({|x}, {|y})}}
00566 trf:tx {{transform} {translateX({|x})}}
00567 trf:ty {{transform} {translateY({|y})}}
00568 trfo {{transform-origin} {{|}}}
00569 trfs {{transform-style} {{|preserve-3d}}}
00570 trs {{transition} {{|prop} {|time}}}
00571 trsde {{transition-delay} {{|time}}}
00572 trsdu {{transition-duration} {{|time}}}
00573 trsp {{transition-property} {{|prop}}}
00574 trstf {{transition-timing-function} {{|tfunc}}}
00575 us {{user-select} {${none}}}
00576 wfsm {{-webkit-font-smoothing} {{|antialiased}}}
00577 wfsm:a {{-webkit-font-smoothing} {antialiased}}
00578 wfsm:n {{-webkit-font-smoothing} {none}}
00579 wfsm:s {{-webkit-font-smoothing} {subpixel-antialiased}}
00580 wfsm:sa {{-webkit-font-smoothing} {subpixel-antialiased}}
00581 }
00582
00583 array set vendor_props {
00584 accelerator {s}
00585 accesskey {o}
00586 animation {wo}
00587 animation-delay {wmo}
00588 animation-direction {wmo}
00589 animation-duration {wmo}
00590 animation-fill-mode {wmo}
00591 animation-iteration-count {wmo}
00592 animation-name {wmo}
00593 animation-play-state {wmo}
00594 animation-timing-function {wmo}
00595 appearance {wm}
00596 backface-visibility {wms}
00597 background-clip {wm}
00598 background-composite {w}
00599 background-inline-policy {m}
00600 background-origin {w}
00601 background-position-y {s}
00602 background-size {w}
00603 behavior {s}
00604 binding {m}
00605 block-progression {s}
00606 border-bottom-colors {m}
00607 border-fit {w}
00608 border-horizontal-spacing {w}
00609 border-image {wmo}
00610 border-left-colors {m}
00611 border-radius {wm}
00612 border-right-colors {m}
00613 border-top-colors {m}
00614 border-vertical-spacing {w}
00615 box-align {wms}
00616 box-direction {wms}
00617 box-flex {wms}
00618 box-flex-group {w}
00619 box-line-progression {s}
00620 box-lines {ws}
00621 box-ordinal-group {wms}
00622 box-orient {wms}
00623 box-pack {wms}
00624 box-reflect {w}
00625 box-shadow {wm}
00626 box-sizing {wm}
00627 color-correction {w}
00628 column-break-after {w}
00629 column-break-before {w}
00630 column-break-inside {w}
00631 column-count {wm}
00632 column-gap {wm}
00633 column-rule-color {wm}
00634 column-rule-style {wm}
00635 column-rule-width {wm}
00636 column-span {w}
00637 column-width {wm}
00638 content-zoom-boundary {s}
00639 content-zoom-boundary-max {s}
00640 content-zoom-boundary-min {s}
00641 content-zoom-chaining {s}
00642 content-zoom-snap {s}
00643 content-zoom-snap-points {s}
00644 content-zoom-snap-type {s}
00645 content-zooming {s}
00646 dashboard-region {wo}
00647 filter {s}
00648 float-edge {m}
00649 flow-from {s}
00650 flow-into {s}
00651 font-feature-settings {ms}
00652 font-language-override {m}
00653 font-smooting {w}
00654 force-broken-image-icon {m}
00655 grid-column {s}
00656 grid-column-align {s}
00657 grid-column-span {s}
00658 grid-columns {s}
00659 grid-layer {s}
00660 grid-row {s}
00661 grid-row-align {s}
00662 grid-row-span {s}
00663 grid-rows {s}
00664 high-contrast-adjust {s}
00665 highlight {w}
00666 hyphenate-character {w}
00667 hyphenate-limit-after {w}
00668 hyphenate-limit-before {w}
00669 hyphenate-limit-chars {s}
00670 hyphenate-limit-lines {s}
00671 hyphenate-limit-zone {s}
00672 hyphens {wms}
00673 image-region {m}
00674 ime-mode {s}
00675 input-format {o}
00676 input-required {o}
00677 interpolation-mode {s}
00678 layout-flow {s}
00679 layout-grid {s}
00680 layout-grid-char {s}
00681 layout-grid-line {s}
00682 layout-grid-mode {s}
00683 layout-grid-type {s}
00684 line-box-contain {w}
00685 line-break {ws}
00686 line-clamp {w}
00687 link {o}
00688 link-source {o}
00689 locale {w}
00690 margin-after-collapse {w}
00691 margin-before-collapse {w}
00692 marquee-dir {o}
00693 marquee-direction {w}
00694 marquee-increment {w}
00695 marquee-loop {o}
00696 marquee-repetition {w}
00697 marquee-speed {o}
00698 marquee-style {wo}
00699 mask-attachment {w}
00700 mask-box-image {w}
00701 mask-box-image-outset {w}
00702 mask-box-image-repeat {w}
00703 mask-box-image-slice {w}
00704 mask-box-image-source {w}
00705 mask-box-image-width {w}
00706 mask-clip {w}
00707 mask-composite {w}
00708 mask-image {w}
00709 mask-origin {w}
00710 mask-position {w}
00711 mask-repeat {w}
00712 mask-size {w}
00713 nbsp-mode {w}
00714 object-fit {o}
00715 object-position {o}
00716 orient {m}
00717 outline-radius-bottomleft {m}
00718 outline-radius-bottomright {m}
00719 outline-radius-topleft {m}
00720 outline-radius-topright {m}
00721 overflow-style {s}
00722 perspective {wms}
00723 perspective-origin {wms}
00724 perspective-origin-x {s}
00725 perspective-origin-y {s}
00726 rtl-ordering {w}
00727 scroll-boundary {s}
00728 scroll-boundary-bottom {s}
00729 scroll-boundary-left {s}
00730 scroll-boundary-right {s}
00731 scroll-boundary-top {s}
00732 scroll-chaining {s}
00733 scroll-rails {s}
00734 scroll-snap-points-x {s}
00735 scroll-snap-points-y {s}
00736 scroll-snap-type {s}
00737 scroll-snap-x {s}
00738 scroll-snap-y {s}
00739 scrollbar-arrow-color {s}
00740 scrollbar-base-color {s}
00741 scrollbar-darkshadow-color {s}
00742 scrollbar-face-color {s}
00743 scrollbar-highlight-color {s}
00744 scrollbar-shadow-color {s}
00745 scrollbar-track-color {s}
00746 stack-sizing {m}
00747 svg-shadow {w}
00748 tab-size {mo}
00749 table-baseline {o}
00750 text-align-last {s}
00751 text-autospace {s}
00752 text-blink {m}
00753 text-combine {w}
00754 text-decoration-color {m}
00755 text-decoration-line {m}
00756 text-decoration-style {m}
00757 text-decorations-in-effect {w}
00758 text-emphasis-color {w}
00759 text-emphasis-position {w}
00760 text-emphasis-style {w}
00761 text-fill-color {w}
00762 text-justify {s}
00763 text-kashida-space {s}
00764 text-orientation {w}
00765 text-security {w}
00766 text-size-adjust {ms}
00767 text-stroke-color {w}
00768 text-stroke-width {w}
00769 text-overflow {s}
00770 text-underline-position {s}
00771 touch-action {s}
00772 transform {wmso}
00773 transform-origin {wmso}
00774 transform-origin-x {s}
00775 transform-origin-y {s}
00776 transform-origin-z {s}
00777 transform-style {wms}
00778 transition {wmso}
00779 transition-delay {wmso}
00780 transition-duration {wmso}
00781 transition-property {wmso}
00782 transition-timing-function {wmso}
00783 user-drag {w}
00784 user-focus {m}
00785 user-input {m}
00786 user-modify {wm}
00787 user-select {wms}
00788 window-shadow {m}
00789 word-break {s}
00790 wrap-flow {s}
00791 wrap-margin {s}
00792 wrap-through {s}
00793 writing-mode {ws}
00794
00795 }
00796
00797 array set unitless {
00798 z-index 1
00799 line-height 1
00800 opacity 1
00801 font-weight 1
00802 }
00803
00804 array set prefixes {
00805 w -webkit-
00806 m -moz-
00807 s -ms-
00808 o -o-
00809 }
00810
00811 array set keyword_aliases {
00812 a auto
00813 i inherit
00814 s solid
00815 da dashed
00816 do dotted
00817 t transparent
00818 }
00819
00820 ######################################################################
00821 # Parses the given Emmet string and returns the generated code version.
00822 proc parse {str} {
00823
00824 set lines [list]
00825 set line [list]
00826
00827 # Set the string to lowercase
00828 set str [string tolower $str]
00829
00830 while {[string length $str] > 0} {
00831 if {[regexp {^-([wmso]+)-([a-z:]+\+?|[a-z]+:-)(.*)$} $str -> prefix word str]} {
00832 lappend line word $word prefix $prefix
00833 } elseif {[regexp {^-([a-z:]+\+?|[a-z]+:-)(.*)$} $str -> word str]} {
00834 lappend line hyphen 1 word $word
00835 } elseif {[regexp {^([a-z:]+\+?|[a-z]+:-)(.*)$} $str -> word str]} {
00836 lappend line word $word
00837 } elseif {[regexp {^(-?[0-9]+\.[0-9]+)(.*)$} $str -> num str]} {
00838 lappend line float $num
00839 } elseif {[regexp {^(-?[0-9]+)(.*)$} $str -> num str]} {
00840 lappend line number $num
00841 } elseif {[regexp {^#([0-9a-fA-F]+)(.*)$} $str -> color str]} {
00842 switch [string length $color] {
00843 1 { lappend line color #[string repeat $color 6] }
00844 2 { lappend line color #[string repeat $color 3] }
00845 3 { lappend line color #[string repeat [string index $color 0] 2][string repeat [string index $color 1] 2][string repeat [string index $color 2] 2] }
00846 6 { lappend line color #$color }
00847 }
00848 } elseif {[regexp {^!(.*)$} $str -> str]} {
00849 lappend line important {}
00850 } else {
00851 if {$line ne [list]} {
00852 lappend lines [generate_line $line]
00853 }
00854 set line [list]
00855 set str [string range $str 1 end]
00856 }
00857 }
00858
00859 if {$line ne ""} {
00860 lappend lines [generate_line $line]
00861 }
00862
00863 return [join $lines \n]
00864
00865 }
00866
00867 ######################################################################
00868 # Returns the CSS that is generates from the given line list.
00869 proc generate_line {line_list} {
00870
00871 variable lookup
00872 variable unitless
00873 variable prefixes
00874 variable keyword_aliases
00875
00876 set line [list]
00877 set important 0
00878 set property ""
00879 set values ""
00880 set val ""
00881 set suffix ""
00882 set suffix_needed 0
00883 set prefix_list [list]
00884 set hyphen 0
00885
00886 foreach {type value} $line_list {
00887 switch $type {
00888 number -
00889 float {
00890 set val $value
00891 if {($property eq "") || ![info exists unitless($property)]} {
00892 if {$type eq "number"} {
00893 set suffix [preferences::get {Emmet/CSSIntUnit}]
00894 } else {
00895 set suffix [preferences::get {Emmet/CSSFloatUnit}]
00896 }
00897 set suffix_needed 1
00898 } else {
00899 set values [insert_value $values $val]
00900 }
00901 }
00902 hyphen {
00903 set hyphen 1
00904 }
00905 prefix {
00906 set prefix_list [list]
00907 foreach prefix [split $value {}] {
00908 if {[info exists prefixes($prefix)]} {
00909 lappend prefix_list $prefixes($prefix)
00910 }
00911 }
00912 }
00913 word {
00914 if {$suffix_needed} {
00915 switch $value {
00916 - { set suffix "px" }
00917 p { set suffix "%" }
00918 e { set suffix "em" }
00919 x { set suffix "ex" }
00920 r { set suffix "rem" }
00921 default { set suffix $value }
00922 }
00923 set suffix_needed 0
00924 if {$property ne ""} {
00925 set values [insert_value $values $val$suffix]
00926 } else {
00927 lappend line $value$suffix
00928 }
00929 } elseif {[info exists lookup($value)]} {
00930 lassign $lookup($value) property values
00931 set prefix_list [get_prefix_list $property $hyphen]
00932 } elseif {[preferences::get {Emmet/CSSFuzzySearch}] && \
00933 [set tmp [lsearch -glob -inline [lsort [array names lookup]] [join [split $value {}] *]]] ne ""} {
00934 lassign $lookup($tmp) property values
00935 set prefix_list [get_prefix_list $property $hyphen]
00936 } elseif {[info exists keyword_aliases($value)]} {
00937 set values [insert_value $values $keyword_aliases($value)]
00938 } elseif {$property ne ""} {
00939 set values [insert_value $values $value]
00940 } else {
00941 lappend line $value
00942 }
00943 }
00944 color {
00945 if {$suffix_needed} {
00946 if {$property ne ""} {
00947 set values [insert_value $values $val$suffix]
00948 } else {
00949 lappend line $val$suffix
00950 }
00951 set suffix_needed 0
00952 }
00953 switch [string tolower [preferences::get {Emmet/CSSColorCase}]] {
00954 upper { set value [string toupper $value] }
00955 lower { set value [string tolower $value] }
00956 }
00957 if {[preferences::get {Emmet/CSSColorShort}]} {
00958 set value [shorten_color $value]
00959 }
00960 if {$property ne ""} {
00961 set values [insert_value $values $value]
00962 } else {
00963 lappend line $value
00964 }
00965 }
00966 important {
00967 set important 1
00968 }
00969 }
00970 }
00971
00972 if {$suffix_needed} {
00973 if {$property ne ""} {
00974 set values [insert_value $values $val$suffix]
00975 } else {
00976 lappend line $val$suffix
00977 }
00978 }
00979
00980 if {$important} {
00981 if {$property ne ""} {
00982 set values [insert_value $values "!important"]
00983 } else {
00984 lappend line "!important"
00985 }
00986 }
00987
00988 if {$property ne ""} {
00989 set index 1
00990 while {[regexp {(.*?)\{\|(.*?)\}(.*)$} $values -> before value after]} {
00991 if {$value eq ""} {
00992 set values "$before\$$index$after"
00993 } else {
00994 set values "$before\${$index:$value}$after"
00995 }
00996 incr index
00997 }
00998 set lines [list]
00999 set endstr [preferences::get {Emmet/CSSPropertyEnd}]
01000 set separator [preferences::get {Emmet/CSSValueSeparator}]
01001 lappend prefix_list ""
01002 foreach prefix $prefix_list {
01003 lappend lines "$prefix$property$separator$values$endstr"
01004 }
01005 return [join $lines \n]
01006 } else {
01007 return [join $line " "]
01008 }
01009
01010 }
01011
01012 ######################################################################
01013 # Inserts the given value into the given value list.
01014 proc insert_value {values value} {
01015
01016 if {[regexp {^(.*)\{\|.*?\}(.*)$} $values -> before after]} {
01017 return $before$value$after
01018 }
01019
01020 return "$values $value"
01021
01022 }
01023
01024 ######################################################################
01025 # Returns the prefix_list for the given property.
01026 proc get_prefix_list {property hyphen} {
01027
01028 variable vendor_props
01029 variable prefixes
01030
01031 set prefix_list [list]
01032
01033 if {[preferences::get {Emmet/CSSAutoInsertVendorPrefixes}] || $hyphen} {
01034
01035 # Get the override values from preferences
01036 set overrides(w) [preferences::get {Emmet/CSSWebkitPropertiesAddon}]
01037 set overrides(m) [preferences::get {Emmet/CSSMozPropertiesAddon}]
01038 set overrides(s) [preferences::get {Emmet/CSSMSPropertiesAddon}]
01039 set overrides(o) [preferences::get {Emmet/CSSOPropertiesAddon}]
01040
01041 # If the value is in vender_props and its not removed via preferences
01042 if {[info exists vendor_props($property)]} {
01043 foreach prefix [split $vendor_props($property) {}] {
01044 if {[lsearch $overrides($prefix) -$property] == -1} {
01045 lappend prefix_list $prefixes($prefix)
01046 }
01047 }
01048
01049 # Otherwise, check to see if the property was added by the user
01050 } else {
01051 foreach prefix [list w m s o] {
01052 if {[lsearch $overrides($prefix) $property] != -1} {
01053 lappend prefix_list $prefixes($prefix)
01054 }
01055 }
01056 }
01057
01058 # If there are no matching prefixes, use them all
01059 if {([llength $prefix_list] == 0) && $hyphen} {
01060 foreach prefix [list w m s o] {
01061 lappend prefix_list $prefixes($prefix)
01062 }
01063 }
01064
01065 }
01066
01067 return $prefix_list
01068
01069 }
01070
01071 ######################################################################
01072 # Shortens the given color value to a three character color (if possible).
01073 proc shorten_color {value} {
01074
01075 if {[string repeat [string index $value 0] 6] eq $value} {
01076 return [string range $value 0 2]
01077 } elseif {[string range $value 0 2] eq [string range $value 3 5]} {
01078 return [string range $value 0 2]
01079 }
01080
01081 return $value
01082
01083 }
01084
01085 ######################################################################
01086 # Returns a list structure containing positional information for the next
01087 # or previous ruleset. This procedure returns a Tcl list containing the
01088 # following contents:
01089 #
01090 # - starting index of selector
01091 # - index of curly bracket starting the properties
01092 # - index of curly bracket ending the properties
01093 # - index of the beginning of the ruleset
01094 proc get_ruleset {txt args} {
01095
01096 array set opts {
01097 -dir "next"
01098 -startpos "insert"
01099 }
01100 array set opts $args
01101
01102 # Find the starting position
01103 if {$opts(-dir) eq "prev"} {
01104 if {[$txt compare $opts(-startpos) == 1.0]} {
01105 return ""
01106 } elseif {[set start_index [lindex [$txt tag prevrange __curlyR $opts(-startpos)-1c] 1]] eq ""} {
01107 set start_index 1.0
01108 }
01109 } else {
01110 if {[set start_index [lindex [$txt tag nextrange __curlyR $opts(-startpos)] 1]] eq ""} {
01111 return ""
01112 }
01113 }
01114
01115 # Find the first non-commented, non-whitespace character
01116 set start $start_index
01117 while {($start ne "") && ([set start [$txt search -forwards -regexp -- {\S} $start end]] ne "") && [$txt is incomment $start_index]} {
01118 set comment_tag [lsearch -inline [$txt tag names $start] __comstr*]
01119 set start [lindex [$txt tag prevrange $comment_tag $start+1c] 1]
01120 }
01121
01122 if {($start ne "") && ([set end_index [lindex [$txt tag nextrange __curlyR $start] 1]] ne "")} {
01123 set curly_index [lindex [$txt tag nextrange __curlyL $start_index] 0]
01124 return [list $start $curly_index $end_index $start_index]
01125 }
01126
01127 return ""
01128
01129 }
01130
01131 ######################################################################
01132 # Returns the current ruleset positional information if we are currently
01133 # within a ruleset; otherwise, returns the empty string.
01134 proc in_ruleset {txt} {
01135
01136 # Returns the previous ruleset
01137 if {([set ruleset [get_ruleset $txt -dir prev -startpos "insert+1c"]] ne "") && [$txt compare insert < [lindex $ruleset 2]]} {
01138 return $ruleset
01139 }
01140
01141 return ""
01142
01143 }
01144
01145 ######################################################################
01146 # Returns the CSS selector portion of the given ruleset. The ruleset must
01147 # be a valid location within the text widget.
01148 proc get_selector {txt ruleset} {
01149
01150 set str [string trim [$txt get {*}[lrange $ruleset 0 1]]]
01151
01152 if {[set index [$txt search -forward -count lengths -- $str [lindex $ruleset 0]]] ne ""} {
01153 return [list $index [$txt index "$index+[lindex $lengths 0]c"]]
01154 }
01155
01156 return ""
01157
01158 }
01159
01160 ######################################################################
01161 # Given the starting position of the property name and its corresponding
01162 # colon index, return a list containing the starting/ending index of the
01163 # property name and the starting/ending index of the property value.
01164 proc get_property_retval {txt namepos colonpos endpos} {
01165
01166 set name [string trim [string range [$txt get $namepos $colonpos] 0 end-1]]
01167 set endpos [$txt search -forward -- {;} $colonpos $endpos]
01168 set full_value [$txt get $colonpos+1c $endpos]
01169 set start_offset [expr ([string length $full_value] - [string length [string trimleft $full_value]]) + 1]
01170
01171 return [list $namepos [$txt index "$namepos+[string length $name]c"] [$txt index "$colonpos+${start_offset}c"] $endpos]
01172
01173 }
01174
01175 ######################################################################
01176 # Returns a list containing all of the properties of the given ruleset.
01177 proc get_properties {txt ruleset} {
01178
01179 set props [list]
01180 set i 0
01181 foreach index [$txt search -all -forward -count lengths -regexp -- {[a-zA-Z0-9_-]+\s*:} {*}[lrange $ruleset 1 2]] {
01182 lappend props [get_property_retval $txt $index [$txt index "$index+[lindex $lengths $i]c"] [lindex $ruleset 2]]
01183 incr i
01184 }
01185
01186 return $props
01187
01188 }
01189
01190 ######################################################################
01191 # Get the positional information for the ruleset property in the given
01192 # direction.
01193 proc get_property {txt ruleset args} {
01194
01195 array set opts {
01196 -dir "next"
01197 }
01198 array set opts $args
01199
01200 # Get the positional information of the property name
01201 if {$opts(-dir) eq "next"} {
01202 set start [expr {[$txt compare insert < [lindex $ruleset 1]] ? [lindex $ruleset 1] : "insert"}]
01203 set index [$txt search -forward -count lengths -regexp -- {[a-zA-Z0-9_-]+\s*:} $start [lindex $ruleset 2]]
01204 } elseif {[$txt compare insert < [lindex $ruleset 1]]} {
01205 return ""
01206 } else {
01207 set start [expr {[$txt compare [lindex $ruleset 2] < insert] ? [lindex $ruleset 2] : "insert"}]
01208 set index [$txt search -backward -count lengths -regexp -- {[a-zA-Z0-9_-]+\s*:} $start [lindex $ruleset 1]]
01209 }
01210
01211 if {$index ne ""} {
01212 return [get_property_retval $txt $index [$txt index "$index+[lindex $lengths 0]c"] [lindex $ruleset 2]]
01213 }
01214
01215 return ""
01216
01217 }
01218
01219 ######################################################################
01220 # Returns true if the insertion cursor is within a url() call.
01221 proc in_url {txt} {
01222
01223 if {[set ruleset [in_ruleset $txt]] ne ""} {
01224 if {[set index [$txt search -forward -count lengths -regexp -- {url\(.+?\)} {*}[lrange $ruleset 2 3]]] ne ""} {
01225 return [expr {[$txt compare "$index+4c" <= insert] && [$txt compare insert < "$index+[expr [lindex $lengths 0] - 1]c"]}]
01226 }
01227 }
01228
01229 return 0
01230
01231 }
01232
01233 ######################################################################
01234 proc select_property_token {txt dir selected startpos endpos} {
01235
01236 set select 0
01237 set pattern [expr {($dir eq "next") ? {^\s*(\S+)} : {(\S+)\s*$}}]
01238 set value [$txt get "$startpos+1c" "$endpos-1c"]
01239
01240
01241
01242 }
01243
01244 ######################################################################
01245 # Returns the number of items that are found in the value string that
01246 # will be parsed.
01247 proc get_item_count {dir str depth} {
01248
01249 if {$dir eq "next"} {
01250 if {$depth == 0} {
01251 set retval [regexp -all -- {\S+(\(.*?\))?} $str]
01252 return $retval
01253 } else {
01254 set retval [llength [split $str ,]]
01255 return $retval
01256 }
01257 } else {
01258 if {[string map {, {} { } {} \( {}} $str] ne $str} {
01259 return 2
01260 }
01261 return 1
01262 }
01263
01264 }
01265
01266 ######################################################################
01267 # Select the next thing in the property list.
01268 proc select_property_value {txt dir depth selected startpos endpos} {
01269
01270 set select 0
01271 set pattern [expr {($dir eq "next") ? {^\s*(\S+(\(.*?\))?)} : {(\S+(\(.*?\))?)\s*$}}]
01272 set value [$txt get $startpos $endpos]
01273
01274 # Figure out if we need to select the first selectable item in the value list
01275 if {((($dir eq "next") && ($selected eq [list $startpos $endpos])) || \
01276 (($dir eq "prev") && ($selected ne "") && [$txt compare [lindex $selected 0] > $endpos])) && \
01277 ([get_item_count $dir $value $depth] > 1)} {
01278 set select 1
01279 }
01280
01281 while {[regexp -indices $pattern $value -> match fnargs]} {
01282 set value_start [$txt index "$startpos+[lindex $match 0]c"]
01283 set value_end [$txt index "$startpos+[expr [lindex $match 1] + 1]c"]
01284 if {[lindex $fnargs 0] != -1} {
01285 set fnargs_start [$txt index "$startpos+[expr [lindex $fnargs 0] + 1]c"]
01286 set fnargs_end [$txt index "$startpos+[lindex $fnargs 1]c"]
01287 }
01288 if {$dir eq "next"} {
01289
01290 if {$select} {
01291 ::tk::TextSetCursor $txt $value_end
01292 $txt tag add sel $value_start $value_end
01293 return 1
01294 } elseif {$selected eq [list $value_start $value_end]} {
01295 if {[lindex $fnargs 0] != -1} {
01296 ::tk::TextSetCursor $txt $fnargs_end
01297 $txt tag add sel $fnargs_start $fnargs_end
01298 return 1
01299 }
01300 set select 1
01301 } elseif {([lindex $fnargs 0] != -1) && ($selected ne "") && \
01302 [$txt compare $fnargs_start <= [lindex $selected 0]] && \
01303 [$txt compare [lindex $selected 1] <= $fnargs_end]} {
01304 if {[select_property_value $txt $dir [expr $depth + 1] $selected $fnargs_start $fnargs_end]} {
01305 return 1
01306 } else {
01307 set select 1
01308 }
01309 }
01310 set value [string range $value [expr [lindex $match 1] + 1] end]
01311 set startpos [$txt index "$startpos+[expr [lindex $match 1] + 1]c"]
01312
01313 } else {
01314
01315 # If the current item is a function call
01316 if {([lindex $fnargs 0] != -1) && ($selected ne "")} {
01317 if {[$txt compare $fnargs_start == [lindex $selected 0]] && \
01318 [$txt compare $fnargs_end == [lindex $selected 1]]} {
01319 ::tk::TextSetCursor $txt $value_end
01320 $txt tag add sel $value_start $value_end
01321 return 1
01322 } elseif {$select || \
01323 ([$txt compare $fnargs_start <= [lindex $selected 0]] && \
01324 [$txt compare [lindex $selected 1] <= $fnargs_end])} {
01325 if {[select_property_value $txt $dir [expr $depth + 1] $selected $fnargs_start $fnargs_end]} {
01326 return 1
01327 } else {
01328 ::tk::TextSetCursor $txt $fnargs_end
01329 $txt tag add sel $fnargs_start $fnargs_end
01330 return 1
01331 }
01332 }
01333 } elseif {$select} {
01334 ::tk::TextSetCursor $txt $value_end
01335 $txt tag add sel $value_start $value_end
01336 return 1
01337 } elseif {$selected eq [list $value_start $value_end]} {
01338 set select 1
01339 }
01340 set value [string range $value 0 [expr [lindex $match 0] - 1]]
01341
01342 }
01343 }
01344
01345 if {$select} {
01346 return 0
01347 } else {
01348 ::tk::TextSetCursor $txt $endpos
01349 $txt tag add sel $startpos $endpos
01350 return 1
01351 }
01352
01353 }
01354
01355 ######################################################################
01356 # Selects the next/previous CSS item.
01357 proc select_item {txt dir} {
01358
01359 # Get the proper ruleset
01360 if {[set ruleset [in_ruleset $txt]] eq ""} {
01361 if {[set ruleset [get_ruleset $txt -dir $dir]] eq ""} {
01362 return
01363 }
01364 }
01365
01366 # Check to see if anything is selected
01367 if {[llength [set selected [$txt tag ranges sel]]] != 2} {
01368 set selected ""
01369 }
01370
01371 if {$dir eq "next"} {
01372
01373 while {$ruleset ne ""} {
01374
01375 lassign [get_selector $txt $ruleset] selector_start selector_end
01376
01377 if {[$txt compare insert <= $selector_start]} {
01378 ::tk::TextSetCursor $txt.t $selector_end
01379 $txt tag add sel $selector_start $selector_end
01380 return
01381
01382 } else {
01383 foreach prop [get_properties $txt $ruleset] {
01384 if {[$txt compare insert > [lindex $prop 3]]} {
01385 continue
01386 }
01387 if {[$txt compare insert < [lindex $prop 2]]} {
01388 ::tk::TextSetCursor $txt [lindex $prop 3]
01389 $txt tag add sel [lindex $prop 0] [lindex $prop 3]
01390 return
01391 } elseif {($selected eq [list [lindex $prop 0] [lindex $prop 3]]) || ($selected eq "")} {
01392 ::tk::TextSetCursor $txt [lindex $prop 3]
01393 $txt tag add sel [lindex $prop 2] [lindex $prop 3]
01394 return
01395 } elseif {[select_property_value $txt next 0 $selected {*}[lrange $prop 2 3]]} {
01396 return
01397 }
01398 }
01399 }
01400
01401 # Get the next ruleset
01402 set ruleset [get_ruleset $txt -dir next -startpos [lindex $ruleset 0]]
01403
01404 }
01405
01406 } else {
01407
01408 while {$ruleset ne ""} {
01409
01410 foreach prop [lreverse [get_properties $txt $ruleset]] {
01411 if {($selected eq [list [lindex $prop 0] [lindex $prop 3]]) || [$txt compare insert < [lindex $prop 0]]} {
01412 continue
01413 }
01414 if {($selected eq [list [lindex $prop 2] [$txt index [lindex $prop 3]]]) || \
01415 (($selected eq "") && [$txt compare insert > [lindex $prop 0]])} {
01416 ::tk::TextSetCursor $txt [lindex $prop 3]
01417 $txt tag add sel [lindex $prop 0] [lindex $prop 3]
01418 return
01419 } elseif {[select_property_value $txt prev 0 $selected {*}[lrange $prop 2 3]]} {
01420 return
01421 } elseif {[$txt compare insert > [lindex $prop 2]]} {
01422 ::tk::TextSetCursor $txt [lindex $prop 3]
01423 $txt tag add sel [lindex $prop 2] [lindex $prop 3]
01424 return
01425 }
01426 }
01427
01428 lassign [get_selector $txt $ruleset] selector_start selector_end
01429
01430 if {(($selected ne [list $selector_start $selector_end]) && [$txt compare insert > [lindex $ruleset 0]]) || \
01431 ($selected eq [list [lindex $prop 0] [lindex $prop 3]])} {
01432 ::tk::TextSetCursor $txt $selector_end
01433 $txt tag add sel $selector_start $selector_end
01434 return
01435 }
01436
01437 # Get the previous ruleset
01438 set ruleset [get_ruleset $txt -dir prev -startpos [lindex $ruleset 3]-1c]
01439
01440 }
01441
01442 }
01443
01444 }
01445
01446 ######################################################################
01447 # Toggles comment of ruleset or property.
01448 proc toggle_comment {txt} {
01449
01450 if {[ctext::inBlockComment $txt insert]} {
01451
01452 set tag [lsearch -inline [$txt tag names insert] __comstr1c*]
01453 lassign [$txt tag prevrange $tag "insert+1c"] startpos endpos
01454
01455 if {[$txt get $endpos-3c] eq " "} {
01456 $txt delete "$endpos-3c" $endpos
01457 } else {
01458 $txt delete "$endpos-2c" $endpos
01459 }
01460
01461 if {[$txt get $startpos+2c] eq " "} {
01462 $txt delete $startpos "$startpos+3c"
01463 } else {
01464 $txt delete $startpos "$startpos+2c"
01465 }
01466
01467 } else {
01468
01469 # We will only comment something if we are within a ruleset
01470 if {[set ruleset [in_ruleset $txt]] eq ""} {
01471 return
01472 }
01473
01474 # If the cursor is within the selector area, comment the entire ruleset
01475 if {[$txt compare [lindex $ruleset 0] <= insert] && [$txt compare insert <= [lindex $ruleset 1]]} {
01476 $txt insert [lindex $ruleset 2] " */"
01477 $txt insert [lindex $ruleset 0] "/* "
01478 } elseif {[set prop [get_property $txt $ruleset -dir prev]] ne ""} {
01479 $txt insert "[lindex $prop 3]+1c" " */"
01480 $txt insert [lindex $prop 0] "/* "
01481 }
01482
01483 }
01484
01485 }
01486
01487 ######################################################################
01488 # If the cursor is within a url() call inside of a ruleset property
01489 # value, adds/updates the height and width properties to match the
01490 # image size.
01491 proc update_image_size {txt} {
01492
01493 if {[set ruleset [in_ruleset $txt]] eq ""} {
01494 return
01495 }
01496
01497 # Get the list of properties associated with the ruleset
01498 set props [get_properties $txt $ruleset]
01499
01500 # Check to see if the insertion cursor is within a url() call
01501 foreach prop $props {
01502 if {[set index [$txt search -count lengths -regexp -- {url\(.+?\)} {*}[lrange $prop 2 3]]] ne ""} {
01503 if {[$txt compare "$index+4c" <= insert] && [$txt compare insert < "$index+[lindex $lengths 0]c"]} {
01504 set url [string trim [$txt get "$index+4c" "$index+[expr [lindex $lengths 0] - 1]c"]]
01505 if {![catch { exec php [file join $::tke_dir lib image_size.php] $url } rc]} {
01506 lassign $rc width height
01507 if {![string is integer $width]} {
01508 return
01509 }
01510 set found(url) $prop
01511 }
01512 }
01513 } else {
01514 set name [$txt get {*}[lrange $prop 0 1]]
01515 if {($name eq "height") || ($name eq "width")} {
01516 set found($name) $prop
01517 }
01518 }
01519 }
01520
01521 # If we didn't find our URL, just return
01522 if {![info exists found(url)]} {
01523 return
01524 }
01525
01526 # Replace/insert width/height values
01527 if {[info exists found(width)]} {
01528 $txt replace {*}[lrange $found(width) 2 3] " ${width}px"
01529 if {[info exists found(height)]} {
01530 $txt replace {*}[lrange $found(height) 2 3] " ${height}px"
01531 } else {
01532 set num_spaces [lindex [split [lindex $found(width) 0] .] 1]
01533 set spaces [expr {($num_spaces > 0) ? [string repeat " " $num_spaces] : ""}]
01534 $txt insert "[lindex $found(width) 3] lineend" "\n${spaces}height: ${height}px;"
01535 }
01536 } elseif {[info exists found(height)]} {
01537 set num_spaces [lindex [split [lindex $found(height) 0] .] 1]
01538 set spaces [expr {($num_spaces > 0) ? [string repeat " " $num_spaces] : ""}]
01539 $txt replace {*}[lrange $found(height) 2 3] " ${height}px"
01540 $txt insert "[lindex $found(height) 0] linestart" "${spaces}width: ${width}px;\n"
01541 } else {
01542 set num_spaces [lindex [split [lindex $found(url) 0] .] 1]
01543 set spaces [expr {($num_spaces > 0) ? [string repeat " " $num_spaces] : ""}]
01544 $txt insert "[lindex $found(url) 3] lineend" "\n${spaces}width: ${width}px;\n${spaces}height: ${height}px;"
01545 }
01546
01547 }
01548
01549 ######################################################################
01550 # Returns the basename of the given property name.
01551 proc get_basename {name} {
01552
01553 regexp {^-(webkit|moz|ms|o)-(.*)$} [set basename $name] -> dummy basename
01554
01555 return $basename
01556
01557 }
01558
01559 ######################################################################
01560 # Attempt to reflect the current value.
01561 proc reflect_css_value {} {
01562
01563 # Get the current text widget
01564 set txt [gui::current_txt]
01565
01566 # Get the current ruleset
01567 if {[set ruleset [in_ruleset $txt]] eq ""} {
01568 return
01569 }
01570
01571 # Get the current property
01572 if {[set prop [get_property $txt $ruleset -dir prev]] eq ""} {
01573 return
01574 }
01575
01576 if {[$txt compare [lindex $prop 0] < insert] && [$txt compare insert < [lindex $prop 3]]} {
01577 set name [$txt get {*}[lrange $prop 0 1]]
01578 set basename [get_basename $name]
01579 set value [$txt get {*}[lrange $prop 2 3]]
01580 foreach prop [lreverse [get_properties $txt $ruleset]] {
01581 set pname [$txt get {*}[lrange $prop 0 1]]
01582 if {($name ne $pname) && ([get_basename $pname] eq $basename)} {
01583 $txt replace {*}[lrange $prop 2 3] $value
01584 }
01585 }
01586 }
01587
01588 }
01589
01590 ######################################################################
01591 # Runs encode/decode image to data:URL in CSS.
01592 proc encode_decode_image_to_data_url {txt args} {
01593
01594 # Get the current ruleset
01595 if {[set ruleset [in_ruleset $txt]] eq ""} {
01596 return
01597 }
01598
01599 # Update the URL
01600 if {[set ruleset [in_ruleset $txt]] ne ""} {
01601 if {[set index [$txt search -forward -count lengths -regexp -- {url\(.+?\)} {*}[lrange $ruleset 2 3]]] ne ""} {
01602 if {[$txt compare "$index+4c" <= insert] && [$txt compare insert < "$index+[expr [lindex $lengths 0] - 1]c"]} {
01603 set startpos "$index+4c"
01604 set endpos "$index+[expr [lindex $lengths 0] - 1]c"
01605 set url [$txt get $startpos $endpos]
01606 emmet::replace_data_url $txt $startpos $endpos $url {*}$args
01607 }
01608 }
01609 }
01610
01611 }
01612
01613 }