cssParser.js 169 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is mozilla.org code.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1998
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * emk <VYV03354@nifty.ne.jp>
  23. * Daniel Glazman <glazman@netscape.com>
  24. * L. David Baron <dbaron@dbaron.org>
  25. * Boris Zbarsky <bzbarsky@mit.edu>
  26. * Mats Palmgren <mats.palmgren@bredband.net>
  27. * Christian Biesinger <cbiesinger@web.de>
  28. * Jeff Walden <jwalden+code@mit.edu>
  29. * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>, Collabora Ltd.
  30. * Siraj Razick <siraj.razick@collabora.co.uk>, Collabora Ltd.
  31. * Daniel Glazman <daniel.glazman@disruptive-innovations.com>
  32. *
  33. * Alternatively, the contents of this file may be used under the terms of
  34. * either of the GNU General Public License Version 2 or later (the "GPL"),
  35. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  36. * in which case the provisions of the GPL or the LGPL are applicable instead
  37. * of those above. If you wish to allow use of your version of this file only
  38. * under the terms of either the GPL or the LGPL, and not to allow others to
  39. * use your version of this file under the terms of the MPL, indicate your
  40. * decision by deleting the provisions above and replace them with the notice
  41. * and other provisions required by the GPL or the LGPL. If you do not delete
  42. * the provisions above, a recipient may use your version of this file under
  43. * the terms of any one of the MPL, the GPL or the LGPL.
  44. *
  45. * ***** END LICENSE BLOCK ***** */
  46. ;
  47. var kCHARSET_RULE_MISSING_SEMICOLON = "Missing semicolon at the end of @charset rule";
  48. var kCHARSET_RULE_CHARSET_IS_STRING = "The charset in the @charset rule should be a string";
  49. var kCHARSET_RULE_MISSING_WS = "Missing mandatory whitespace after @charset";
  50. var kIMPORT_RULE_MISSING_URL = "Missing URL in @import rule";
  51. var kURL_EOF = "Unexpected end of stylesheet";
  52. var kURL_WS_INSIDE = "Multiple tokens inside a url() notation";
  53. var kVARIABLES_RULE_POSITION = "@variables rule invalid at this position in the stylesheet";
  54. var kIMPORT_RULE_POSITION = "@import rule invalid at this position in the stylesheet";
  55. var kNAMESPACE_RULE_POSITION = "@namespace rule invalid at this position in the stylesheet";
  56. var kCHARSET_RULE_CHARSET_SOF = "@charset rule invalid at this position in the stylesheet";
  57. var kUNKNOWN_AT_RULE = "Unknow @-rule";
  58. /* FROM http://peter.sh/data/vendor-prefixed-css.php?js=1 */
  59. var kENGINES = [
  60. "webkit",
  61. "presto",
  62. "trident",
  63. "generic"
  64. ];
  65. var kCSS_VENDOR_VALUES = {
  66. "-moz-box": {"webkit": "-webkit-box", "presto": "", "trident": "", "generic": "box" },
  67. "-moz-inline-box": {"webkit": "-webkit-inline-box", "presto": "", "trident": "", "generic": "inline-box" },
  68. "-moz-initial": {"webkit": "", "presto": "", "trident": "", "generic": "initial" },
  69. "-moz-linear-gradient": {"webkit20110101": FilterLinearGradientForOutput,
  70. "webkit": FilterLinearGradientForOutput,
  71. "presto": "",
  72. "trident": "",
  73. "generic": FilterLinearGradientForOutput },
  74. "-moz-radial-gradient": {"webkit20110101": FilterRadialGradientForOutput,
  75. "webkit": FilterRadialGradientForOutput,
  76. "presto": "",
  77. "trident": "",
  78. "generic": FilterRadialGradientForOutput },
  79. "-moz-repeating-linear-gradient": {"webkit20110101": "",
  80. "webkit": FilterRepeatingGradientForOutput,
  81. "presto": "",
  82. "trident": "",
  83. "generic": FilterRepeatingGradientForOutput },
  84. "-moz-repeating-radial-gradient": {"webkit20110101": "",
  85. "webkit": FilterRepeatingGradientForOutput,
  86. "presto": "",
  87. "trident": "",
  88. "generic": FilterRepeatingGradientForOutput }
  89. };
  90. var kCSS_VENDOR_PREFIXES = {"lastUpdate":1304175007,"properties":[{"gecko":"","webkit":"","presto":"","trident":"-ms-accelerator","status":"P"},
  91. {"gecko":"","webkit":"","presto":"-wap-accesskey","trident":"","status":""},
  92. {"gecko":"-moz-animation","webkit":"-webkit-animation","presto":"","trident":"","status":"WD"},
  93. {"gecko":"-moz-animation-delay","webkit":"-webkit-animation-delay","presto":"","trident":"","status":"WD"},
  94. {"gecko":"-moz-animation-direction","webkit":"-webkit-animation-direction","presto":"","trident":"","status":"WD"},
  95. {"gecko":"-moz-animation-duration","webkit":"-webkit-animation-duration","presto":"","trident":"","status":"WD"},
  96. {"gecko":"-moz-animation-fill-mode","webkit":"-webkit-animation-fill-mode","presto":"","trident":"","status":"ED"},
  97. {"gecko":"-moz-animation-iteration-count","webkit":"-webkit-animation-iteration-count","presto":"","trident":"","status":"WD"},
  98. {"gecko":"-moz-animation-name","webkit":"-webkit-animation-name","presto":"","trident":"","status":"WD"},
  99. {"gecko":"-moz-animation-play-state","webkit":"-webkit-animation-play-state","presto":"","trident":"","status":"WD"},
  100. {"gecko":"-moz-animation-timing-function","webkit":"-webkit-animation-timing-function","presto":"","trident":"","status":"WD"},
  101. {"gecko":"-moz-appearance","webkit":"-webkit-appearance","presto":"","trident":"","status":"CR"},
  102. {"gecko":"","webkit":"-webkit-backface-visibility","presto":"","trident":"","status":"WD"},
  103. {"gecko":"background-clip","webkit":"-webkit-background-clip","presto":"background-clip","trident":"background-clip","status":"WD"},
  104. {"gecko":"","webkit":"-webkit-background-composite","presto":"","trident":"","status":""},
  105. {"gecko":"-moz-background-inline-policy","webkit":"","presto":"","trident":"","status":"P"},
  106. {"gecko":"background-origin","webkit":"-webkit-background-origin","presto":"background-origin","trident":"background-origin","status":"WD"},
  107. {"gecko":"","webkit":"background-position-x","presto":"","trident":"-ms-background-position-x","status":""},
  108. {"gecko":"","webkit":"background-position-y","presto":"","trident":"-ms-background-position-y","status":""},
  109. {"gecko":"background-size","webkit":"-webkit-background-size","presto":"background-size","trident":"background-size","status":"WD"},
  110. {"gecko":"","webkit":"","presto":"","trident":"-ms-behavior","status":""},
  111. {"gecko":"-moz-binding","webkit":"","presto":"","trident":"","status":"P"},
  112. {"gecko":"","webkit":"","presto":"","trident":"-ms-block-progression","status":""},
  113. {"gecko":"","webkit":"-webkit-border-after","presto":"","trident":"","status":"ED"},
  114. {"gecko":"","webkit":"-webkit-border-after-color","presto":"","trident":"","status":"ED"},
  115. {"gecko":"","webkit":"-webkit-border-after-style","presto":"","trident":"","status":"ED"},
  116. {"gecko":"","webkit":"-webkit-border-after-width","presto":"","trident":"","status":"ED"},
  117. {"gecko":"","webkit":"-webkit-border-before","presto":"","trident":"","status":"ED"},
  118. {"gecko":"","webkit":"-webkit-border-before-color","presto":"","trident":"","status":"ED"},
  119. {"gecko":"","webkit":"-webkit-border-before-style","presto":"","trident":"","status":"ED"},
  120. {"gecko":"","webkit":"-webkit-border-before-width","presto":"","trident":"","status":"ED"},
  121. {"gecko":"-moz-border-bottom-colors","webkit":"","presto":"","trident":"","status":"P"},
  122. {"gecko":"border-bottom-left-radius","webkit":"-webkit-border-bottom-left-radius","presto":"border-bottom-left-radius","trident":"border-bottom-left-radius","status":"WD"},
  123. {"gecko":"","webkit":"-webkit-border-bottom-left-radius = border-bottom-left-radius","presto":"","trident":"","status":""},
  124. {"gecko":"border-bottom-right-radius","webkit":"-webkit-border-bottom-right-radius","presto":"border-bottom-right-radius","trident":"border-bottom-right-radius","status":"WD"},
  125. {"gecko":"","webkit":"-webkit-border-bottom-right-radius = border-bottom-right-radius","presto":"","trident":"","status":""},
  126. {"gecko":"-moz-border-end","webkit":"-webkit-border-end","presto":"","trident":"","status":"ED"},
  127. {"gecko":"-moz-border-end-color","webkit":"-webkit-border-end-color","presto":"","trident":"","status":"ED"},
  128. {"gecko":"-moz-border-end-style","webkit":"-webkit-border-end-style","presto":"","trident":"","status":"ED"},
  129. {"gecko":"-moz-border-end-width","webkit":"-webkit-border-end-width","presto":"","trident":"","status":"ED"},
  130. {"gecko":"","webkit":"-webkit-border-fit","presto":"","trident":"","status":""},
  131. {"gecko":"","webkit":"-webkit-border-horizontal-spacing","presto":"","trident":"","status":""},
  132. {"gecko":"-moz-border-image","webkit":"-webkit-border-image","presto":"-o-border-image","trident":"","status":"WD"},
  133. {"gecko":"-moz-border-left-colors","webkit":"","presto":"","trident":"","status":"P"},
  134. {"gecko":"border-radius","webkit":"-webkit-border-radius","presto":"border-radius","trident":"border-radius","status":"WD"},
  135. {"gecko":"-moz-border-right-colors","webkit":"","presto":"","trident":"","status":"P"},
  136. {"gecko":"-moz-border-start","webkit":"-webkit-border-start","presto":"","trident":"","status":"ED"},
  137. {"gecko":"-moz-border-start-color","webkit":"-webkit-border-start-color","presto":"","trident":"","status":"ED"},
  138. {"gecko":"-moz-border-start-style","webkit":"-webkit-border-start-style","presto":"","trident":"","status":"ED"},
  139. {"gecko":"-moz-border-start-width","webkit":"-webkit-border-start-width","presto":"","trident":"","status":"ED"},
  140. {"gecko":"-moz-border-top-colors","webkit":"","presto":"","trident":"","status":"P"},
  141. {"gecko":"border-top-left-radius","webkit":"-webkit-border-top-left-radius","presto":"border-top-left-radius","trident":"border-top-left-radius","status":"WD"},
  142. {"gecko":"","webkit":"-webkit-border-top-left-radius = border-top-left-radius","presto":"","trident":"","status":""},
  143. {"gecko":"border-top-right-radius","webkit":"-webkit-border-top-right-radius","presto":"border-top-right-radius","trident":"border-top-right-radius","status":"WD"},
  144. {"gecko":"","webkit":"-webkit-border-top-right-radius = border-top-right-radius","presto":"","trident":"","status":""},
  145. {"gecko":"","webkit":"-webkit-border-vertical-spacing","presto":"","trident":"","status":""},
  146. {"gecko":"-moz-box-align","webkit":"-webkit-box-align","presto":"","trident":"-ms-box-align","status":"WD"},
  147. {"gecko":"-moz-box-direction","webkit":"-webkit-box-direction","presto":"","trident":"-ms-box-direction","status":"WD"},
  148. {"gecko":"-moz-box-flex","webkit":"-webkit-box-flex","presto":"","trident":"-ms-box-flex","status":"WD"},
  149. {"gecko":"","webkit":"-webkit-box-flex-group","presto":"","trident":"","status":"WD"},
  150. {"gecko":"","webkit":"","presto":"","trident":"-ms-box-line-progression","status":""},
  151. {"gecko":"","webkit":"-webkit-box-lines","presto":"","trident":"-ms-box-lines","status":"WD"},
  152. {"gecko":"-moz-box-ordinal-group","webkit":"-webkit-box-ordinal-group","presto":"","trident":"-ms-box-ordinal-group","status":"WD"},
  153. {"gecko":"-moz-box-orient","webkit":"-webkit-box-orient","presto":"","trident":"-ms-box-orient","status":"WD"},
  154. {"gecko":"-moz-box-pack","webkit":"-webkit-box-pack","presto":"","trident":"-ms-box-pack","status":"WD"},
  155. {"gecko":"","webkit":"-webkit-box-reflect","presto":"","trident":"","status":""},
  156. {"gecko":"box-shadow","webkit":"-webkit-box-shadow","presto":"box-shadow","trident":"box-shadow","status":"WD"},
  157. {"gecko":"-moz-box-sizing","webkit":"box-sizing","presto":"box-sizing","trident":"","status":"CR"},
  158. {"gecko":"","webkit":"-webkit-box-sizing = box-sizing","presto":"","trident":"","status":""},
  159. {"gecko":"","webkit":"-epub-caption-side = caption-side","presto":"","trident":"","status":""},
  160. {"gecko":"","webkit":"-webkit-color-correction","presto":"","trident":"","status":""},
  161. {"gecko":"","webkit":"-webkit-column-break-after","presto":"","trident":"","status":""},
  162. {"gecko":"","webkit":"-webkit-column-break-before","presto":"","trident":"","status":""},
  163. {"gecko":"","webkit":"-webkit-column-break-inside","presto":"","trident":"","status":""},
  164. {"gecko":"-moz-column-count","webkit":"-webkit-column-count","presto":"column-count","trident":"column-count","status":"CR"},
  165. {"gecko":"-moz-column-gap","webkit":"-webkit-column-gap","presto":"column-gap","trident":"column-gap","status":"CR"},
  166. {"gecko":"-moz-column-rule","webkit":"-webkit-column-rule","presto":"column-rule","trident":"column-rule","status":"CR"},
  167. {"gecko":"-moz-column-rule-color","webkit":"-webkit-column-rule-color","presto":"column-rule-color","trident":"column-rule-color","status":"CR"},
  168. {"gecko":"-moz-column-rule-style","webkit":"-webkit-column-rule-style","presto":"column-rule-style","trident":"column-rule-style","status":"CR"},
  169. {"gecko":"-moz-column-rule-width","webkit":"-webkit-column-rule-width","presto":"column-rule-width","trident":"column-rule-width","status":"CR"},
  170. {"gecko":"","webkit":"-webkit-column-span","presto":"column-span","trident":"column-span","status":"CR"},
  171. {"gecko":"-moz-column-width","webkit":"-webkit-column-width","presto":"column-width","trident":"column-width","status":"CR"},
  172. {"gecko":"","webkit":"-webkit-columns","presto":"columns","trident":"columns","status":"CR"},
  173. {"gecko":"","webkit":"-webkit-dashboard-region","presto":"-apple-dashboard-region","trident":"","status":""},
  174. {"gecko":"filter","webkit":"","presto":"filter","trident":"-ms-filter","status":""},
  175. {"gecko":"-moz-float-edge","webkit":"","presto":"","trident":"","status":"P"},
  176. {"gecko":"","webkit":"","presto":"-o-focus-opacity","trident":"","status":""},
  177. {"gecko":"-moz-font-feature-settings","webkit":"","presto":"","trident":"","status":""},
  178. {"gecko":"-moz-font-language-override","webkit":"","presto":"","trident":"","status":""},
  179. {"gecko":"","webkit":"-webkit-font-size-delta","presto":"","trident":"","status":""},
  180. {"gecko":"","webkit":"-webkit-font-smoothing","presto":"","trident":"","status":""},
  181. {"gecko":"-moz-force-broken-image-icon","webkit":"","presto":"","trident":"","status":""},
  182. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-column","status":"WD"},
  183. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-column-align","status":"WD"},
  184. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-column-span","status":"WD"},
  185. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-columns","status":"WD"},
  186. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-layer","status":"WD"},
  187. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-row","status":"WD"},
  188. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-row-align","status":"WD"},
  189. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-row-span","status":"WD"},
  190. {"gecko":"","webkit":"","presto":"","trident":"-ms-grid-rows","status":"WD"},
  191. {"gecko":"","webkit":"-webkit-highlight","presto":"","trident":"","status":""},
  192. {"gecko":"","webkit":"-webkit-hyphenate-character","presto":"","trident":"","status":"WD"},
  193. {"gecko":"","webkit":"-webkit-hyphenate-limit-after","presto":"","trident":"","status":""},
  194. {"gecko":"","webkit":"-webkit-hyphenate-limit-before","presto":"","trident":"","status":""},
  195. {"gecko":"","webkit":"-webkit-hyphens","presto":"","trident":"","status":"WD"},
  196. {"gecko":"","webkit":"-epub-hyphens = -webkit-hyphens","presto":"","trident":"","status":""},
  197. {"gecko":"-moz-image-region","webkit":"","presto":"","trident":"","status":"P"},
  198. {"gecko":"ime-mode","webkit":"","presto":"","trident":"-ms-ime-mode","status":""},
  199. {"gecko":"","webkit":"","presto":"-wap-input-format","trident":"","status":""},
  200. {"gecko":"","webkit":"","presto":"-wap-input-required","trident":"","status":""},
  201. {"gecko":"","webkit":"","presto":"","trident":"-ms-interpolation-mode","status":""},
  202. {"gecko":"","webkit":"","presto":"-xv-interpret-as","trident":"","status":""},
  203. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-flow","status":""},
  204. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid","status":""},
  205. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-char","status":""},
  206. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-line","status":""},
  207. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-mode","status":""},
  208. {"gecko":"","webkit":"","presto":"","trident":"-ms-layout-grid-type","status":""},
  209. {"gecko":"","webkit":"-webkit-line-box-contain","presto":"","trident":"","status":""},
  210. {"gecko":"","webkit":"-webkit-line-break","presto":"","trident":"-ms-line-break","status":""},
  211. {"gecko":"","webkit":"-webkit-line-clamp","presto":"","trident":"","status":""},
  212. {"gecko":"","webkit":"","presto":"","trident":"-ms-line-grid-mode","status":""},
  213. {"gecko":"","webkit":"","presto":"-o-link","trident":"","status":""},
  214. {"gecko":"","webkit":"","presto":"-o-link-source","trident":"","status":""},
  215. {"gecko":"","webkit":"-webkit-locale","presto":"","trident":"","status":""},
  216. {"gecko":"","webkit":"-webkit-logical-height","presto":"","trident":"","status":"ED"},
  217. {"gecko":"","webkit":"-webkit-logical-width","presto":"","trident":"","status":"ED"},
  218. {"gecko":"","webkit":"-webkit-margin-after","presto":"","trident":"","status":"ED"},
  219. {"gecko":"","webkit":"-webkit-margin-after-collapse","presto":"","trident":"","status":""},
  220. {"gecko":"","webkit":"-webkit-margin-before","presto":"","trident":"","status":"ED"},
  221. {"gecko":"","webkit":"-webkit-margin-before-collapse","presto":"","trident":"","status":""},
  222. {"gecko":"","webkit":"-webkit-margin-bottom-collapse","presto":"","trident":"","status":""},
  223. {"gecko":"","webkit":"-webkit-margin-collapse","presto":"","trident":"","status":""},
  224. {"gecko":"-moz-margin-end","webkit":"-webkit-margin-end","presto":"","trident":"","status":"ED"},
  225. {"gecko":"-moz-margin-start","webkit":"-webkit-margin-start","presto":"","trident":"","status":"ED"},
  226. {"gecko":"","webkit":"-webkit-margin-top-collapse","presto":"","trident":"","status":""},
  227. {"gecko":"","webkit":"-webkit-marquee","presto":"","trident":"","status":""},
  228. {"gecko":"","webkit":"","presto":"-wap-marquee-dir","trident":"","status":""},
  229. {"gecko":"","webkit":"-webkit-marquee-direction","presto":"","trident":"","status":"WD"},
  230. {"gecko":"","webkit":"-webkit-marquee-increment","presto":"","trident":"","status":""},
  231. {"gecko":"","webkit":"","presto":"-wap-marquee-loop","trident":"","status":"WD"},
  232. {"gecko":"","webkit":"-webkit-marquee-repetition","presto":"","trident":"","status":""},
  233. {"gecko":"","webkit":"-webkit-marquee-speed","presto":"-wap-marquee-speed","trident":"","status":"WD"},
  234. {"gecko":"","webkit":"-webkit-marquee-style","presto":"-wap-marquee-style","trident":"","status":"WD"},
  235. {"gecko":"mask","webkit":"-webkit-mask","presto":"mask","trident":"","status":""},
  236. {"gecko":"","webkit":"-webkit-mask-attachment","presto":"","trident":"","status":""},
  237. {"gecko":"","webkit":"-webkit-mask-box-image","presto":"","trident":"","status":""},
  238. {"gecko":"","webkit":"-webkit-mask-clip","presto":"","trident":"","status":""},
  239. {"gecko":"","webkit":"-webkit-mask-composite","presto":"","trident":"","status":""},
  240. {"gecko":"","webkit":"-webkit-mask-image","presto":"","trident":"","status":""},
  241. {"gecko":"","webkit":"-webkit-mask-origin","presto":"","trident":"","status":""},
  242. {"gecko":"","webkit":"-webkit-mask-position","presto":"","trident":"","status":""},
  243. {"gecko":"","webkit":"-webkit-mask-position-x","presto":"","trident":"","status":""},
  244. {"gecko":"","webkit":"-webkit-mask-position-y","presto":"","trident":"","status":""},
  245. {"gecko":"","webkit":"-webkit-mask-repeat","presto":"","trident":"","status":""},
  246. {"gecko":"","webkit":"-webkit-mask-repeat-x","presto":"","trident":"","status":""},
  247. {"gecko":"","webkit":"-webkit-mask-repeat-y","presto":"","trident":"","status":""},
  248. {"gecko":"","webkit":"-webkit-mask-size","presto":"","trident":"","status":""},
  249. {"gecko":"","webkit":"-webkit-match-nearest-mail-blockquote-color","presto":"","trident":"","status":""},
  250. {"gecko":"","webkit":"-webkit-max-logical-height","presto":"","trident":"","status":""},
  251. {"gecko":"","webkit":"-webkit-max-logical-width","presto":"","trident":"","status":"ED"},
  252. {"gecko":"","webkit":"-webkit-min-logical-height","presto":"","trident":"","status":"ED"},
  253. {"gecko":"","webkit":"-webkit-min-logical-width","presto":"","trident":"","status":"ED"},
  254. {"gecko":"","webkit":"","presto":"-o-mini-fold","trident":"","status":""},
  255. {"gecko":"","webkit":"-webkit-nbsp-mode","presto":"","trident":"","status":"P"},
  256. {"gecko":"","webkit":"","presto":"-o-object-fit","trident":"","status":"ED"},
  257. {"gecko":"","webkit":"","presto":"-o-object-position","trident":"","status":"ED"},
  258. {"gecko":"opacity","webkit":"-webkit-opacity","presto":"opacity","trident":"opacity","status":"WD"},
  259. {"gecko":"","webkit":"-webkit-opacity = opacity","presto":"","trident":"","status":""},
  260. {"gecko":"-moz-outline-radius","webkit":"","presto":"","trident":"","status":"P"},
  261. {"gecko":"-moz-outline-radius-bottomleft","webkit":"","presto":"","trident":"","status":"P"},
  262. {"gecko":"-moz-outline-radius-bottomright","webkit":"","presto":"","trident":"","status":"P"},
  263. {"gecko":"-moz-outline-radius-topleft","webkit":"","presto":"","trident":"","status":"P"},
  264. {"gecko":"-moz-outline-radius-topright","webkit":"","presto":"","trident":"","status":"P"},
  265. {"gecko":"overflow-x","webkit":"overflow-x","presto":"overflow-x","trident":"-ms-overflow-x","status":"WD"},
  266. {"gecko":"overflow-y","webkit":"overflow-y","presto":"overflow-y","trident":"-ms-overflow-y","status":"WD"},
  267. {"gecko":"","webkit":"-webkit-padding-after","presto":"","trident":"","status":"ED"},
  268. {"gecko":"","webkit":"-webkit-padding-before","presto":"","trident":"","status":"ED"},
  269. {"gecko":"-moz-padding-end","webkit":"-webkit-padding-end","presto":"","trident":"","status":"ED"},
  270. {"gecko":"-moz-padding-start","webkit":"-webkit-padding-start","presto":"","trident":"","status":"ED"},
  271. {"gecko":"","webkit":"-webkit-perspective","presto":"","trident":"","status":"WD"},
  272. {"gecko":"","webkit":"-webkit-perspective-origin","presto":"","trident":"","status":"WD"},
  273. {"gecko":"","webkit":"-webkit-perspective-origin-x","presto":"","trident":"","status":""},
  274. {"gecko":"","webkit":"-webkit-perspective-origin-y","presto":"","trident":"","status":""},
  275. {"gecko":"","webkit":"","presto":"-xv-phonemes","trident":"","status":""},
  276. {"gecko":"","webkit":"-webkit-rtl-ordering","presto":"","trident":"","status":"P"},
  277. {"gecko":"-moz-script-level","webkit":"","presto":"","trident":"","status":""},
  278. {"gecko":"-moz-script-min-size","webkit":"","presto":"","trident":"","status":""},
  279. {"gecko":"-moz-script-size-multiplier","webkit":"","presto":"","trident":"","status":""},
  280. {"gecko":"","webkit":"","presto":"scrollbar-3dlight-color","trident":"-ms-scrollbar-3dlight-color","status":"P"},
  281. {"gecko":"","webkit":"","presto":"scrollbar-arrow-color","trident":"-ms-scrollbar-arrow-color","status":"P"},
  282. {"gecko":"","webkit":"","presto":"scrollbar-base-color","trident":"-ms-scrollbar-base-color","status":"P"},
  283. {"gecko":"","webkit":"","presto":"scrollbar-darkshadow-color","trident":"-ms-scrollbar-darkshadow-color","status":"P"},
  284. {"gecko":"","webkit":"","presto":"scrollbar-face-color","trident":"-ms-scrollbar-face-color","status":"P"},
  285. {"gecko":"","webkit":"","presto":"scrollbar-highlight-color","trident":"-ms-scrollbar-highlight-color","status":"P"},
  286. {"gecko":"","webkit":"","presto":"scrollbar-shadow-color","trident":"-ms-scrollbar-shadow-color","status":"P"},
  287. {"gecko":"","webkit":"","presto":"scrollbar-track-color","trident":"-ms-scrollbar-track-color","status":"P"},
  288. {"gecko":"-moz-stack-sizing","webkit":"","presto":"","trident":"","status":"P"},
  289. {"gecko":"","webkit":"-webkit-svg-shadow","presto":"","trident":"","status":""},
  290. {"gecko":"-moz-tab-size","webkit":"","presto":"-o-tab-size","trident":"","status":""},
  291. {"gecko":"","webkit":"","presto":"-o-table-baseline","trident":"","status":""},
  292. {"gecko":"","webkit":"-webkit-tap-highlight-color","presto":"","trident":"","status":"P"},
  293. {"gecko":"","webkit":"","presto":"","trident":"-ms-text-align-last","status":"WD"},
  294. {"gecko":"","webkit":"","presto":"","trident":"-ms-text-autospace","status":"WD"},
  295. {"gecko":"-moz-text-blink","webkit":"","presto":"","trident":"","status":""},
  296. {"gecko":"","webkit":"-webkit-text-combine","presto":"","trident":"","status":""},
  297. {"gecko":"","webkit":"-epub-text-combine = -webkit-text-combine","presto":"","trident":"","status":""},
  298. {"gecko":"-moz-text-decoration-color","webkit":"","presto":"","trident":"","status":""},
  299. {"gecko":"-moz-text-decoration-line","webkit":"","presto":"","trident":"","status":""},
  300. {"gecko":"-moz-text-decoration-style","webkit":"","presto":"","trident":"","status":""},
  301. {"gecko":"","webkit":"-webkit-text-decorations-in-effect","presto":"","trident":"","status":""},
  302. {"gecko":"","webkit":"-webkit-text-emphasis","presto":"","trident":"","status":""},
  303. {"gecko":"","webkit":"-epub-text-emphasis = -webkit-text-emphasis","presto":"","trident":"","status":""},
  304. {"gecko":"","webkit":"-webkit-text-emphasis-color","presto":"","trident":"","status":""},
  305. {"gecko":"","webkit":"-epub-text-emphasis-color = -webkit-text-emphasis-color","presto":"","trident":"","status":""},
  306. {"gecko":"","webkit":"-webkit-text-emphasis-position","presto":"","trident":"","status":""},
  307. {"gecko":"","webkit":"-webkit-text-emphasis-style","presto":"","trident":"","status":""},
  308. {"gecko":"","webkit":"-epub-text-emphasis-style = -webkit-text-emphasis-style","presto":"","trident":"","status":""},
  309. {"gecko":"","webkit":"-webkit-text-fill-color","presto":"","trident":"","status":"P"},
  310. {"gecko":"","webkit":"","presto":"","trident":"-ms-text-justify","status":"WD"},
  311. {"gecko":"","webkit":"","presto":"","trident":"-ms-text-kashida-space","status":"P"},
  312. {"gecko":"","webkit":"-webkit-text-orientation","presto":"","trident":"","status":""},
  313. {"gecko":"","webkit":"-epub-text-orientation = -webkit-text-orientation","presto":"","trident":"","status":""},
  314. {"gecko":"","webkit":"text-overflow","presto":"text-overflow","trident":"-ms-text-overflow","status":"WD"},
  315. {"gecko":"","webkit":"-webkit-text-security","presto":"","trident":"","status":"P"},
  316. {"gecko":"","webkit":"-webkit-text-size-adjust","presto":"","trident":"-ms-text-size-adjust","status":""},
  317. {"gecko":"","webkit":"-webkit-text-stroke","presto":"","trident":"","status":"P"},
  318. {"gecko":"","webkit":"-webkit-text-stroke-color","presto":"","trident":"","status":"P"},
  319. {"gecko":"","webkit":"-webkit-text-stroke-width","presto":"","trident":"","status":"P"},
  320. {"gecko":"","webkit":"-epub-text-transform = text-transform","presto":"","trident":"","status":""},
  321. {"gecko":"","webkit":"","presto":"","trident":"-ms-text-underline-position","status":"P"},
  322. {"gecko":"","webkit":"-webkit-touch-callout","presto":"","trident":"","status":"P"},
  323. {"gecko":"-moz-transform","webkit":"-webkit-transform","presto":"-o-transform","trident":"-ms-transform","status":"WD"},
  324. {"gecko":"-moz-transform-origin","webkit":"-webkit-transform-origin","presto":"-o-transform-origin","trident":"-ms-transform-origin","status":"WD"},
  325. {"gecko":"","webkit":"-webkit-transform-origin-x","presto":"","trident":"","status":"P"},
  326. {"gecko":"","webkit":"-webkit-transform-origin-y","presto":"","trident":"","status":"P"},
  327. {"gecko":"","webkit":"-webkit-transform-origin-z","presto":"","trident":"","status":"P"},
  328. {"gecko":"","webkit":"-webkit-transform-style","presto":"","trident":"","status":"WD"},
  329. {"gecko":"-moz-transition","webkit":"-webkit-transition","presto":"-o-transition","trident":"","status":"WD"},
  330. {"gecko":"-moz-transition-delay","webkit":"-webkit-transition-delay","presto":"-o-transition-delay","trident":"","status":"WD"},
  331. {"gecko":"-moz-transition-duration","webkit":"-webkit-transition-duration","presto":"-o-transition-duration","trident":"","status":"WD"},
  332. {"gecko":"-moz-transition-property","webkit":"-webkit-transition-property","presto":"-o-transition-property","trident":"","status":"WD"},
  333. {"gecko":"-moz-transition-timing-function","webkit":"-webkit-transition-timing-function","presto":"-o-transition-timing-function","trident":"","status":"WD"},
  334. {"gecko":"","webkit":"-webkit-user-drag","presto":"","trident":"","status":"P"},
  335. {"gecko":"-moz-user-focus","webkit":"","presto":"","trident":"","status":"P"},
  336. {"gecko":"-moz-user-input","webkit":"","presto":"","trident":"","status":"P"},
  337. {"gecko":"-moz-user-modify","webkit":"-webkit-user-modify","presto":"","trident":"","status":"P"},
  338. {"gecko":"-moz-user-select","webkit":"-webkit-user-select","presto":"","trident":"","status":"P"},
  339. {"gecko":"","webkit":"","presto":"-xv-voice-balance","trident":"","status":""},
  340. {"gecko":"","webkit":"","presto":"-xv-voice-duration","trident":"","status":""},
  341. {"gecko":"","webkit":"","presto":"-xv-voice-pitch","trident":"","status":""},
  342. {"gecko":"","webkit":"","presto":"-xv-voice-pitch-range","trident":"","status":""},
  343. {"gecko":"","webkit":"","presto":"-xv-voice-rate","trident":"","status":""},
  344. {"gecko":"","webkit":"","presto":"-xv-voice-stress","trident":"","status":""},
  345. {"gecko":"","webkit":"","presto":"-xv-voice-volume","trident":"","status":""},
  346. {"gecko":"-moz-window-shadow","webkit":"","presto":"","trident":"","status":"P"},
  347. {"gecko":"","webkit":"word-break","presto":"","trident":"-ms-word-break","status":"WD"},
  348. {"gecko":"","webkit":"-epub-word-break = word-break","presto":"","trident":"","status":""},
  349. {"gecko":"word-wrap","webkit":"word-wrap","presto":"word-wrap","trident":"-ms-word-wrap","status":"WD"},
  350. {"gecko":"","webkit":"-webkit-writing-mode","presto":"writing-mode","trident":"-ms-writing-mode","status":"ED"},
  351. {"gecko":"","webkit":"-epub-writing-mode = -webkit-writing-mode","presto":"","trident":"","status":""},
  352. {"gecko":"","webkit":"zoom","presto":"","trident":"-ms-zoom","status":""}]};
  353. var kCSS_PREFIXED_VALUE = [
  354. {"gecko": "-moz-box", "webkit": "-moz-box", "presto": "", "trident": "", "generic": "box"}
  355. ];
  356. var CssInspector = {
  357. mVENDOR_PREFIXES: null,
  358. kEXPORTS_FOR_GECKO: true,
  359. kEXPORTS_FOR_WEBKIT: true,
  360. kEXPORTS_FOR_PRESTO: true,
  361. kEXPORTS_FOR_TRIDENT: true,
  362. cleanPrefixes: function()
  363. {
  364. this.mVENDOR_PREFIXES = null;
  365. },
  366. prefixesForProperty: function(aProperty)
  367. {
  368. if (!this.mVENDOR_PREFIXES) {
  369. this.mVENDOR_PREFIXES = {};
  370. for (var i = 0; i < kCSS_VENDOR_PREFIXES.properties.length; i++) {
  371. var p = kCSS_VENDOR_PREFIXES.properties[i];
  372. if (p.gecko && (p.webkit || p.presto || p.trident)) {
  373. var o = {};
  374. if (this.kEXPORTS_FOR_GECKO) o[p.gecko] = true;
  375. if (this.kEXPORTS_FOR_WEBKIT && p.webkit) o[p.webkit] = true;
  376. if (this.kEXPORTS_FOR_PRESTO && p.presto) o[p.presto] = true;
  377. if (this.kEXPORTS_FOR_TRIDENT && p.trident) o[p.trident] = true;
  378. this.mVENDOR_PREFIXES[p.gecko] = [];
  379. for (var j in o)
  380. this.mVENDOR_PREFIXES[p.gecko].push(j)
  381. }
  382. }
  383. }
  384. if (aProperty in this.mVENDOR_PREFIXES)
  385. return this.mVENDOR_PREFIXES[aProperty].sort();
  386. return null;
  387. },
  388. parseColorStop: function(parser, token)
  389. {
  390. var color = parser.parseColor(token);
  391. var position = "";
  392. if (!color)
  393. return null;
  394. token = parser.getToken(true, true);
  395. if (token.isPercentage() ||
  396. token.isDimensionOfUnit("cm") ||
  397. token.isDimensionOfUnit("mm") ||
  398. token.isDimensionOfUnit("in") ||
  399. token.isDimensionOfUnit("pc") ||
  400. token.isDimensionOfUnit("px") ||
  401. token.isDimensionOfUnit("em") ||
  402. token.isDimensionOfUnit("ex") ||
  403. token.isDimensionOfUnit("pt")) {
  404. position = token.value;
  405. token = parser.getToken(true, true);
  406. }
  407. return { color: color, position: position }
  408. },
  409. parseGradient: function (parser, token)
  410. {
  411. var isRadial = false;
  412. var gradient = { isRepeating: false };
  413. if (token.isNotNull()) {
  414. if (token.isFunction("-moz-linear-gradient(") ||
  415. token.isFunction("-moz-radial-gradient(") ||
  416. token.isFunction("-moz-repeating-linear-gradient(") ||
  417. token.isFunction("-moz-repeating-radial-gradient(")) {
  418. if (token.isFunction("-moz-radial-gradient(") ||
  419. token.isFunction("-moz-repeating-radial-gradient(")) {
  420. gradient.isRadial = true;
  421. }
  422. if (token.isFunction("-moz-repeating-linear-gradient(") ||
  423. token.isFunction("-moz-repeating-radial-gradient(")) {
  424. gradient.isRepeating = true;
  425. }
  426. token = parser.getToken(true, true);
  427. var haveGradientLine = false;
  428. var foundHorizPosition = false;
  429. var haveAngle = false;
  430. if (token.isAngle()) {
  431. gradient.angle = token.value;
  432. haveGradientLine = true;
  433. haveAngle = true;
  434. token = parser.getToken(true, true);
  435. }
  436. if (token.isLength()
  437. || token.isIdent("top")
  438. || token.isIdent("center")
  439. || token.isIdent("bottom")
  440. || token.isIdent("left")
  441. || token.isIdent("right")) {
  442. haveGradientLine = true;
  443. if (token.isLength()
  444. || token.isIdent("left")
  445. || token.isIdent("right")) {
  446. foundHorizPosition = true;
  447. }
  448. gradient.position = token.value;
  449. token = parser.getToken(true, true);
  450. }
  451. if (haveGradientLine) {
  452. if (!haveAngle && token.isAngle()) { // we have an angle here
  453. gradient.angle = token.value;
  454. haveAngle = true;
  455. token = parser.getToken(true, true);
  456. }
  457. else if (token.isLength()
  458. || (foundHorizPosition && (token.isIdent("top")
  459. || token.isIdent("center")
  460. || token.isIdent("bottom")))
  461. || (!foundHorizPosition && (token.isLength()
  462. || token.isIdent("top")
  463. || token.isIdent("center")
  464. || token.isIdent("bottom")
  465. || token.isIdent("left")
  466. || token.isIdent("right")))) {
  467. gradient.position = ("position" in gradient) ? gradient.position + " ": "";
  468. gradient.position += token.value;
  469. token = parser.getToken(true, true);
  470. }
  471. if (!haveAngle && token.isAngle()) { // we have an angle here
  472. gradient.angle = token.value;
  473. haveAngle = true;
  474. token = parser.getToken(true, true);
  475. }
  476. // we must find a comma here
  477. if (!token.isSymbol(","))
  478. return null;
  479. token = parser.getToken(true, true);
  480. }
  481. // ok... Let's deal with the rest now
  482. if (gradient.isRadial) {
  483. if (token.isIdent("circle") ||
  484. token.isIdent("ellipse")) {
  485. gradient.shape = token.value;
  486. token = parser.getToken(true, true);
  487. }
  488. if (token.isIdent("closest-side") ||
  489. token.isIdent("closest-corner") ||
  490. token.isIdent("farthest-side") ||
  491. token.isIdent("farthest-corner") ||
  492. token.isIdent("contain") ||
  493. token.isIdent("cover")) {
  494. gradient.size = token.value;
  495. token = parser.getToken(true, true);
  496. }
  497. if (!("shape" in gradient) &&
  498. (token.isIdent("circle") ||
  499. token.isIdent("ellipse"))) {
  500. // we can still have the second value...
  501. gradient.shape = token.value;
  502. token = parser.getToken(true, true);
  503. }
  504. if ((("shape" in gradient) || ("size" in gradient)) && !token.isSymbol(","))
  505. return null;
  506. else if (("shape" in gradient) || ("size" in gradient))
  507. token = parser.getToken(true, true);
  508. }
  509. // now color stops...
  510. var stop1 = this.parseColorStop(parser, token);
  511. if (!stop1)
  512. return null;
  513. token = parser.currentToken();
  514. if (!token.isSymbol(","))
  515. return null;
  516. token = parser.getToken(true, true);
  517. var stop2 = this.parseColorStop(parser, token);
  518. if (!stop2)
  519. return null;
  520. token = parser.currentToken();
  521. if (token.isSymbol(",")) {
  522. token = parser.getToken(true, true);
  523. }
  524. // ok we have at least two color stops
  525. gradient.stops = [stop1, stop2];
  526. while (!token.isSymbol(")")) {
  527. var colorstop = this.parseColorStop(parser, token);
  528. if (!colorstop)
  529. return null;
  530. token = parser.currentToken();
  531. if (!token.isSymbol(")") && !token.isSymbol(","))
  532. return null;
  533. if (token.isSymbol(","))
  534. token = parser.getToken(true, true);
  535. gradient.stops.push(colorstop);
  536. }
  537. return gradient;
  538. }
  539. }
  540. return null;
  541. },
  542. parseBoxShadows: function(aString)
  543. {
  544. var parser = new CSSParser();
  545. parser._init();
  546. parser.mPreserveWS = false;
  547. parser.mPreserveComments = false;
  548. parser.mPreservedTokens = [];
  549. parser.mScanner.init(aString);
  550. var shadows = [];
  551. var token = parser.getToken(true, true);
  552. var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px", spreadRadius = "0px";
  553. var inset = false;
  554. while (token.isNotNull()) {
  555. if (token.isIdent("none")) {
  556. shadows.push( { none: true } );
  557. token = parser.getToken(true, true);
  558. }
  559. else {
  560. if (token.isIdent('inset')) {
  561. inset = true;
  562. token = parser.getToken(true, true);
  563. }
  564. if (token.isPercentage() ||
  565. token.isDimensionOfUnit("cm") ||
  566. token.isDimensionOfUnit("mm") ||
  567. token.isDimensionOfUnit("in") ||
  568. token.isDimensionOfUnit("pc") ||
  569. token.isDimensionOfUnit("px") ||
  570. token.isDimensionOfUnit("em") ||
  571. token.isDimensionOfUnit("ex") ||
  572. token.isDimensionOfUnit("pt")) {
  573. var offsetX = token.value;
  574. token = parser.getToken(true, true);
  575. }
  576. else
  577. return [];
  578. if (!inset && token.isIdent('inset')) {
  579. inset = true;
  580. token = parser.getToken(true, true);
  581. }
  582. if (token.isPercentage() ||
  583. token.isDimensionOfUnit("cm") ||
  584. token.isDimensionOfUnit("mm") ||
  585. token.isDimensionOfUnit("in") ||
  586. token.isDimensionOfUnit("pc") ||
  587. token.isDimensionOfUnit("px") ||
  588. token.isDimensionOfUnit("em") ||
  589. token.isDimensionOfUnit("ex") ||
  590. token.isDimensionOfUnit("pt")) {
  591. var offsetX = token.value;
  592. token = parser.getToken(true, true);
  593. }
  594. else
  595. return [];
  596. if (!inset && token.isIdent('inset')) {
  597. inset = true;
  598. token = parser.getToken(true, true);
  599. }
  600. if (token.isPercentage() ||
  601. token.isDimensionOfUnit("cm") ||
  602. token.isDimensionOfUnit("mm") ||
  603. token.isDimensionOfUnit("in") ||
  604. token.isDimensionOfUnit("pc") ||
  605. token.isDimensionOfUnit("px") ||
  606. token.isDimensionOfUnit("em") ||
  607. token.isDimensionOfUnit("ex") ||
  608. token.isDimensionOfUnit("pt")) {
  609. var blurRadius = token.value;
  610. token = parser.getToken(true, true);
  611. }
  612. if (!inset && token.isIdent('inset')) {
  613. inset = true;
  614. token = parser.getToken(true, true);
  615. }
  616. if (token.isPercentage() ||
  617. token.isDimensionOfUnit("cm") ||
  618. token.isDimensionOfUnit("mm") ||
  619. token.isDimensionOfUnit("in") ||
  620. token.isDimensionOfUnit("pc") ||
  621. token.isDimensionOfUnit("px") ||
  622. token.isDimensionOfUnit("em") ||
  623. token.isDimensionOfUnit("ex") ||
  624. token.isDimensionOfUnit("pt")) {
  625. var spreadRadius = token.value;
  626. token = parser.getToken(true, true);
  627. }
  628. if (!inset && token.isIdent('inset')) {
  629. inset = true;
  630. token = parser.getToken(true, true);
  631. }
  632. if (token.isFunction("rgb(") ||
  633. token.isFunction("rgba(") ||
  634. token.isFunction("hsl(") ||
  635. token.isFunction("hsla(") ||
  636. token.isSymbol("#") ||
  637. token.isIdent()) {
  638. var color = parser.parseColor(token);
  639. token = parser.getToken(true, true);
  640. }
  641. if (!inset && token.isIdent('inset')) {
  642. inset = true;
  643. token = parser.getToken(true, true);
  644. }
  645. shadows.push( { none: false,
  646. color: color,
  647. offsetX: offsetX, offsetY: offsetY,
  648. blurRadius: blurRadius,
  649. spreadRadius: spreadRadius } );
  650. if (token.isSymbol(",")) {
  651. inset = false;
  652. color = "";
  653. blurRadius = "0px";
  654. spreadRadius = "0px"
  655. offsetX = "0px";
  656. offsetY = "0px";
  657. token = parser.getToken(true, true);
  658. }
  659. else if (!token.isNotNull())
  660. return shadows;
  661. else
  662. return [];
  663. }
  664. }
  665. return shadows;
  666. },
  667. parseTextShadows: function(aString)
  668. {
  669. var parser = new CSSParser();
  670. parser._init();
  671. parser.mPreserveWS = false;
  672. parser.mPreserveComments = false;
  673. parser.mPreservedTokens = [];
  674. parser.mScanner.init(aString);
  675. var shadows = [];
  676. var token = parser.getToken(true, true);
  677. var color = "", blurRadius = "0px", offsetX = "0px", offsetY = "0px";
  678. while (token.isNotNull()) {
  679. if (token.isIdent("none")) {
  680. shadows.push( { none: true } );
  681. token = parser.getToken(true, true);
  682. }
  683. else {
  684. if (token.isFunction("rgb(") ||
  685. token.isFunction("rgba(") ||
  686. token.isFunction("hsl(") ||
  687. token.isFunction("hsla(") ||
  688. token.isSymbol("#") ||
  689. token.isIdent()) {
  690. var color = parser.parseColor(token);
  691. token = parser.getToken(true, true);
  692. }
  693. if (token.isPercentage() ||
  694. token.isDimensionOfUnit("cm") ||
  695. token.isDimensionOfUnit("mm") ||
  696. token.isDimensionOfUnit("in") ||
  697. token.isDimensionOfUnit("pc") ||
  698. token.isDimensionOfUnit("px") ||
  699. token.isDimensionOfUnit("em") ||
  700. token.isDimensionOfUnit("ex") ||
  701. token.isDimensionOfUnit("pt")) {
  702. var offsetX = token.value;
  703. token = parser.getToken(true, true);
  704. }
  705. else
  706. return [];
  707. if (token.isPercentage() ||
  708. token.isDimensionOfUnit("cm") ||
  709. token.isDimensionOfUnit("mm") ||
  710. token.isDimensionOfUnit("in") ||
  711. token.isDimensionOfUnit("pc") ||
  712. token.isDimensionOfUnit("px") ||
  713. token.isDimensionOfUnit("em") ||
  714. token.isDimensionOfUnit("ex") ||
  715. token.isDimensionOfUnit("pt")) {
  716. var offsetY = token.value;
  717. token = parser.getToken(true, true);
  718. }
  719. else
  720. return [];
  721. if (token.isPercentage() ||
  722. token.isDimensionOfUnit("cm") ||
  723. token.isDimensionOfUnit("mm") ||
  724. token.isDimensionOfUnit("in") ||
  725. token.isDimensionOfUnit("pc") ||
  726. token.isDimensionOfUnit("px") ||
  727. token.isDimensionOfUnit("em") ||
  728. token.isDimensionOfUnit("ex") ||
  729. token.isDimensionOfUnit("pt")) {
  730. var blurRadius = token.value;
  731. token = parser.getToken(true, true);
  732. }
  733. if (!color &&
  734. (token.isFunction("rgb(") ||
  735. token.isFunction("rgba(") ||
  736. token.isFunction("hsl(") ||
  737. token.isFunction("hsla(") ||
  738. token.isSymbol("#") ||
  739. token.isIdent())) {
  740. var color = parser.parseColor(token);
  741. token = parser.getToken(true, true);
  742. }
  743. shadows.push( { none: false,
  744. color: color,
  745. offsetX: offsetX, offsetY: offsetY,
  746. blurRadius: blurRadius } );
  747. if (token.isSymbol(",")) {
  748. color = "";
  749. blurRadius = "0px";
  750. offsetX = "0px";
  751. offsetY = "0px";
  752. token = parser.getToken(true, true);
  753. }
  754. else if (!token.isNotNull())
  755. return shadows;
  756. else
  757. return [];
  758. }
  759. }
  760. return shadows;
  761. },
  762. parseBackgroundImages: function(aString)
  763. {
  764. var parser = new CSSParser();
  765. parser._init();
  766. parser.mPreserveWS = false;
  767. parser.mPreserveComments = false;
  768. parser.mPreservedTokens = [];
  769. parser.mScanner.init(aString);
  770. var backgrounds = [];
  771. var token = parser.getToken(true, true);
  772. while (token.isNotNull()) {
  773. /*if (token.isFunction("rgb(") ||
  774. token.isFunction("rgba(") ||
  775. token.isFunction("hsl(") ||
  776. token.isFunction("hsla(") ||
  777. token.isSymbol("#") ||
  778. token.isIdent()) {
  779. var color = parser.parseColor(token);
  780. backgrounds.push( { type: "color", value: color });
  781. token = parser.getToken(true, true);
  782. }
  783. else */
  784. if (token.isFunction("url(")) {
  785. token = parser.getToken(true, true);
  786. var urlContent = parser.parseURL(token);
  787. backgrounds.push( { type: "image", value: "url(" + urlContent });
  788. token = parser.getToken(true, true);
  789. }
  790. else if (token.isFunction("-moz-linear-gradient(") ||
  791. token.isFunction("-moz-radial-gradient(") ||
  792. token.isFunction("-moz-repeating-linear-gradient(") ||
  793. token.isFunction("-moz-repeating-radial-gradient(")) {
  794. var gradient = this.parseGradient(parser, token);
  795. backgrounds.push( { type: gradient.isRadial ? "radial-gradient" : "linear-gradient", value: gradient });
  796. token = parser.getToken(true, true);
  797. }
  798. else
  799. return null;
  800. if (token.isSymbol(",")) {
  801. token = parser.getToken(true, true);
  802. if (!token.isNotNull())
  803. return null;
  804. }
  805. }
  806. return backgrounds;
  807. },
  808. serializeGradient: function(gradient)
  809. {
  810. var s = gradient.isRadial
  811. ? (gradient.isRepeating ? "-moz-repeating-radial-gradient(" : "-moz-radial-gradient(" )
  812. : (gradient.isRepeating ? "-moz-repeating-linear-gradient(" : "-moz-linear-gradient(" );
  813. if (gradient.angle || gradient.position)
  814. s += (gradient.angle ? gradient.angle + " ": "") +
  815. (gradient.position ? gradient.position : "") +
  816. ", ";
  817. if (gradient.isRadial && (gradient.shape || gradient.size))
  818. s += (gradient.shape ? gradient.shape : "") +
  819. " " +
  820. (gradient.size ? gradient.size : "") +
  821. ", ";
  822. for (var i = 0; i < gradient.stops.length; i++) {
  823. var colorstop = gradient.stops[i];
  824. s += colorstop.color + (colorstop.position ? " " + colorstop.position : "");
  825. if (i != gradient.stops.length -1)
  826. s += ", ";
  827. }
  828. s += ")";
  829. return s;
  830. },
  831. parseBorderImage: function(aString)
  832. {
  833. var parser = new CSSParser();
  834. parser._init();
  835. parser.mPreserveWS = false;
  836. parser.mPreserveComments = false;
  837. parser.mPreservedTokens = [];
  838. parser.mScanner.init(aString);
  839. var borderImage = {url: "", offsets: [], widths: [], sizes: []};
  840. var token = parser.getToken(true, true);
  841. if (token.isFunction("url(")) {
  842. token = parser.getToken(true, true);
  843. var urlContent = parser.parseURL(token);
  844. if (urlContent) {
  845. borderImage.url = urlContent.substr(0, urlContent.length - 1).trim();
  846. if ((borderImage.url[0] == '"' && borderImage.url[borderImage.url.length - 1] == '"') ||
  847. (borderImage.url[0] == "'" && borderImage.url[borderImage.url.length - 1] == "'"))
  848. borderImage.url = borderImage.url.substr(1, borderImage.url.length - 2);
  849. }
  850. else
  851. return null;
  852. }
  853. else
  854. return null;
  855. token = parser.getToken(true, true);
  856. if (token.isNumber() || token.isPercentage())
  857. borderImage.offsets.push(token.value);
  858. else
  859. return null;
  860. var i;
  861. for (i= 0; i < 3; i++) {
  862. token = parser.getToken(true, true);
  863. if (token.isNumber() || token.isPercentage())
  864. borderImage.offsets.push(token.value);
  865. else
  866. break;
  867. }
  868. if (i == 3)
  869. token = parser.getToken(true, true);
  870. if (token.isSymbol("/")) {
  871. token = parser.getToken(true, true);
  872. if (token.isDimension()
  873. || token.isNumber("0")
  874. || (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
  875. borderImage.widths.push(token.value);
  876. else
  877. return null;
  878. for (var i = 0; i < 3; i++) {
  879. token = parser.getToken(true, true);
  880. if (token.isDimension()
  881. || token.isNumber("0")
  882. || (token.isIdent() && token.value in parser.kBORDER_WIDTH_NAMES))
  883. borderImage.widths.push(token.value);
  884. else
  885. break;
  886. }
  887. if (i == 3)
  888. token = parser.getToken(true, true);
  889. }
  890. for (var i = 0; i < 2; i++) {
  891. if (token.isIdent("stretch")
  892. || token.isIdent("repeat")
  893. || token.isIdent("round"))
  894. borderImage.sizes.push(token.value);
  895. else if (!token.isNotNull())
  896. return borderImage;
  897. else
  898. return null;
  899. token = parser.getToken(true, true);
  900. }
  901. if (!token.isNotNull())
  902. return borderImage;
  903. return null;
  904. },
  905. parseMediaQuery: function(aString)
  906. {
  907. var kCONSTRAINTS = {
  908. "width": true,
  909. "min-width": true,
  910. "max-width": true,
  911. "height": true,
  912. "min-height": true,
  913. "max-height": true,
  914. "device-width": true,
  915. "min-device-width": true,
  916. "max-device-width": true,
  917. "device-height": true,
  918. "min-device-height": true,
  919. "max-device-height": true,
  920. "orientation": true,
  921. "aspect-ratio": true,
  922. "min-aspect-ratio": true,
  923. "max-aspect-ratio": true,
  924. "device-aspect-ratio": true,
  925. "min-device-aspect-ratio": true,
  926. "max-device-aspect-ratio": true,
  927. "color": true,
  928. "min-color": true,
  929. "max-color": true,
  930. "color-index": true,
  931. "min-color-index": true,
  932. "max-color-index": true,
  933. "monochrome": true,
  934. "min-monochrome": true,
  935. "max-monochrome": true,
  936. "resolution": true,
  937. "min-resolution": true,
  938. "max-resolution": true,
  939. "scan": true,
  940. "grid": true
  941. };
  942. var parser = new CSSParser();
  943. parser._init();
  944. parser.mPreserveWS = false;
  945. parser.mPreserveComments = false;
  946. parser.mPreservedTokens = [];
  947. parser.mScanner.init(aString);
  948. var m = {amplifier: "", medium: "", constraints: []};
  949. var token = parser.getToken(true, true);
  950. if (token.isIdent("all") ||
  951. token.isIdent("aural") ||
  952. token.isIdent("braille") ||
  953. token.isIdent("handheld") ||
  954. token.isIdent("print") ||
  955. token.isIdent("projection") ||
  956. token.isIdent("screen") ||
  957. token.isIdent("tty") ||
  958. token.isIdent("tv")) {
  959. m.medium = token.value;
  960. token = parser.getToken(true, true);
  961. }
  962. else if (token.isIdent("not") || token.isIdent("only")) {
  963. m.amplifier = token.value;
  964. token = parser.getToken(true, true);
  965. if (token.isIdent("all") ||
  966. token.isIdent("aural") ||
  967. token.isIdent("braille") ||
  968. token.isIdent("handheld") ||
  969. token.isIdent("print") ||
  970. token.isIdent("projection") ||
  971. token.isIdent("screen") ||
  972. token.isIdent("tty") ||
  973. token.isIdent("tv")) {
  974. m.medium = token.value;
  975. token = parser.getToken(true, true);
  976. }
  977. else
  978. return null;
  979. }
  980. if (m.medium) {
  981. if (!token.isNotNull())
  982. return m;
  983. if (token.isIdent("and")) {
  984. token = parser.getToken(true, true);
  985. }
  986. else
  987. return null;
  988. }
  989. while (token.isSymbol("(")) {
  990. token = parser.getToken(true, true);
  991. if (token.isIdent() && (token.value in kCONSTRAINTS)) {
  992. var constraint = token.value;
  993. token = parser.getToken(true, true);
  994. if (token.isSymbol(":")) {
  995. token = parser.getToken(true, true);
  996. var values = [];
  997. while (!token.isSymbol(")")) {
  998. values.push(token.value);
  999. token = parser.getToken(true, true);
  1000. }
  1001. if (token.isSymbol(")")) {
  1002. m.constraints.push({constraint: constraint, value: values});
  1003. token = parser.getToken(true, true);
  1004. if (token.isNotNull()) {
  1005. if (token.isIdent("and")) {
  1006. token = parser.getToken(true, true);
  1007. }
  1008. else
  1009. return null;
  1010. }
  1011. else
  1012. return m;
  1013. }
  1014. else
  1015. return null;
  1016. }
  1017. else if (token.isSymbol(")")) {
  1018. m.constraints.push({constraint: constraint, value: null});
  1019. token = parser.getToken(true, true);
  1020. if (token.isNotNull()) {
  1021. if (token.isIdent("and")) {
  1022. token = parser.getToken(true, true);
  1023. }
  1024. else
  1025. return null;
  1026. }
  1027. else
  1028. return m;
  1029. }
  1030. else
  1031. return null;
  1032. }
  1033. else
  1034. return null;
  1035. }
  1036. return m;
  1037. }
  1038. };
  1039. /************************************************************/
  1040. /************************** JSCSSP **************************/
  1041. /************************************************************/
  1042. var CSS_ESCAPE = '\\';
  1043. var IS_HEX_DIGIT = 1;
  1044. var START_IDENT = 2;
  1045. var IS_IDENT = 4;
  1046. var IS_WHITESPACE = 8;
  1047. var W = IS_WHITESPACE;
  1048. var I = IS_IDENT;
  1049. var S = START_IDENT;
  1050. var SI = IS_IDENT|START_IDENT;
  1051. var XI = IS_IDENT |IS_HEX_DIGIT;
  1052. var XSI = IS_IDENT|START_IDENT|IS_HEX_DIGIT;
  1053. function CSSScanner(aString)
  1054. {
  1055. this.init(aString);
  1056. }
  1057. CSSScanner.prototype = {
  1058. kLexTable: [
  1059. // TAB LF FF CR
  1060. 0, 0, 0, 0, 0, 0, 0, 0, 0, W, W, 0, W, W, 0, 0,
  1061. //
  1062. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1063. // SPC ! " # $ % & ' ( ) * + , - . /
  1064. W, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, I, 0, 0,
  1065. // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
  1066. XI, XI, XI, XI, XI, XI, XI, XI, XI, XI, 0, 0, 0, 0, 0, 0,
  1067. // @ A B C D E F G H I J K L M N O
  1068. 0, XSI,XSI,XSI,XSI,XSI,XSI,SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1069. // P Q R S T U V W X Y Z [ \ ] ^ _
  1070. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, 0, S, 0, 0, SI,
  1071. // ` a b c d e f g h i j k l m n o
  1072. 0, XSI,XSI,XSI,XSI,XSI,XSI,SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1073. // p q r s t u v w x y z { | } ~
  1074. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, 0, 0, 0, 0, 0,
  1075. //
  1076. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1077. //
  1078. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  1079. // ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯
  1080. 0, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1081. // ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿
  1082. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1083. // À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
  1084. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1085. // Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
  1086. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1087. // à á â ã ä å æ ç è é ê ë ì í î ï
  1088. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI,
  1089. // ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
  1090. SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI, SI
  1091. ],
  1092. kHexValues: {
  1093. "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
  1094. "a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15
  1095. },
  1096. mString : "",
  1097. mPos : 0,
  1098. mPreservedPos : [],
  1099. init: function(aString) {
  1100. this.mString = aString;
  1101. this.mPos = 0;
  1102. this.mPreservedPos = [];
  1103. },
  1104. getCurrentPos: function() {
  1105. return this.mPos;
  1106. },
  1107. getAlreadyScanned: function()
  1108. {
  1109. return this.mString.substr(0, this.mPos);
  1110. },
  1111. preserveState: function() {
  1112. this.mPreservedPos.push(this.mPos);
  1113. },
  1114. restoreState: function() {
  1115. if (this.mPreservedPos.length) {
  1116. this.mPos = this.mPreservedPos.pop();
  1117. }
  1118. },
  1119. forgetState: function() {
  1120. if (this.mPreservedPos.length) {
  1121. this.mPreservedPos.pop();
  1122. }
  1123. },
  1124. read: function() {
  1125. if (this.mPos < this.mString.length)
  1126. return this.mString.charAt(this.mPos++);
  1127. return -1;
  1128. },
  1129. peek: function() {
  1130. if (this.mPos < this.mString.length)
  1131. return this.mString.charAt(this.mPos);
  1132. return -1;
  1133. },
  1134. isHexDigit: function(c) {
  1135. var code = c.charCodeAt(0);
  1136. return (code < 256 && (this.kLexTable[code] & IS_HEX_DIGIT) != 0);
  1137. },
  1138. isIdentStart: function(c) {
  1139. var code = c.charCodeAt(0);
  1140. return (code >= 256 || (this.kLexTable[code] & START_IDENT) != 0);
  1141. },
  1142. startsWithIdent: function(aFirstChar, aSecondChar) {
  1143. var code = aFirstChar.charCodeAt(0);
  1144. return this.isIdentStart(aFirstChar) ||
  1145. (aFirstChar == "-" && this.isIdentStart(aSecondChar));
  1146. },
  1147. isIdent: function(c) {
  1148. var code = c.charCodeAt(0);
  1149. return (code >= 256 || (this.kLexTable[code] & IS_IDENT) != 0);
  1150. },
  1151. isSymbol: function(c) {
  1152. var code = c.charCodeAt(0);
  1153. return (this.kLexTable[code] & IS_IDENT) != 1;
  1154. },
  1155. pushback: function() {
  1156. this.mPos--;
  1157. },
  1158. nextHexValue: function() {
  1159. var c = this.read();
  1160. if (c == -1 || !this.isHexDigit(c))
  1161. return new jscsspToken(jscsspToken.NULL_TYPE, null);
  1162. var s = c;
  1163. c = this.read();
  1164. while (c != -1 && this.isHexDigit(c)) {
  1165. s += c;
  1166. c = this.read();
  1167. }
  1168. if (c != -1)
  1169. this.pushback();
  1170. return new jscsspToken(jscsspToken.HEX_TYPE, s);
  1171. },
  1172. gatherEscape: function() {
  1173. var c = this.peek();
  1174. if (c == -1)
  1175. return "";
  1176. if (this.isHexDigit(c)) {
  1177. var code = 0;
  1178. for (var i = 0; i < 6; i++) {
  1179. c = this.read();
  1180. if (this.isHexDigit(c))
  1181. code = code * 16 + this.kHexValues[c.toLowerCase()];
  1182. else if (!this.isHexDigit(c) && !this.isWhiteSpace(c)) {
  1183. this.pushback();
  1184. break;
  1185. }
  1186. else
  1187. break;
  1188. }
  1189. if (i == 6) {
  1190. c = this.peek();
  1191. if (this.isWhiteSpace(c))
  1192. this.read();
  1193. }
  1194. return String.fromCharCode(code);
  1195. }
  1196. c = this.read();
  1197. if (c != "\n")
  1198. return c;
  1199. return "";
  1200. },
  1201. gatherIdent: function(c) {
  1202. var s = "";
  1203. if (c == CSS_ESCAPE)
  1204. s += this.gatherEscape();
  1205. else
  1206. s += c;
  1207. c = this.read();
  1208. if(!this.mMediaQueryMode){
  1209. while (c != -1
  1210. && (this.isIdent(c) || c == CSS_ESCAPE)) {
  1211. if (c == CSS_ESCAPE)
  1212. s += this.gatherEscape();
  1213. else
  1214. s += c;
  1215. c = this.read();
  1216. }
  1217. }
  1218. else {
  1219. while (c != -1
  1220. && c != '{'
  1221. && c != ',') {
  1222. s += c;
  1223. c = this.read();
  1224. }
  1225. }
  1226. if (c != -1)
  1227. this.pushback();
  1228. this.mMediaQueryMode = false;
  1229. return s;
  1230. },
  1231. parseIdent: function(c) {
  1232. var value = this.gatherIdent(c);
  1233. var nextChar = this.peek();
  1234. if (nextChar == "(") {
  1235. value += this.read();
  1236. return new jscsspToken(jscsspToken.FUNCTION_TYPE, value);
  1237. }
  1238. return new jscsspToken(jscsspToken.IDENT_TYPE, value);
  1239. },
  1240. isDigit: function(c) {
  1241. return (c >= '0') && (c <= '9');
  1242. },
  1243. parseComment: function(c) {
  1244. var s = c;
  1245. while ((c = this.read()) != -1) {
  1246. s += c;
  1247. if (c == "*") {
  1248. c = this.read();
  1249. if (c == -1)
  1250. break;
  1251. if (c == "/") {
  1252. s += c;
  1253. break;
  1254. }
  1255. this.pushback();
  1256. }
  1257. }
  1258. return new jscsspToken(jscsspToken.COMMENT_TYPE, s);
  1259. },
  1260. parseNumber: function(c) {
  1261. var s = c;
  1262. var foundDot = false;
  1263. while ((c = this.read()) != -1) {
  1264. if (c == ".") {
  1265. if (foundDot)
  1266. break;
  1267. else {
  1268. s += c;
  1269. foundDot = true;
  1270. }
  1271. } else if (this.isDigit(c))
  1272. s += c;
  1273. else
  1274. break;
  1275. }
  1276. if (c != -1 && this.startsWithIdent(c, this.peek())) { // DIMENSION
  1277. var unit = this.gatherIdent(c);
  1278. s += unit;
  1279. return new jscsspToken(jscsspToken.DIMENSION_TYPE, s, unit);
  1280. }
  1281. else if (c == "%") {
  1282. s += "%";
  1283. return new jscsspToken(jscsspToken.PERCENTAGE_TYPE, s);
  1284. }
  1285. else if (c != -1)
  1286. this.pushback();
  1287. return new jscsspToken(jscsspToken.NUMBER_TYPE, s);
  1288. },
  1289. parseString: function(aStop) {
  1290. var s = aStop;
  1291. var previousChar = aStop;
  1292. var c;
  1293. while ((c = this.read()) != -1) {
  1294. if (c == aStop && previousChar != CSS_ESCAPE) {
  1295. s += c;
  1296. break;
  1297. }
  1298. else if (c == CSS_ESCAPE) {
  1299. c = this.peek();
  1300. if (c == -1)
  1301. break;
  1302. else if (c == "\n" || c == "\r" || c == "\f") {
  1303. d = c;
  1304. c = this.read();
  1305. // special for Opera that preserves \r\n...
  1306. if (d == "\r") {
  1307. c = this.peek();
  1308. if (c == "\n")
  1309. c = this.read();
  1310. }
  1311. }
  1312. else {
  1313. s += this.gatherEscape();
  1314. c = this.peek();
  1315. }
  1316. }
  1317. else if (c == "\n" || c == "\r" || c == "\f") {
  1318. break;
  1319. }
  1320. else
  1321. s += c;
  1322. previousChar = c;
  1323. }
  1324. return new jscsspToken(jscsspToken.STRING_TYPE, s);
  1325. },
  1326. isWhiteSpace: function(c) {
  1327. var code = c.charCodeAt(0);
  1328. return code < 256 && (this.kLexTable[code] & IS_WHITESPACE) != 0;
  1329. },
  1330. eatWhiteSpace: function(c) {
  1331. var s = c;
  1332. while ((c = this.read()) != -1) {
  1333. if (!this.isWhiteSpace(c))
  1334. break;
  1335. s += c;
  1336. }
  1337. if (c != -1)
  1338. this.pushback();
  1339. return s;
  1340. },
  1341. parseAtKeyword: function(c) {
  1342. return new jscsspToken(jscsspToken.ATRULE_TYPE, this.gatherIdent(c));
  1343. },
  1344. nextToken: function() {
  1345. var c = this.read();
  1346. if (c == -1)
  1347. return new jscsspToken(jscsspToken.NULL_TYPE, null);
  1348. if (this.startsWithIdent(c, this.peek()))
  1349. return this.parseIdent(c);
  1350. if (c == '@') {
  1351. var nextChar = this.read();
  1352. if (nextChar != -1) {
  1353. var followingChar = this.peek();
  1354. this.pushback();
  1355. if (this.startsWithIdent(nextChar, followingChar))
  1356. return this.parseAtKeyword(c);
  1357. }
  1358. }
  1359. if (c == "." || c == "+" || c == "-") {
  1360. var nextChar = this.peek();
  1361. if (this.isDigit(nextChar))
  1362. return this.parseNumber(c);
  1363. else if (nextChar == "." && c != ".") {
  1364. firstChar = this.read();
  1365. var secondChar = this.peek();
  1366. this.pushback();
  1367. if (this.isDigit(secondChar))
  1368. return this.parseNumber(c);
  1369. }
  1370. }
  1371. if (this.isDigit(c)) {
  1372. return this.parseNumber(c);
  1373. }
  1374. if (c == "'" || c == '"')
  1375. return this.parseString(c);
  1376. if (this.isWhiteSpace(c)) {
  1377. var s = this.eatWhiteSpace(c);
  1378. return new jscsspToken(jscsspToken.WHITESPACE_TYPE, s);
  1379. }
  1380. if (c == "|" || c == "~" || c == "^" || c == "$" || c == "*") {
  1381. var nextChar = this.read();
  1382. if (nextChar == "=") {
  1383. switch (c) {
  1384. case "~" :
  1385. return new jscsspToken(jscsspToken.INCLUDES_TYPE, "~=");
  1386. case "|" :
  1387. return new jscsspToken(jscsspToken.DASHMATCH_TYPE, "|=");
  1388. case "^" :
  1389. return new jscsspToken(jscsspToken.BEGINSMATCH_TYPE, "^=");
  1390. case "$" :
  1391. return new jscsspToken(jscsspToken.ENDSMATCH_TYPE, "$=");
  1392. case "*" :
  1393. return new jscsspToken(jscsspToken.CONTAINSMATCH_TYPE, "*=");
  1394. default :
  1395. break;
  1396. }
  1397. } else if (nextChar != -1)
  1398. this.pushback();
  1399. }
  1400. if (c == "/" && this.peek() == "*")
  1401. return this.parseComment(c);
  1402. return new jscsspToken(jscsspToken.SYMBOL_TYPE, c);
  1403. }
  1404. };
  1405. function CSSParser(aString)
  1406. {
  1407. this.mToken = null;
  1408. this.mLookAhead = null;
  1409. this.mScanner = new CSSScanner(aString);
  1410. this.mPreserveWS = true;
  1411. this.mPreserveComments = true;
  1412. this.mPreservedTokens = [];
  1413. this.mError = null;
  1414. }
  1415. CSSParser.prototype = {
  1416. _init:function() {
  1417. this.mToken = null;
  1418. this.mLookAhead = null;
  1419. this.mMediaQueryMode = false;
  1420. },
  1421. kINHERIT: "inherit",
  1422. kBORDER_WIDTH_NAMES: {
  1423. "thin": true,
  1424. "medium": true,
  1425. "thick": true
  1426. },
  1427. kBORDER_STYLE_NAMES: {
  1428. "none": true,
  1429. "hidden": true,
  1430. "dotted": true,
  1431. "dashed": true,
  1432. "solid": true,
  1433. "double": true,
  1434. "groove": true,
  1435. "ridge": true,
  1436. "inset": true,
  1437. "outset": true
  1438. },
  1439. kCOLOR_NAMES: {
  1440. "transparent": true,
  1441. "black": true,
  1442. "silver": true,
  1443. "gray": true,
  1444. "white": true,
  1445. "maroon": true,
  1446. "red": true,
  1447. "purple": true,
  1448. "fuchsia": true,
  1449. "green": true,
  1450. "lime": true,
  1451. "olive": true,
  1452. "yellow": true,
  1453. "navy": true,
  1454. "blue": true,
  1455. "teal": true,
  1456. "aqua": true,
  1457. "aliceblue": true,
  1458. "antiquewhite": true,
  1459. "aqua": true,
  1460. "aquamarine": true,
  1461. "azure": true,
  1462. "beige": true,
  1463. "bisque": true,
  1464. "black": true,
  1465. "blanchedalmond": true,
  1466. "blue": true,
  1467. "blueviolet": true,
  1468. "brown": true,
  1469. "burlywood": true,
  1470. "cadetblue": true,
  1471. "chartreuse": true,
  1472. "chocolate": true,
  1473. "coral": true,
  1474. "cornflowerblue": true,
  1475. "cornsilk": true,
  1476. "crimson": true,
  1477. "cyan": true,
  1478. "darkblue": true,
  1479. "darkcyan": true,
  1480. "darkgoldenrod": true,
  1481. "darkgray": true,
  1482. "darkgreen": true,
  1483. "darkgrey": true,
  1484. "darkkhaki": true,
  1485. "darkmagenta": true,
  1486. "darkolivegreen": true,
  1487. "darkorange": true,
  1488. "darkorchid": true,
  1489. "darkred": true,
  1490. "darksalmon": true,
  1491. "darkseagreen": true,
  1492. "darkslateblue": true,
  1493. "darkslategray": true,
  1494. "darkslategrey": true,
  1495. "darkturquoise": true,
  1496. "darkviolet": true,
  1497. "deeppink": true,
  1498. "deepskyblue": true,
  1499. "dimgray": true,
  1500. "dimgrey": true,
  1501. "dodgerblue": true,
  1502. "firebrick": true,
  1503. "floralwhite": true,
  1504. "forestgreen": true,
  1505. "fuchsia": true,
  1506. "gainsboro": true,
  1507. "ghostwhite": true,
  1508. "gold": true,
  1509. "goldenrod": true,
  1510. "gray": true,
  1511. "green": true,
  1512. "greenyellow": true,
  1513. "grey": true,
  1514. "honeydew": true,
  1515. "hotpink": true,
  1516. "indianred": true,
  1517. "indigo": true,
  1518. "ivory": true,
  1519. "khaki": true,
  1520. "lavender": true,
  1521. "lavenderblush": true,
  1522. "lawngreen": true,
  1523. "lemonchiffon": true,
  1524. "lightblue": true,
  1525. "lightcoral": true,
  1526. "lightcyan": true,
  1527. "lightgoldenrodyellow": true,
  1528. "lightgray": true,
  1529. "lightgreen": true,
  1530. "lightgrey": true,
  1531. "lightpink": true,
  1532. "lightsalmon": true,
  1533. "lightseagreen": true,
  1534. "lightskyblue": true,
  1535. "lightslategray": true,
  1536. "lightslategrey": true,
  1537. "lightsteelblue": true,
  1538. "lightyellow": true,
  1539. "lime": true,
  1540. "limegreen": true,
  1541. "linen": true,
  1542. "magenta": true,
  1543. "maroon": true,
  1544. "mediumaquamarine": true,
  1545. "mediumblue": true,
  1546. "mediumorchid": true,
  1547. "mediumpurple": true,
  1548. "mediumseagreen": true,
  1549. "mediumslateblue": true,
  1550. "mediumspringgreen": true,
  1551. "mediumturquoise": true,
  1552. "mediumvioletred": true,
  1553. "midnightblue": true,
  1554. "mintcream": true,
  1555. "mistyrose": true,
  1556. "moccasin": true,
  1557. "navajowhite": true,
  1558. "navy": true,
  1559. "oldlace": true,
  1560. "olive": true,
  1561. "olivedrab": true,
  1562. "orange": true,
  1563. "orangered": true,
  1564. "orchid": true,
  1565. "palegoldenrod": true,
  1566. "palegreen": true,
  1567. "paleturquoise": true,
  1568. "palevioletred": true,
  1569. "papayawhip": true,
  1570. "peachpuff": true,
  1571. "peru": true,
  1572. "pink": true,
  1573. "plum": true,
  1574. "powderblue": true,
  1575. "purple": true,
  1576. "red": true,
  1577. "rosybrown": true,
  1578. "royalblue": true,
  1579. "saddlebrown": true,
  1580. "salmon": true,
  1581. "sandybrown": true,
  1582. "seagreen": true,
  1583. "seashell": true,
  1584. "sienna": true,
  1585. "silver": true,
  1586. "skyblue": true,
  1587. "slateblue": true,
  1588. "slategray": true,
  1589. "slategrey": true,
  1590. "snow": true,
  1591. "springgreen": true,
  1592. "steelblue": true,
  1593. "tan": true,
  1594. "teal": true,
  1595. "thistle": true,
  1596. "tomato": true,
  1597. "turquoise": true,
  1598. "violet": true,
  1599. "wheat": true,
  1600. "white": true,
  1601. "whitesmoke": true,
  1602. "yellow": true,
  1603. "yellowgreen": true,
  1604. "activeborder": true,
  1605. "activecaption": true,
  1606. "appworkspace": true,
  1607. "background": true,
  1608. "buttonface": true,
  1609. "buttonhighlight": true,
  1610. "buttonshadow": true,
  1611. "buttontext": true,
  1612. "captiontext": true,
  1613. "graytext": true,
  1614. "highlight": true,
  1615. "highlighttext": true,
  1616. "inactiveborder": true,
  1617. "inactivecaption": true,
  1618. "inactivecaptiontext": true,
  1619. "infobackground": true,
  1620. "infotext": true,
  1621. "menu": true,
  1622. "menutext": true,
  1623. "scrollbar": true,
  1624. "threeddarkshadow": true,
  1625. "threedface": true,
  1626. "threedhighlight": true,
  1627. "threedlightshadow": true,
  1628. "threedshadow": true,
  1629. "window": true,
  1630. "windowframe": true,
  1631. "windowtext": true
  1632. },
  1633. kLIST_STYLE_TYPE_NAMES: {
  1634. "decimal": true,
  1635. "decimal-leading-zero": true,
  1636. "lower-roman": true,
  1637. "upper-roman": true,
  1638. "georgian": true,
  1639. "armenian": true,
  1640. "lower-latin": true,
  1641. "lower-alpha": true,
  1642. "upper-latin": true,
  1643. "upper-alpha": true,
  1644. "lower-greek": true,
  1645. "disc": true,
  1646. "circle": true,
  1647. "square": true,
  1648. "none": true,
  1649. /* CSS 3 */
  1650. "box": true,
  1651. "check": true,
  1652. "diamond": true,
  1653. "hyphen": true,
  1654. "lower-armenian": true,
  1655. "cjk-ideographic": true,
  1656. "ethiopic-numeric": true,
  1657. "hebrew": true,
  1658. "japanese-formal": true,
  1659. "japanese-informal": true,
  1660. "simp-chinese-formal": true,
  1661. "simp-chinese-informal": true,
  1662. "syriac": true,
  1663. "tamil": true,
  1664. "trad-chinese-formal": true,
  1665. "trad-chinese-informal": true,
  1666. "upper-armenian": true,
  1667. "arabic-indic": true,
  1668. "binary": true,
  1669. "bengali": true,
  1670. "cambodian": true,
  1671. "khmer": true,
  1672. "devanagari": true,
  1673. "gujarati": true,
  1674. "gurmukhi": true,
  1675. "kannada": true,
  1676. "lower-hexadecimal": true,
  1677. "lao": true,
  1678. "malayalam": true,
  1679. "mongolian": true,
  1680. "myanmar": true,
  1681. "octal": true,
  1682. "oriya": true,
  1683. "persian": true,
  1684. "urdu": true,
  1685. "telugu": true,
  1686. "tibetan": true,
  1687. "upper-hexadecimal": true,
  1688. "afar": true,
  1689. "ethiopic-halehame-aa-et": true,
  1690. "ethiopic-halehame-am-et": true,
  1691. "amharic-abegede": true,
  1692. "ehiopic-abegede-am-et": true,
  1693. "cjk-earthly-branch": true,
  1694. "cjk-heavenly-stem": true,
  1695. "ethiopic": true,
  1696. "ethiopic-abegede": true,
  1697. "ethiopic-abegede-gez": true,
  1698. "hangul-consonant": true,
  1699. "hangul": true,
  1700. "hiragana-iroha": true,
  1701. "hiragana": true,
  1702. "katakana-iroha": true,
  1703. "katakana": true,
  1704. "lower-norwegian": true,
  1705. "oromo": true,
  1706. "ethiopic-halehame-om-et": true,
  1707. "sidama": true,
  1708. "ethiopic-halehame-sid-et": true,
  1709. "somali": true,
  1710. "ethiopic-halehame-so-et": true,
  1711. "tigre": true,
  1712. "ethiopic-halehame-tig": true,
  1713. "tigrinya-er-abegede": true,
  1714. "ethiopic-abegede-ti-er": true,
  1715. "tigrinya-et": true,
  1716. "ethiopic-halehame-ti-et": true,
  1717. "upper-greek": true,
  1718. "asterisks": true,
  1719. "footnotes": true,
  1720. "circled-decimal": true,
  1721. "circled-lower-latin": true,
  1722. "circled-upper-latin": true,
  1723. "dotted-decimal": true,
  1724. "double-circled-decimal": true,
  1725. "filled-circled-decimal": true,
  1726. "parenthesised-decimal": true,
  1727. "parenthesised-lower-latin": true
  1728. },
  1729. reportError: function(aMsg) {
  1730. this.mError = aMsg;
  1731. },
  1732. consumeError: function() {
  1733. var e = this.mError;
  1734. this.mError = null;
  1735. return e;
  1736. },
  1737. currentToken: function() {
  1738. return this.mToken;
  1739. },
  1740. getHexValue: function() {
  1741. this.mToken = this.mScanner.nextHexValue();
  1742. return this.mToken;
  1743. },
  1744. getToken: function(aSkipWS, aSkipComment) {
  1745. if (this.mLookAhead) {
  1746. this.mToken = this.mLookAhead;
  1747. this.mLookAhead = null;
  1748. return this.mToken;
  1749. }
  1750. this.mToken = this.mScanner.nextToken();
  1751. while (this.mToken &&
  1752. ((aSkipWS && this.mToken.isWhiteSpace()) ||
  1753. (aSkipComment && this.mToken.isComment())))
  1754. this.mToken = this.mScanner.nextToken();
  1755. return this.mToken;
  1756. },
  1757. lookAhead: function(aSkipWS, aSkipComment) {
  1758. var preservedToken = this.mToken;
  1759. this.mScanner.preserveState();
  1760. var token = this.getToken(aSkipWS, aSkipComment);
  1761. this.mScanner.restoreState();
  1762. this.mToken = preservedToken;
  1763. return token;
  1764. },
  1765. ungetToken: function() {
  1766. this.mLookAhead = this.mToken;
  1767. },
  1768. addUnknownAtRule: function(aSheet, aString) {
  1769. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  1770. var blocks = [];
  1771. var token = this.getToken(false, false);
  1772. while (token.isNotNull()) {
  1773. aString += token.value;
  1774. if (token.isSymbol(";") && !blocks.length)
  1775. break;
  1776. else if (token.isSymbol("{")
  1777. || token.isSymbol("(")
  1778. || token.isSymbol("[")
  1779. || token.type == "function") {
  1780. blocks.push(token.isFunction() ? "(" : token.value);
  1781. } else if (token.isSymbol("}")
  1782. || token.isSymbol(")")
  1783. || token.isSymbol("]")) {
  1784. if (blocks.length) {
  1785. var ontop = blocks[blocks.length - 1];
  1786. if ((token.isSymbol("}") && ontop == "{")
  1787. || (token.isSymbol(")") && ontop == "(")
  1788. || (token.isSymbol("]") && ontop == "[")) {
  1789. blocks.pop();
  1790. if (!blocks.length && token.isSymbol("}"))
  1791. break;
  1792. }
  1793. }
  1794. }
  1795. token = this.getToken(false, false);
  1796. }
  1797. this.addUnknownRule(aSheet, aString, currentLine);
  1798. },
  1799. addUnknownRule: function(aSheet, aString, aCurrentLine) {
  1800. var errorMsg = this.consumeError();
  1801. var rule = new jscsspErrorRule(errorMsg);
  1802. rule.currentLine = aCurrentLine;
  1803. rule.parsedCssText = aString;
  1804. rule.parentStyleSheet = aSheet;
  1805. aSheet.cssRules.push(rule);
  1806. },
  1807. addWhitespace: function(aSheet, aString) {
  1808. var rule = new jscsspWhitespace();
  1809. rule.parsedCssText = aString;
  1810. rule.parentStyleSheet = aSheet;
  1811. aSheet.cssRules.push(rule);
  1812. },
  1813. addComment: function(aSheet, aString) {
  1814. var rule = new jscsspComment();
  1815. rule.parsedCssText = aString;
  1816. rule.parentStyleSheet = aSheet;
  1817. aSheet.cssRules.push(rule);
  1818. },
  1819. parseCharsetRule: function(aToken, aSheet) {
  1820. var s = aToken.value;
  1821. var token = this.getToken(false, false);
  1822. s += token.value;
  1823. if (token.isWhiteSpace(" ")) {
  1824. token = this.getToken(false, false);
  1825. s += token.value;
  1826. if (token.isString()) {
  1827. var encoding = token.value;
  1828. token = this.getToken(false, false);
  1829. s += token.value;
  1830. if (token.isSymbol(";")) {
  1831. var rule = new jscsspCharsetRule();
  1832. rule.encoding = encoding;
  1833. rule.parsedCssText = s;
  1834. rule.parentStyleSheet = aSheet;
  1835. aSheet.cssRules.push(rule);
  1836. return true;
  1837. }
  1838. else
  1839. this.reportError(kCHARSET_RULE_MISSING_SEMICOLON);
  1840. }
  1841. else
  1842. this.reportError(kCHARSET_RULE_CHARSET_IS_STRING);
  1843. }
  1844. else
  1845. this.reportError(kCHARSET_RULE_MISSING_WS);
  1846. this.addUnknownAtRule(aSheet, s);
  1847. return false;
  1848. },
  1849. parseImportRule: function(aToken, aSheet) {
  1850. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  1851. var s = aToken.value;
  1852. this.preserveState();
  1853. var token = this.getToken(true, true);
  1854. var media = [];
  1855. var href = "";
  1856. if (token.isString()) {
  1857. href = token.value;
  1858. s += " " + href;
  1859. }
  1860. else if (token.isFunction("url(")) {
  1861. token = this.getToken(true, true);
  1862. var urlContent = this.parseURL(token);
  1863. if (urlContent) {
  1864. href = "url(" + urlContent;
  1865. s += " " + href;
  1866. }
  1867. }
  1868. else
  1869. this.reportError(kIMPORT_RULE_MISSING_URL);
  1870. if (href) {
  1871. token = this.getToken(true, true);
  1872. while (token.isIdent()) {
  1873. s += " " + token.value;
  1874. media.push(token.value);
  1875. token = this.getToken(true, true);
  1876. if (!token)
  1877. break;
  1878. if (token.isSymbol(",")) {
  1879. s += ",";
  1880. } else if (token.isSymbol(";")) {
  1881. break;
  1882. } else
  1883. break;
  1884. token = this.getToken(true, true);
  1885. }
  1886. if (!media.length) {
  1887. media.push("all");
  1888. }
  1889. if (token.isSymbol(";")) {
  1890. s += ";"
  1891. this.forgetState();
  1892. var rule = new jscsspImportRule();
  1893. rule.currentLine = currentLine;
  1894. rule.parsedCssText = s;
  1895. rule.href = href;
  1896. rule.media = media;
  1897. rule.parentStyleSheet = aSheet;
  1898. aSheet.cssRules.push(rule);
  1899. return true;
  1900. }
  1901. }
  1902. this.restoreState();
  1903. this.addUnknownAtRule(aSheet, "@import");
  1904. return false;
  1905. },
  1906. parseVariablesRule: function(token, aSheet) {
  1907. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  1908. var s = token.value;
  1909. var declarations = [];
  1910. var valid = false;
  1911. this.preserveState();
  1912. token = this.getToken(true, true);
  1913. var media = [];
  1914. var foundMedia = false;
  1915. while (token.isNotNull()) {
  1916. if (token.isIdent()) {
  1917. foundMedia = true;
  1918. s += " " + token.value;
  1919. media.push(token.value);
  1920. token = this.getToken(true, true);
  1921. if (token.isSymbol(",")) {
  1922. s += ",";
  1923. } else {
  1924. if (token.isSymbol("{"))
  1925. this.ungetToken();
  1926. else {
  1927. // error...
  1928. token.type = jscsspToken.NULL_TYPE;
  1929. break;
  1930. }
  1931. }
  1932. } else if (token.isSymbol("{"))
  1933. break;
  1934. else if (foundMedia) {
  1935. token.type = jscsspToken.NULL_TYPE;
  1936. // not a media list
  1937. break;
  1938. }
  1939. token = this.getToken(true, true);
  1940. }
  1941. if (token.isSymbol("{")) {
  1942. s += " {";
  1943. token = this.getToken(true, true);
  1944. while (true) {
  1945. if (!token.isNotNull()) {
  1946. valid = true;
  1947. break;
  1948. }
  1949. if (token.isSymbol("}")) {
  1950. s += "}";
  1951. valid = true;
  1952. break;
  1953. } else {
  1954. var d = this.parseDeclaration(token, declarations, true, false, aSheet);
  1955. s += ((d && declarations.length) ? " " : "") + d;
  1956. }
  1957. token = this.getToken(true, false);
  1958. }
  1959. }
  1960. if (valid) {
  1961. this.forgetState();
  1962. var rule = new jscsspVariablesRule();
  1963. rule.currentLine = currentLine;
  1964. rule.parsedCssText = s;
  1965. rule.declarations = declarations;
  1966. rule.media = media;
  1967. rule.parentStyleSheet = aSheet;
  1968. aSheet.cssRules.push(rule)
  1969. return true;
  1970. }
  1971. this.restoreState();
  1972. return false;
  1973. },
  1974. parseNamespaceRule: function(aToken, aSheet) {
  1975. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  1976. var s = aToken.value;
  1977. var valid = false;
  1978. this.preserveState();
  1979. var token = this.getToken(true, true);
  1980. if (token.isNotNull()) {
  1981. var prefix = "";
  1982. var url = "";
  1983. if (token.isIdent()) {
  1984. prefix = token.value;
  1985. s += " " + prefix;
  1986. token = this.getToken(true, true);
  1987. }
  1988. if (token) {
  1989. var foundURL = false;
  1990. if (token.isString()) {
  1991. foundURL = true;
  1992. url = token.value;
  1993. s += " " + url;
  1994. } else if (token.isFunction("url(")) {
  1995. // get a url here...
  1996. token = this.getToken(true, true);
  1997. var urlContent = this.parseURL(token);
  1998. if (urlContent) {
  1999. url += "url(" + urlContent;
  2000. foundURL = true;
  2001. s += " " + urlContent;
  2002. }
  2003. }
  2004. }
  2005. if (foundURL) {
  2006. token = this.getToken(true, true);
  2007. if (token.isSymbol(";")) {
  2008. s += ";";
  2009. this.forgetState();
  2010. var rule = new jscsspNamespaceRule();
  2011. rule.currentLine = currentLine;
  2012. rule.parsedCssText = s;
  2013. rule.prefix = prefix;
  2014. rule.url = url;
  2015. rule.parentStyleSheet = aSheet;
  2016. aSheet.cssRules.push(rule);
  2017. return true;
  2018. }
  2019. }
  2020. }
  2021. this.restoreState();
  2022. this.addUnknownAtRule(aSheet, "@namespace");
  2023. return false;
  2024. },
  2025. parseFontFaceRule: function(aToken, aSheet) {
  2026. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  2027. var s = aToken.value;
  2028. var valid = false;
  2029. var descriptors = [];
  2030. this.preserveState();
  2031. var token = this.getToken(true, true);
  2032. if (token.isNotNull()) {
  2033. // expecting block start
  2034. if (token.isSymbol("{")) {
  2035. s += " " + token.value;
  2036. var token = this.getToken(true, false);
  2037. while (true) {
  2038. if (token.isSymbol("}")) {
  2039. s += "}";
  2040. valid = true;
  2041. break;
  2042. } else {
  2043. var d = this.parseDeclaration(token, descriptors, false, false, aSheet);
  2044. s += ((d && descriptors.length) ? " " : "") + d;
  2045. }
  2046. token = this.getToken(true, false);
  2047. }
  2048. }
  2049. }
  2050. if (valid) {
  2051. this.forgetState();
  2052. var rule = new jscsspFontFaceRule();
  2053. rule.currentLine = currentLine;
  2054. rule.parsedCssText = s;
  2055. rule.descriptors = descriptors;
  2056. rule.parentStyleSheet = aSheet;
  2057. aSheet.cssRules.push(rule)
  2058. return true;
  2059. }
  2060. this.restoreState();
  2061. return false;
  2062. },
  2063. parsePageRule: function(aToken, aSheet) {
  2064. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  2065. var s = aToken.value;
  2066. var valid = false;
  2067. var declarations = [];
  2068. this.preserveState();
  2069. var token = this.getToken(true, true);
  2070. var pageSelector = "";
  2071. if (token.isSymbol(":") || token.isIdent()) {
  2072. if (token.isSymbol(":")) {
  2073. pageSelector = ":";
  2074. token = this.getToken(false, false);
  2075. }
  2076. if (token.isIdent()) {
  2077. pageSelector += token.value;
  2078. s += " " + pageSelector;
  2079. token = this.getToken(true, true);
  2080. }
  2081. }
  2082. if (token.isNotNull()) {
  2083. // expecting block start
  2084. if (token.isSymbol("{")) {
  2085. s += " " + token.value;
  2086. var token = this.getToken(true, false);
  2087. while (true) {
  2088. if (token.isSymbol("}")) {
  2089. s += "}";
  2090. valid = true;
  2091. break;
  2092. } else {
  2093. var d = this.parseDeclaration(token, declarations, true, true, aSheet);
  2094. s += ((d && declarations.length) ? " " : "") + d;
  2095. }
  2096. token = this.getToken(true, false);
  2097. }
  2098. }
  2099. }
  2100. if (valid) {
  2101. this.forgetState();
  2102. var rule = new jscsspPageRule();
  2103. rule.currentLine = currentLine;
  2104. rule.parsedCssText = s;
  2105. rule.pageSelector = pageSelector;
  2106. rule.declarations = declarations;
  2107. rule.parentStyleSheet = aSheet;
  2108. aSheet.cssRules.push(rule)
  2109. return true;
  2110. }
  2111. this.restoreState();
  2112. return false;
  2113. },
  2114. parseDefaultPropertyValue: function(token, aDecl, aAcceptPriority, descriptor, aSheet) {
  2115. var valueText = "";
  2116. var blocks = [];
  2117. var foundPriority = false;
  2118. var values = [];
  2119. while (token.isNotNull()) {
  2120. if ((token.isSymbol(";")
  2121. || token.isSymbol("}")
  2122. || token.isSymbol("!"))
  2123. && !blocks.length) {
  2124. if (token.isSymbol("}"))
  2125. this.ungetToken();
  2126. break;
  2127. }
  2128. if (token.isIdent(this.kINHERIT)) {
  2129. if (values.length) {
  2130. return "";
  2131. }
  2132. else {
  2133. valueText = this.kINHERIT;
  2134. var value = new jscsspVariable(kJscsspINHERIT_VALUE, aSheet);
  2135. values.push(value);
  2136. token = this.getToken(true, true);
  2137. break;
  2138. }
  2139. }
  2140. else if (token.isSymbol("{")
  2141. || token.isSymbol("(")
  2142. || token.isSymbol("[")) {
  2143. blocks.push(token.value);
  2144. }
  2145. else if (token.isSymbol("}")
  2146. || token.isSymbol("]")) {
  2147. if (blocks.length) {
  2148. var ontop = blocks[blocks.length - 1];
  2149. if ((token.isSymbol("}") && ontop == "{")
  2150. || (token.isSymbol(")") && ontop == "(")
  2151. || (token.isSymbol("]") && ontop == "[")) {
  2152. blocks.pop();
  2153. }
  2154. }
  2155. }
  2156. // XXX must find a better way to store individual values
  2157. // probably a |values: []| field holding dimensions, percentages
  2158. // functions, idents, numbers and symbols, in that order.
  2159. if (token.isFunction()) {
  2160. if (token.isFunction("var(")) {
  2161. token = this.getToken(true, true);
  2162. if (token.isIdent()) {
  2163. var name = token.value;
  2164. token = this.getToken(true, true);
  2165. if (token.isSymbol(")")) {
  2166. var value = new jscsspVariable(kJscsspVARIABLE_VALUE, aSheet);
  2167. valueText += "var(" + name + ")";
  2168. value.name = name;
  2169. values.push(value);
  2170. }
  2171. else
  2172. return "";
  2173. }
  2174. else
  2175. return "";
  2176. }
  2177. else {
  2178. var fn = token.value;
  2179. token = this.getToken(false, true);
  2180. var arg = this.parseFunctionArgument(token);
  2181. if (arg) {
  2182. valueText += fn + arg;
  2183. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet);
  2184. value.value = fn + arg;
  2185. values.push(value);
  2186. }
  2187. else
  2188. return "";
  2189. }
  2190. }
  2191. else if (token.isSymbol("#")) {
  2192. var color = this.parseColor(token);
  2193. if (color) {
  2194. valueText += color;
  2195. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet);
  2196. value.value = color;
  2197. values.push(value);
  2198. }
  2199. else
  2200. return "";
  2201. }
  2202. else if (!token.isWhiteSpace() && !token.isSymbol(",")) {
  2203. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, aSheet);
  2204. value.value = token.value;
  2205. values.push(value);
  2206. valueText += token.value;
  2207. }
  2208. else
  2209. valueText += token.value;
  2210. token = this.getToken(false, true);
  2211. }
  2212. if (values.length && valueText) {
  2213. this.forgetState();
  2214. aDecl.push(this._createJscsspDeclarationFromValuesArray(descriptor, values, valueText));
  2215. return valueText;
  2216. }
  2217. return "";
  2218. },
  2219. parseMarginOrPaddingShorthand: function(token, aDecl, aAcceptPriority, aProperty)
  2220. {
  2221. var top = null;
  2222. var bottom = null;
  2223. var left = null;
  2224. var right = null;
  2225. var values = [];
  2226. while (true) {
  2227. if (!token.isNotNull())
  2228. break;
  2229. if (token.isSymbol(";")
  2230. || (aAcceptPriority && token.isSymbol("!"))
  2231. || token.isSymbol("}")) {
  2232. if (token.isSymbol("}"))
  2233. this.ungetToken();
  2234. break;
  2235. }
  2236. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2237. values.push(token.value);
  2238. token = this.getToken(true, true);
  2239. break;
  2240. }
  2241. else if (token.isDimension()
  2242. || token.isNumber("0")
  2243. || token.isPercentage()
  2244. || token.isIdent("auto")) {
  2245. values.push(token.value);
  2246. }
  2247. else
  2248. return "";
  2249. token = this.getToken(true, true);
  2250. }
  2251. var count = values.length;
  2252. switch (count) {
  2253. case 1:
  2254. top = values[0];
  2255. bottom = top;
  2256. left = top;
  2257. right = top;
  2258. break;
  2259. case 2:
  2260. top = values[0];
  2261. bottom = top;
  2262. left = values[1];
  2263. right = left;
  2264. break;
  2265. case 3:
  2266. top = values[0];
  2267. left = values[1];
  2268. right = left;
  2269. bottom = values[2];
  2270. break;
  2271. case 4:
  2272. top = values[0];
  2273. right = values[1];
  2274. bottom = values[2];
  2275. left = values[3];
  2276. break;
  2277. default:
  2278. return "";
  2279. }
  2280. this.forgetState();
  2281. aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-top", top));
  2282. aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-right", right));
  2283. aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-bottom", bottom));
  2284. aDecl.push(this._createJscsspDeclarationFromValue(aProperty + "-left", left));
  2285. return top + " " + right + " " + bottom + " " + left;
  2286. },
  2287. parseBorderColorShorthand: function(token, aDecl, aAcceptPriority)
  2288. {
  2289. var top = null;
  2290. var bottom = null;
  2291. var left = null;
  2292. var right = null;
  2293. var values = [];
  2294. while (true) {
  2295. if (!token.isNotNull())
  2296. break;
  2297. if (token.isSymbol(";")
  2298. || (aAcceptPriority && token.isSymbol("!"))
  2299. || token.isSymbol("}")) {
  2300. if (token.isSymbol("}"))
  2301. this.ungetToken();
  2302. break;
  2303. }
  2304. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2305. values.push(token.value);
  2306. token = this.getToken(true, true);
  2307. break;
  2308. }
  2309. else {
  2310. var color = this.parseColor(token);
  2311. if (color)
  2312. values.push(color);
  2313. else
  2314. return "";
  2315. }
  2316. token = this.getToken(true, true);
  2317. }
  2318. var count = values.length;
  2319. switch (count) {
  2320. case 1:
  2321. top = values[0];
  2322. bottom = top;
  2323. left = top;
  2324. right = top;
  2325. break;
  2326. case 2:
  2327. top = values[0];
  2328. bottom = top;
  2329. left = values[1];
  2330. right = left;
  2331. break;
  2332. case 3:
  2333. top = values[0];
  2334. left = values[1];
  2335. right = left;
  2336. bottom = values[2];
  2337. break;
  2338. case 4:
  2339. top = values[0];
  2340. right = values[1];
  2341. bottom = values[2];
  2342. left = values[3];
  2343. break;
  2344. default:
  2345. return "";
  2346. }
  2347. this.forgetState();
  2348. aDecl.push(this._createJscsspDeclarationFromValue("border-top-color", top));
  2349. aDecl.push(this._createJscsspDeclarationFromValue("border-right-color", right));
  2350. aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-color", bottom));
  2351. aDecl.push(this._createJscsspDeclarationFromValue("border-left-color", left));
  2352. return top + " " + right + " " + bottom + " " + left;
  2353. },
  2354. parseCueShorthand: function(token, declarations, aAcceptPriority)
  2355. {
  2356. var before = "";
  2357. var after = "";
  2358. var values = [];
  2359. var values = [];
  2360. while (true) {
  2361. if (!token.isNotNull())
  2362. break;
  2363. if (token.isSymbol(";")
  2364. || (aAcceptPriority && token.isSymbol("!"))
  2365. || token.isSymbol("}")) {
  2366. if (token.isSymbol("}"))
  2367. this.ungetToken();
  2368. break;
  2369. }
  2370. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2371. values.push(token.value);
  2372. }
  2373. else if (token.isIdent("none"))
  2374. values.push(token.value);
  2375. else if (token.isFunction("url(")) {
  2376. var token = this.getToken(true, true);
  2377. var urlContent = this.parseURL(token);
  2378. if (urlContent)
  2379. values.push("url(" + urlContent);
  2380. else
  2381. return "";
  2382. }
  2383. else
  2384. return "";
  2385. token = this.getToken(true, true);
  2386. }
  2387. var count = values.length;
  2388. switch (count) {
  2389. case 1:
  2390. before = values[0];
  2391. after = before;
  2392. break;
  2393. case 2:
  2394. before = values[0];
  2395. after = values[1];
  2396. break;
  2397. default:
  2398. return "";
  2399. }
  2400. this.forgetState();
  2401. aDecl.push(this._createJscsspDeclarationFromValue("cue-before", before));
  2402. aDecl.push(this._createJscsspDeclarationFromValue("cue-after", after));
  2403. return before + " " + after;
  2404. },
  2405. parsePauseShorthand: function(token, declarations, aAcceptPriority)
  2406. {
  2407. var before = "";
  2408. var after = "";
  2409. var values = [];
  2410. var values = [];
  2411. while (true) {
  2412. if (!token.isNotNull())
  2413. break;
  2414. if (token.isSymbol(";")
  2415. || (aAcceptPriority && token.isSymbol("!"))
  2416. || token.isSymbol("}")) {
  2417. if (token.isSymbol("}"))
  2418. this.ungetToken();
  2419. break;
  2420. }
  2421. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2422. values.push(token.value);
  2423. }
  2424. else if (token.isDimensionOfUnit("ms")
  2425. || token.isDimensionOfUnit("s")
  2426. || token.isPercentage()
  2427. || token.isNumber("0"))
  2428. values.push(token.value);
  2429. else
  2430. return "";
  2431. token = this.getToken(true, true);
  2432. }
  2433. var count = values.length;
  2434. switch (count) {
  2435. case 1:
  2436. before = values[0];
  2437. after = before;
  2438. break;
  2439. case 2:
  2440. before = values[0];
  2441. after = values[1];
  2442. break;
  2443. default:
  2444. return "";
  2445. }
  2446. this.forgetState();
  2447. aDecl.push(this._createJscsspDeclarationFromValue("pause-before", before));
  2448. aDecl.push(this._createJscsspDeclarationFromValue("pause-after", after));
  2449. return before + " " + after;
  2450. },
  2451. parseBorderWidthShorthand: function(token, aDecl, aAcceptPriority)
  2452. {
  2453. var top = null;
  2454. var bottom = null;
  2455. var left = null;
  2456. var right = null;
  2457. var values = [];
  2458. while (true) {
  2459. if (!token.isNotNull())
  2460. break;
  2461. if (token.isSymbol(";")
  2462. || (aAcceptPriority && token.isSymbol("!"))
  2463. || token.isSymbol("}")) {
  2464. if (token.isSymbol("}"))
  2465. this.ungetToken();
  2466. break;
  2467. }
  2468. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2469. values.push(token.value);
  2470. }
  2471. else if (token.isDimension()
  2472. || token.isNumber("0")
  2473. || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)) {
  2474. values.push(token.value);
  2475. }
  2476. else
  2477. return "";
  2478. token = this.getToken(true, true);
  2479. }
  2480. var count = values.length;
  2481. switch (count) {
  2482. case 1:
  2483. top = values[0];
  2484. bottom = top;
  2485. left = top;
  2486. right = top;
  2487. break;
  2488. case 2:
  2489. top = values[0];
  2490. bottom = top;
  2491. left = values[1];
  2492. right = left;
  2493. break;
  2494. case 3:
  2495. top = values[0];
  2496. left = values[1];
  2497. right = left;
  2498. bottom = values[2];
  2499. break;
  2500. case 4:
  2501. top = values[0];
  2502. right = values[1];
  2503. bottom = values[2];
  2504. left = values[3];
  2505. break;
  2506. default:
  2507. return "";
  2508. }
  2509. this.forgetState();
  2510. aDecl.push(this._createJscsspDeclarationFromValue("border-top-width", top));
  2511. aDecl.push(this._createJscsspDeclarationFromValue("border-right-width", right));
  2512. aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-width", bottom));
  2513. aDecl.push(this._createJscsspDeclarationFromValue("border-left-width", left));
  2514. return top + " " + right + " " + bottom + " " + left;
  2515. },
  2516. parseBorderStyleShorthand: function(token, aDecl, aAcceptPriority)
  2517. {
  2518. var top = null;
  2519. var bottom = null;
  2520. var left = null;
  2521. var right = null;
  2522. var values = [];
  2523. while (true) {
  2524. if (!token.isNotNull())
  2525. break;
  2526. if (token.isSymbol(";")
  2527. || (aAcceptPriority && token.isSymbol("!"))
  2528. || token.isSymbol("}")) {
  2529. if (token.isSymbol("}"))
  2530. this.ungetToken();
  2531. break;
  2532. }
  2533. else if (!values.length && token.isIdent(this.kINHERIT)) {
  2534. values.push(token.value);
  2535. }
  2536. else if (token.isIdent() && token.value in this.kBORDER_STYLE_NAMES) {
  2537. values.push(token.value);
  2538. }
  2539. else
  2540. return "";
  2541. token = this.getToken(true, true);
  2542. }
  2543. var count = values.length;
  2544. switch (count) {
  2545. case 1:
  2546. top = values[0];
  2547. bottom = top;
  2548. left = top;
  2549. right = top;
  2550. break;
  2551. case 2:
  2552. top = values[0];
  2553. bottom = top;
  2554. left = values[1];
  2555. right = left;
  2556. break;
  2557. case 3:
  2558. top = values[0];
  2559. left = values[1];
  2560. right = left;
  2561. bottom = values[2];
  2562. break;
  2563. case 4:
  2564. top = values[0];
  2565. right = values[1];
  2566. bottom = values[2];
  2567. left = values[3];
  2568. break;
  2569. default:
  2570. return "";
  2571. }
  2572. this.forgetState();
  2573. aDecl.push(this._createJscsspDeclarationFromValue("border-top-style", top));
  2574. aDecl.push(this._createJscsspDeclarationFromValue("border-right-style", right));
  2575. aDecl.push(this._createJscsspDeclarationFromValue("border-bottom-style", bottom));
  2576. aDecl.push(this._createJscsspDeclarationFromValue("border-left-style", left));
  2577. return top + " " + right + " " + bottom + " " + left;
  2578. },
  2579. parseBorderEdgeOrOutlineShorthand: function(token, aDecl, aAcceptPriority, aProperty)
  2580. {
  2581. var bWidth = null;
  2582. var bStyle = null;
  2583. var bColor = null;
  2584. while (true) {
  2585. if (!token.isNotNull())
  2586. break;
  2587. if (token.isSymbol(";")
  2588. || (aAcceptPriority && token.isSymbol("!"))
  2589. || token.isSymbol("}")) {
  2590. if (token.isSymbol("}"))
  2591. this.ungetToken();
  2592. break;
  2593. }
  2594. else if (!bWidth && !bStyle && !bColor
  2595. && token.isIdent(this.kINHERIT)) {
  2596. bWidth = this.kINHERIT;
  2597. bStyle = this.kINHERIT;
  2598. bColor = this.kINHERIT;
  2599. }
  2600. else if (!bWidth &&
  2601. (token.isDimension()
  2602. || (token.isIdent() && token.value in this.kBORDER_WIDTH_NAMES)
  2603. || token.isNumber("0"))) {
  2604. bWidth = token.value;
  2605. }
  2606. else if (!bStyle &&
  2607. (token.isIdent() && token.value in this.kBORDER_STYLE_NAMES)) {
  2608. bStyle = token.value;
  2609. }
  2610. else {
  2611. var color = (aProperty == "outline" && token.isIdent("invert"))
  2612. ? "invert" : this.parseColor(token);
  2613. if (!bColor && color)
  2614. bColor = color;
  2615. else
  2616. return "";
  2617. }
  2618. token = this.getToken(true, true);
  2619. }
  2620. // create the declarations
  2621. this.forgetState();
  2622. bWidth = bWidth ? bWidth : "medium";
  2623. bStyle = bStyle ? bStyle : "none";
  2624. bColor = bColor ? bColor : "-moz-initial";
  2625. function addPropertyToDecl(aSelf, aDecl, property, w, s, c) {
  2626. aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-width", w));
  2627. aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-style", s));
  2628. aDecl.push(aSelf._createJscsspDeclarationFromValue(property + "-color", c));
  2629. }
  2630. if (aProperty == "border") {
  2631. addPropertyToDecl(this, aDecl, "border-top", bWidth, bStyle, bColor);
  2632. addPropertyToDecl(this, aDecl, "border-right", bWidth, bStyle, bColor);
  2633. addPropertyToDecl(this, aDecl, "border-bottom", bWidth, bStyle, bColor);
  2634. addPropertyToDecl(this, aDecl, "border-left", bWidth, bStyle, bColor);
  2635. }
  2636. else
  2637. addPropertyToDecl(this, aDecl, aProperty, bWidth, bStyle, bColor);
  2638. return bWidth + " " + bStyle + " " + bColor;
  2639. },
  2640. parseBackgroundShorthand: function(token, aDecl, aAcceptPriority)
  2641. {
  2642. var kHPos = {"left": true, "right": true };
  2643. var kVPos = {"top": true, "bottom": true };
  2644. var kPos = {"left": true, "right": true, "top": true, "bottom": true, "center": true};
  2645. var bgColor = null;
  2646. var bgRepeat = null;
  2647. var bgAttachment = null;
  2648. var bgImage = null;
  2649. var bgPosition = null;
  2650. while (true) {
  2651. if (!token.isNotNull())
  2652. break;
  2653. if (token.isSymbol(";")
  2654. || (aAcceptPriority && token.isSymbol("!"))
  2655. || token.isSymbol("}")) {
  2656. if (token.isSymbol("}"))
  2657. this.ungetToken();
  2658. break;
  2659. }
  2660. else if (!bgColor && !bgRepeat && !bgAttachment && !bgImage && !bgPosition
  2661. && token.isIdent(this.kINHERIT)) {
  2662. bgColor = this.kINHERIT;
  2663. bgRepeat = this.kINHERIT;
  2664. bgAttachment = this.kINHERIT;
  2665. bgImage = this.kINHERIT;
  2666. bgPosition = this.kINHERIT;
  2667. }
  2668. else {
  2669. if (!bgAttachment &&
  2670. (token.isIdent("scroll")
  2671. || token.isIdent("fixed"))) {
  2672. bgAttachment = token.value;
  2673. }
  2674. else if (!bgPosition &&
  2675. ((token.isIdent() && token.value in kPos)
  2676. || token.isDimension()
  2677. || token.isNumber("0")
  2678. || token.isPercentage())) {
  2679. bgPosition = token.value;
  2680. token = this.getToken(true, true);
  2681. if (token.isDimension() || token.isNumber("0") || token.isPercentage()) {
  2682. bgPosition += " " + token.value;
  2683. }
  2684. else if (token.isIdent() && token.value in kPos) {
  2685. if ((bgPosition in kHPos && token.value in kHPos) ||
  2686. (bgPosition in kVPos && token.value in kVPos))
  2687. return "";
  2688. bgPosition += " " + token.value;
  2689. }
  2690. else {
  2691. this.ungetToken();
  2692. bgPosition += " center";
  2693. }
  2694. }
  2695. else if (!bgRepeat &&
  2696. (token.isIdent("repeat")
  2697. || token.isIdent("repeat-x")
  2698. || token.isIdent("repeat-y")
  2699. || token.isIdent("no-repeat"))) {
  2700. bgRepeat = token.value;
  2701. }
  2702. else if (!bgImage &&
  2703. (token.isFunction("url(")
  2704. || token.isIdent("none"))) {
  2705. bgImage = token.value;
  2706. if (token.isFunction("url(")) {
  2707. token = this.getToken(true, true);
  2708. var url = this.parseURL(token); // TODO
  2709. if (url)
  2710. bgImage += url;
  2711. else
  2712. return "";
  2713. }
  2714. }
  2715. else if (!bgImage &&
  2716. (token.isFunction("-moz-linear-gradient(")
  2717. || token.isFunction("-moz-radial-gradient(")
  2718. || token.isFunction("-moz-repeating-linear-gradient(")
  2719. || token.isFunction("-moz-repeating-radial-gradient("))) {
  2720. var gradient = CssInspector.parseGradient(this, token);
  2721. if (gradient)
  2722. bgImage = CssInspector.serializeGradient(gradient);
  2723. else
  2724. return "";
  2725. }
  2726. else {
  2727. var color = this.parseColor(token);
  2728. if (!bgColor && color)
  2729. bgColor = color;
  2730. else
  2731. return "";
  2732. }
  2733. }
  2734. token = this.getToken(true, true);
  2735. }
  2736. // create the declarations
  2737. this.forgetState();
  2738. bgColor = bgColor ? bgColor : "transparent";
  2739. bgImage = bgImage ? bgImage : "none";
  2740. bgRepeat = bgRepeat ? bgRepeat : "repeat";
  2741. bgAttachment = bgAttachment ? bgAttachment : "scroll";
  2742. bgPosition = bgPosition ? bgPosition : "top left";
  2743. aDecl.push(this._createJscsspDeclarationFromValue("background-color", bgColor));
  2744. aDecl.push(this._createJscsspDeclarationFromValue("background-image", bgImage));
  2745. aDecl.push(this._createJscsspDeclarationFromValue("background-repeat", bgRepeat));
  2746. aDecl.push(this._createJscsspDeclarationFromValue("background-attachment", bgAttachment));
  2747. aDecl.push(this._createJscsspDeclarationFromValue("background-position", bgPosition));
  2748. return bgColor + " " + bgImage + " " + bgRepeat + " " + bgAttachment + " " + bgPosition;
  2749. },
  2750. parseListStyleShorthand: function(token, aDecl, aAcceptPriority)
  2751. {
  2752. var kPosition = { "inside": true, "outside": true };
  2753. var lType = null;
  2754. var lPosition = null;
  2755. var lImage = null;
  2756. while (true) {
  2757. if (!token.isNotNull())
  2758. break;
  2759. if (token.isSymbol(";")
  2760. || (aAcceptPriority && token.isSymbol("!"))
  2761. || token.isSymbol("}")) {
  2762. if (token.isSymbol("}"))
  2763. this.ungetToken();
  2764. break;
  2765. }
  2766. else if (!lType && !lPosition && ! lImage
  2767. && token.isIdent(this.kINHERIT)) {
  2768. lType = this.kINHERIT;
  2769. lPosition = this.kINHERIT;
  2770. lImage = this.kINHERIT;
  2771. }
  2772. else if (!lType &&
  2773. (token.isIdent() && token.value in this.kLIST_STYLE_TYPE_NAMES)) {
  2774. lType = token.value;
  2775. }
  2776. else if (!lPosition &&
  2777. (token.isIdent() && token.value in kPosition)) {
  2778. lPosition = token.value;
  2779. }
  2780. else if (!lImage && token.isFunction("url")) {
  2781. token = this.getToken(true, true);
  2782. var urlContent = this.parseURL(token);
  2783. if (urlContent) {
  2784. lImage = "url(" + urlContent;
  2785. }
  2786. else
  2787. return "";
  2788. }
  2789. else if (!token.isIdent("none"))
  2790. return "";
  2791. token = this.getToken(true, true);
  2792. }
  2793. // create the declarations
  2794. this.forgetState();
  2795. lType = lType ? lType : "none";
  2796. lImage = lImage ? lImage : "none";
  2797. lPosition = lPosition ? lPosition : "outside";
  2798. aDecl.push(this._createJscsspDeclarationFromValue("list-style-type", lType));
  2799. aDecl.push(this._createJscsspDeclarationFromValue("list-style-position", lPosition));
  2800. aDecl.push(this._createJscsspDeclarationFromValue("list-style-image", lImage));
  2801. return lType + " " + lPosition + " " + lImage;
  2802. },
  2803. parseFontShorthand: function(token, aDecl, aAcceptPriority)
  2804. {
  2805. var kStyle = {"italic": true, "oblique": true };
  2806. var kVariant = {"small-caps": true };
  2807. var kWeight = { "bold": true, "bolder": true, "lighter": true,
  2808. "100": true, "200": true, "300": true, "400": true,
  2809. "500": true, "600": true, "700": true, "800": true,
  2810. "900": true };
  2811. var kSize = { "xx-small": true, "x-small": true, "small": true, "medium": true,
  2812. "large": true, "x-large": true, "xx-large": true,
  2813. "larger": true, "smaller": true };
  2814. var kValues = { "caption": true, "icon": true, "menu": true, "message-box": true, "small-caption": true, "status-bar": true };
  2815. var kFamily = { "serif": true, "sans-serif": true, "cursive": true, "fantasy": true, "monospace": true };
  2816. var fStyle = null;
  2817. var fVariant = null;
  2818. var fWeight = null;
  2819. var fSize = null;
  2820. var fLineHeight = null;
  2821. var fFamily = "";
  2822. var fSystem = null;
  2823. var fFamilyValues = [];
  2824. var normalCount = 0;
  2825. while (true) {
  2826. if (!token.isNotNull())
  2827. break;
  2828. if (token.isSymbol(";")
  2829. || (aAcceptPriority && token.isSymbol("!"))
  2830. || token.isSymbol("}")) {
  2831. if (token.isSymbol("}"))
  2832. this.ungetToken();
  2833. break;
  2834. }
  2835. else if (!fStyle && !fVariant && !fWeight
  2836. && !fSize && !fLineHeight && !fFamily
  2837. && !fSystem
  2838. && token.isIdent(this.kINHERIT)) {
  2839. fStyle = this.kINHERIT;
  2840. fVariant = this.kINHERIT;
  2841. fWeight = this.kINHERIT;
  2842. fSize = this.kINHERIT;
  2843. fLineHeight = this.kINHERIT;
  2844. fFamily = this.kINHERIT;
  2845. fSystem = this.kINHERIT;
  2846. }
  2847. else {
  2848. if (!fSystem && (token.isIdent() && token.value in kValues)) {
  2849. fSystem = token.value;
  2850. break;
  2851. }
  2852. else {
  2853. if (!fStyle
  2854. && token.isIdent()
  2855. && (token.value in kStyle)) {
  2856. fStyle = token.value;
  2857. }
  2858. else if (!fVariant
  2859. && token.isIdent()
  2860. && (token.value in kVariant)) {
  2861. fVariant = token.value;
  2862. }
  2863. else if (!fWeight
  2864. && (token.isIdent() || token.isNumber())
  2865. && (token.value in kWeight)) {
  2866. fWeight = token.value;
  2867. }
  2868. else if (!fSize
  2869. && ((token.isIdent() && (token.value in kSize))
  2870. || token.isDimension()
  2871. || token.isPercentage())) {
  2872. fSize = token.value;
  2873. var token = this.getToken(false, false);
  2874. if (token.isSymbol("/")) {
  2875. token = this.getToken(false, false);
  2876. if (!fLineHeight &&
  2877. (token.isDimension() || token.isNumber() || token.isPercentage())) {
  2878. fLineHeight = token.value;
  2879. }
  2880. else
  2881. return "";
  2882. }
  2883. else
  2884. this.ungetToken();
  2885. }
  2886. else if (token.isIdent("normal")) {
  2887. normalCount++;
  2888. if (normalCount > 3)
  2889. return "";
  2890. }
  2891. else if (!fFamily && // *MUST* be last to be tested here
  2892. (token.isString()
  2893. || token.isIdent())) {
  2894. var lastWasComma = false;
  2895. while (true) {
  2896. if (!token.isNotNull())
  2897. break;
  2898. else if (token.isSymbol(";")
  2899. || (aAcceptPriority && token.isSymbol("!"))
  2900. || token.isSymbol("}")) {
  2901. this.ungetToken();
  2902. break;
  2903. }
  2904. else if (token.isIdent() && token.value in kFamily) {
  2905. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null);
  2906. value.value = token.value;
  2907. fFamilyValues.push(value);
  2908. fFamily += token.value;
  2909. break;
  2910. }
  2911. else if (token.isString() || token.isIdent()) {
  2912. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null);
  2913. value.value = token.value;
  2914. fFamilyValues.push(value);
  2915. fFamily += token.value;
  2916. lastWasComma = false;
  2917. }
  2918. else if (!lastWasComma && token.isSymbol(",")) {
  2919. fFamily += ", ";
  2920. lastWasComma = true;
  2921. }
  2922. else
  2923. return "";
  2924. token = this.getToken(true, true);
  2925. }
  2926. }
  2927. else {
  2928. return "";
  2929. }
  2930. }
  2931. }
  2932. token = this.getToken(true, true);
  2933. }
  2934. // create the declarations
  2935. this.forgetState();
  2936. if (fSystem) {
  2937. aDecl.push(this._createJscsspDeclarationFromValue("font", fSystem));
  2938. return fSystem;
  2939. }
  2940. fStyle = fStyle ? fStyle : "normal";
  2941. fVariant = fVariant ? fVariant : "normal";
  2942. fWeight = fWeight ? fWeight : "normal";
  2943. fSize = fSize ? fSize : "medium";
  2944. fLineHeight = fLineHeight ? fLineHeight : "normal";
  2945. fFamily = fFamily ? fFamily : "-moz-initial";
  2946. aDecl.push(this._createJscsspDeclarationFromValue("font-style", fStyle));
  2947. aDecl.push(this._createJscsspDeclarationFromValue("font-variant", fVariant));
  2948. aDecl.push(this._createJscsspDeclarationFromValue("font-weight", fWeight));
  2949. aDecl.push(this._createJscsspDeclarationFromValue("font-size", fSize));
  2950. aDecl.push(this._createJscsspDeclarationFromValue("line-height", fLineHeight));
  2951. aDecl.push(this._createJscsspDeclarationFromValuesArray("font-family", fFamilyValues, fFamily));
  2952. return fStyle + " " + fVariant + " " + fWeight + " " + fSize + "/" + fLineHeight + " " + fFamily;
  2953. },
  2954. _createJscsspDeclaration: function(property, value)
  2955. {
  2956. var decl = new jscsspDeclaration();
  2957. decl.property = property;
  2958. decl.value = this.trim11(value);
  2959. decl.parsedCssText = property + ": " + value + ";";
  2960. return decl;
  2961. },
  2962. _createJscsspDeclarationFromValue: function(property, valueText)
  2963. {
  2964. var decl = new jscsspDeclaration();
  2965. decl.property = property;
  2966. var value = new jscsspVariable(kJscsspPRIMITIVE_VALUE, null);
  2967. value.value = valueText;
  2968. decl.values = [value];
  2969. decl.valueText = valueText;
  2970. decl.parsedCssText = property + ": " + valueText + ";";
  2971. return decl;
  2972. },
  2973. _createJscsspDeclarationFromValuesArray: function(property, values, valueText)
  2974. {
  2975. var decl = new jscsspDeclaration();
  2976. decl.property = property;
  2977. decl.values = values;
  2978. decl.valueText = valueText;
  2979. decl.parsedCssText = property + ": " + valueText + ";";
  2980. return decl;
  2981. },
  2982. parseURL: function(token)
  2983. {
  2984. var value = "";
  2985. if (token.isString())
  2986. {
  2987. value += token.value;
  2988. token = this.getToken(true, true);
  2989. }
  2990. else
  2991. while (true)
  2992. {
  2993. if (!token.isNotNull()) {
  2994. this.reportError(kURL_EOF);
  2995. return "";
  2996. }
  2997. if (token.isWhiteSpace()) {
  2998. nextToken = this.lookAhead(true, true);
  2999. // if next token is not a closing parenthesis, that's an error
  3000. if (!nextToken.isSymbol(")")) {
  3001. this.reportError(kURL_WS_INSIDE);
  3002. token = this.currentToken();
  3003. break;
  3004. }
  3005. }
  3006. if (token.isSymbol(")")) {
  3007. break;
  3008. }
  3009. value += token.value;
  3010. token = this.getToken(false, false);
  3011. }
  3012. if (token.isSymbol(")")) {
  3013. return value + ")";
  3014. }
  3015. return "";
  3016. },
  3017. parseFunctionArgument: function(token)
  3018. {
  3019. var value = "";
  3020. if (token.isString())
  3021. {
  3022. value += token.value;
  3023. token = this.getToken(true, true);
  3024. }
  3025. else {
  3026. var parenthesis = 1;
  3027. while (true)
  3028. {
  3029. if (!token.isNotNull())
  3030. return "";
  3031. if (token.isFunction() || token.isSymbol("("))
  3032. parenthesis++;
  3033. if (token.isSymbol(")")) {
  3034. parenthesis--;
  3035. if (!parenthesis)
  3036. break;
  3037. }
  3038. value += token.value;
  3039. token = this.getToken(false, false);
  3040. }
  3041. }
  3042. if (token.isSymbol(")"))
  3043. return value + ")";
  3044. return "";
  3045. },
  3046. parseColor: function(token)
  3047. {
  3048. var color = "";
  3049. if (token.isFunction("rgb(")
  3050. || token.isFunction("rgba(")) {
  3051. color = token.value;
  3052. var isRgba = token.isFunction("rgba(")
  3053. token = this.getToken(true, true);
  3054. if (!token.isNumber() && !token.isPercentage())
  3055. return "";
  3056. color += token.value;
  3057. token = this.getToken(true, true);
  3058. if (!token.isSymbol(","))
  3059. return "";
  3060. color += ", ";
  3061. token = this.getToken(true, true);
  3062. if (!token.isNumber() && !token.isPercentage())
  3063. return "";
  3064. color += token.value;
  3065. token = this.getToken(true, true);
  3066. if (!token.isSymbol(","))
  3067. return "";
  3068. color += ", ";
  3069. token = this.getToken(true, true);
  3070. if (!token.isNumber() && !token.isPercentage())
  3071. return "";
  3072. color += token.value;
  3073. if (isRgba) {
  3074. token = this.getToken(true, true);
  3075. if (!token.isSymbol(","))
  3076. return "";
  3077. color += ", ";
  3078. token = this.getToken(true, true);
  3079. if (!token.isNumber())
  3080. return "";
  3081. color += token.value;
  3082. }
  3083. token = this.getToken(true, true);
  3084. if (!token.isSymbol(")"))
  3085. return "";
  3086. color += token.value;
  3087. }
  3088. else if (token.isFunction("hsl(")
  3089. || token.isFunction("hsla(")) {
  3090. color = token.value;
  3091. var isHsla = token.isFunction("hsla(")
  3092. token = this.getToken(true, true);
  3093. if (!token.isNumber())
  3094. return "";
  3095. color += token.value;
  3096. token = this.getToken(true, true);
  3097. if (!token.isSymbol(","))
  3098. return "";
  3099. color += ", ";
  3100. token = this.getToken(true, true);
  3101. if (!token.isPercentage())
  3102. return "";
  3103. color += token.value;
  3104. token = this.getToken(true, true);
  3105. if (!token.isSymbol(","))
  3106. return "";
  3107. color += ", ";
  3108. token = this.getToken(true, true);
  3109. if (!token.isPercentage())
  3110. return "";
  3111. color += token.value;
  3112. if (isHsla) {
  3113. token = this.getToken(true, true);
  3114. if (!token.isSymbol(","))
  3115. return "";
  3116. color += ", ";
  3117. token = this.getToken(true, true);
  3118. if (!token.isNumber())
  3119. return "";
  3120. color += token.value;
  3121. }
  3122. token = this.getToken(true, true);
  3123. if (!token.isSymbol(")"))
  3124. return "";
  3125. color += token.value;
  3126. }
  3127. else if (token.isIdent()
  3128. && (token.value in this.kCOLOR_NAMES))
  3129. color = token.value;
  3130. else if (token.isSymbol("#")) {
  3131. token = this.getHexValue();
  3132. if (!token.isHex())
  3133. return "";
  3134. var length = token.value.length;
  3135. if (length != 3 && length != 6)
  3136. return "";
  3137. if (token.value.match( /[a-fA-F0-9]/g ).length != length)
  3138. return "";
  3139. color = "#" + token.value;
  3140. }
  3141. return color;
  3142. },
  3143. parseDeclaration: function(aToken, aDecl, aAcceptPriority, aExpandShorthands, aSheet) {
  3144. this.preserveState();
  3145. var blocks = [];
  3146. if (aToken.isIdent()) {
  3147. var descriptor = aToken.value.toLowerCase();
  3148. var token = this.getToken(true, true);
  3149. if (token.isSymbol(":")) {
  3150. var token = this.getToken(true, true);
  3151. var value = "";
  3152. var declarations = [];
  3153. if (aExpandShorthands)
  3154. switch (descriptor) {
  3155. case "background":
  3156. value = this.parseBackgroundShorthand(token, declarations, aAcceptPriority);
  3157. break;
  3158. case "margin":
  3159. case "padding":
  3160. value = this.parseMarginOrPaddingShorthand(token, declarations, aAcceptPriority, descriptor);
  3161. break;
  3162. case "border-color":
  3163. value = this.parseBorderColorShorthand(token, declarations, aAcceptPriority);
  3164. break;
  3165. case "border-style":
  3166. value = this.parseBorderStyleShorthand(token, declarations, aAcceptPriority);
  3167. break;
  3168. case "border-width":
  3169. value = this.parseBorderWidthShorthand(token, declarations, aAcceptPriority);
  3170. break;
  3171. case "border-top":
  3172. case "border-right":
  3173. case "border-bottom":
  3174. case "border-left":
  3175. case "border":
  3176. case "outline":
  3177. value = this.parseBorderEdgeOrOutlineShorthand(token, declarations, aAcceptPriority, descriptor);
  3178. break;
  3179. case "cue":
  3180. value = this.parseCueShorthand(token, declarations, aAcceptPriority);
  3181. break;
  3182. case "pause":
  3183. value = this.parsePauseShorthand(token, declarations, aAcceptPriority);
  3184. break;
  3185. case "font":
  3186. value = this.parseFontShorthand(token, declarations, aAcceptPriority);
  3187. break;
  3188. case "list-style":
  3189. value = this.parseListStyleShorthand(token, declarations, aAcceptPriority);
  3190. break;
  3191. default:
  3192. value = this.parseDefaultPropertyValue(token, declarations, aAcceptPriority, descriptor, aSheet);
  3193. break;
  3194. }
  3195. else
  3196. value = this.parseDefaultPropertyValue(token, declarations, aAcceptPriority, descriptor, aSheet);
  3197. token = this.currentToken();
  3198. if (value) // no error above
  3199. {
  3200. var priority = false;
  3201. if (token.isSymbol("!")) {
  3202. token = this.getToken(true, true);
  3203. if (token.isIdent("important")) {
  3204. priority = true;
  3205. token = this.getToken(true, true);
  3206. if (token.isSymbol(";") || token.isSymbol("}")) {
  3207. if (token.isSymbol("}"))
  3208. this.ungetToken();
  3209. }
  3210. else return "";
  3211. }
  3212. else return "";
  3213. }
  3214. else if (token.isNotNull() && !token.isSymbol(";") && !token.isSymbol("}"))
  3215. return "";
  3216. for (var i = 0; i < declarations.length; i++) {
  3217. declarations[i].priority = priority;
  3218. aDecl.push(declarations[i]);
  3219. }
  3220. return descriptor + ": " + value + ";";
  3221. }
  3222. }
  3223. }
  3224. else if (aToken.isComment()) {
  3225. if (this.mPreserveComments) {
  3226. this.forgetState();
  3227. var comment = new jscsspComment();
  3228. comment.parsedCssText = aToken.value;
  3229. aDecl.push(comment);
  3230. }
  3231. return aToken.value;
  3232. }
  3233. // we have an error here, let's skip it
  3234. this.restoreState();
  3235. var s = aToken.value;
  3236. blocks = [];
  3237. var token = this.getToken(false, false);
  3238. while (token.isNotNull()) {
  3239. s += token.value;
  3240. if ((token.isSymbol(";") || token.isSymbol("}")) && !blocks.length) {
  3241. if (token.isSymbol("}"))
  3242. this.ungetToken();
  3243. break;
  3244. } else if (token.isSymbol("{")
  3245. || token.isSymbol("(")
  3246. || token.isSymbol("[")
  3247. || token.isFunction()) {
  3248. blocks.push(token.isFunction() ? "(" : token.value);
  3249. } else if (token.isSymbol("}")
  3250. || token.isSymbol(")")
  3251. || token.isSymbol("]")) {
  3252. if (blocks.length) {
  3253. var ontop = blocks[blocks.length - 1];
  3254. if ((token.isSymbol("}") && ontop == "{")
  3255. || (token.isSymbol(")") && ontop == "(")
  3256. || (token.isSymbol("]") && ontop == "[")) {
  3257. blocks.pop();
  3258. }
  3259. }
  3260. }
  3261. token = this.getToken(false, false);
  3262. }
  3263. return "";
  3264. },
  3265. parseKeyframesRule: function(aToken, aSheet) {
  3266. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  3267. var s = aToken.value;
  3268. var valid = false;
  3269. var keyframesRule = new jscsspKeyframesRule();
  3270. keyframesRule.currentLine = currentLine;
  3271. this.preserveState();
  3272. var token = this.getToken(true, true);
  3273. var foundName = false;
  3274. while (token.isNotNull()) {
  3275. if (token.isIdent()) {
  3276. // should be the keyframes' name
  3277. foundName = true;
  3278. s += " " + token.value;
  3279. keyframesRule.name = token.value;
  3280. token = this.getToken(true, true);
  3281. if (token.isSymbol("{"))
  3282. this.ungetToken();
  3283. else {
  3284. // error...
  3285. token.type = jscsspToken.NULL_TYPE;
  3286. break;
  3287. }
  3288. }
  3289. else if (token.isSymbol("{")) {
  3290. if (!foundName) {
  3291. token.type = jscsspToken.NULL_TYPE;
  3292. // not a valid keyframes at-rule
  3293. }
  3294. break;
  3295. }
  3296. else {
  3297. token.type = jscsspToken.NULL_TYPE;
  3298. // not a valid keyframes at-rule
  3299. break;
  3300. }
  3301. token = this.getToken(true, true);
  3302. }
  3303. if (token.isSymbol("{") && keyframesRule.name) {
  3304. // ok let's parse keyframe rules now...
  3305. s += " { ";
  3306. token = this.getToken(true, false);
  3307. while (token.isNotNull()) {
  3308. if (token.isComment() && this.mPreserveComments) {
  3309. s += " " + token.value;
  3310. var comment = new jscsspComment();
  3311. comment.parsedCssText = token.value;
  3312. keyframesRule.cssRules.push(comment);
  3313. } else if (token.isSymbol("}")) {
  3314. valid = true;
  3315. break;
  3316. } else {
  3317. var r = this.parseKeyframeRule(token, keyframesRule, true);
  3318. if (r)
  3319. s += r;
  3320. }
  3321. token = this.getToken(true, false);
  3322. }
  3323. }
  3324. if (valid) {
  3325. this.forgetState();
  3326. keyframesRule.currentLine = currentLine;
  3327. keyframesRule.parsedCssText = s;
  3328. aSheet.cssRules.push(keyframesRule);
  3329. return true;
  3330. }
  3331. this.restoreState();
  3332. return false;
  3333. },
  3334. parseKeyframeRule: function(aToken, aOwner) {
  3335. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  3336. this.preserveState();
  3337. var token = aToken;
  3338. // find the keyframe keys
  3339. var key = "";
  3340. while (token.isNotNull()) {
  3341. if (token.isIdent() || token.isPercentage()) {
  3342. if (token.isIdent()
  3343. && !token.isIdent("from")
  3344. && !token.isIdent("to")) {
  3345. key = "";
  3346. break;
  3347. }
  3348. key += token.value;
  3349. token = this.getToken(true, true);
  3350. if (token.isSymbol("{")) {
  3351. this.ungetToken();
  3352. break;
  3353. }
  3354. else
  3355. if (token.isSymbol(",")) {
  3356. key += ", ";
  3357. }
  3358. else {
  3359. key = "";
  3360. break;
  3361. }
  3362. }
  3363. else {
  3364. key = "";
  3365. break;
  3366. }
  3367. token = this.getToken(true, true);
  3368. }
  3369. var valid = false;
  3370. var declarations = [];
  3371. if (key) {
  3372. var s = key;
  3373. token = this.getToken(true, true);
  3374. if (token.isSymbol("{")) {
  3375. s += " { ";
  3376. token = this.getToken(true, false);
  3377. while (true) {
  3378. if (!token.isNotNull()) {
  3379. valid = true;
  3380. break;
  3381. }
  3382. if (token.isSymbol("}")) {
  3383. s += "}";
  3384. valid = true;
  3385. break;
  3386. } else {
  3387. var d = this.parseDeclaration(token, declarations, true, true, aOwner);
  3388. s += ((d && declarations.length) ? " " : "") + d;
  3389. }
  3390. token = this.getToken(true, false);
  3391. }
  3392. }
  3393. }
  3394. else {
  3395. // key is invalid so the whole rule is invalid with it
  3396. }
  3397. if (valid) {
  3398. var rule = new jscsspKeyframeRule();
  3399. rule.currentLine = currentLine;
  3400. rule.parsedCssText = s;
  3401. rule.declarations = declarations;
  3402. rule.keyText = key;
  3403. rule.parentRule = aOwner;
  3404. aOwner.cssRules.push(rule);
  3405. return s;
  3406. }
  3407. this.restoreState();
  3408. s = this.currentToken().value;
  3409. this.addUnknownAtRule(aOwner, s);
  3410. return "";
  3411. },
  3412. parseMediaRule: function(aToken, aSheet) {
  3413. this.mScanner.mMediaQueryMode = true;
  3414. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  3415. var s = aToken.value;
  3416. var valid = false;
  3417. var mediaRule = new jscsspMediaRule();
  3418. mediaRule.currentLine = currentLine;
  3419. this.preserveState();
  3420. var token = this.getToken(true, true);
  3421. var foundMedia = false;
  3422. while (token.isNotNull()) {
  3423. if (token.isIdent()) {
  3424. foundMedia = true;
  3425. s += " " + token.value;
  3426. mediaRule.media.push(token.value);
  3427. token = this.getToken(true, true);
  3428. if (token.isSymbol(",")) {
  3429. s += ",";
  3430. } else {
  3431. if (token.isSymbol("{"))
  3432. this.ungetToken();
  3433. else {
  3434. // error...
  3435. token.type = jscsspToken.NULL_TYPE;
  3436. break;
  3437. }
  3438. }
  3439. }
  3440. else if (token.isSymbol("{"))
  3441. break;
  3442. else if (foundMedia) {
  3443. token.type = jscsspToken.NULL_TYPE;
  3444. // not a media list
  3445. break;
  3446. }
  3447. token = this.getToken(true, true);
  3448. }
  3449. if (token.isSymbol("{") && mediaRule.media.length) {
  3450. // ok let's parse style rules now...
  3451. s += " { ";
  3452. token = this.getToken(true, false);
  3453. while (token.isNotNull()) {
  3454. if (token.isComment() && this.mPreserveComments) {
  3455. s += " " + token.value;
  3456. var comment = new jscsspComment();
  3457. comment.parsedCssText = token.value;
  3458. mediaRule.cssRules.push(comment);
  3459. } else if (token.isSymbol("}")) {
  3460. valid = true;
  3461. break;
  3462. } else {
  3463. var r = this.parseStyleRule(token, mediaRule, true);
  3464. if (r)
  3465. s += r;
  3466. }
  3467. token = this.getToken(true, false);
  3468. }
  3469. }
  3470. if (valid) {
  3471. this.forgetState();
  3472. mediaRule.parsedCssText = s;
  3473. aSheet.cssRules.push(mediaRule);
  3474. return true;
  3475. }
  3476. this.restoreState();
  3477. return false;
  3478. },
  3479. trim11: function(str) {
  3480. str = str.replace(/^\s+/, '');
  3481. for (var i = str.length - 1; i >= 0; i--) {
  3482. if (/\S/.test( str.charAt(i) )) { // XXX charat
  3483. str = str.substring(0, i + 1);
  3484. break;
  3485. }
  3486. }
  3487. return str;
  3488. },
  3489. parseStyleRule: function(aToken, aOwner, aIsInsideMediaRule)
  3490. {
  3491. var currentLine = CountLF(this.mScanner.getAlreadyScanned());
  3492. this.preserveState();
  3493. // first let's see if we have a selector here...
  3494. var selector = this.parseSelector(aToken, false);
  3495. var valid = false;
  3496. var declarations = [];
  3497. if (selector) {
  3498. selector = this.trim11(selector.selector);
  3499. var s = selector;
  3500. var token = this.getToken(true, true);
  3501. if (token.isSymbol("{")) {
  3502. s += " { ";
  3503. var token = this.getToken(true, false);
  3504. while (true) {
  3505. if (!token.isNotNull()) {
  3506. valid = true;
  3507. break;
  3508. }
  3509. if (token.isSymbol("}")) {
  3510. s += "}";
  3511. valid = true;
  3512. break;
  3513. } else {
  3514. var d = this.parseDeclaration(token, declarations, true, true, aOwner);
  3515. s += ((d && declarations.length) ? " " : "") + d;
  3516. }
  3517. token = this.getToken(true, false);
  3518. }
  3519. }
  3520. }
  3521. else {
  3522. // selector is invalid so the whole rule is invalid with it
  3523. }
  3524. if (valid) {
  3525. var rule = new jscsspStyleRule();
  3526. rule.currentLine = currentLine;
  3527. rule.parsedCssText = s;
  3528. rule.declarations = declarations;
  3529. rule.mSelectorText = selector;
  3530. if (aIsInsideMediaRule)
  3531. rule.parentRule = aOwner;
  3532. else
  3533. rule.parentStyleSheet = aOwner;
  3534. aOwner.cssRules.push(rule);
  3535. return s;
  3536. }
  3537. this.restoreState();
  3538. s = this.currentToken().value;
  3539. this.addUnknownAtRule(aOwner, s);
  3540. return "";
  3541. },
  3542. parseSelector: function(aToken, aParseSelectorOnly) {
  3543. var s = "";
  3544. var specificity = {a: 0, b: 0, c: 0, d: 0}; // CSS 2.1 section 6.4.3
  3545. var isFirstInChain = true;
  3546. var token = aToken;
  3547. var valid = false;
  3548. var combinatorFound = false;
  3549. while (true) {
  3550. if (!token.isNotNull()) {
  3551. if (aParseSelectorOnly)
  3552. return {selector: s, specificity: specificity };
  3553. return "";
  3554. }
  3555. if (!aParseSelectorOnly && token.isSymbol("{")) {
  3556. // end of selector
  3557. valid = !combinatorFound;
  3558. if (valid) this.ungetToken();
  3559. break;
  3560. }
  3561. if (token.isSymbol(",")) { // group of selectors
  3562. s += token.value;
  3563. isFirstInChain = true;
  3564. combinatorFound = false;
  3565. token = this.getToken(false, true);
  3566. continue;
  3567. }
  3568. // now combinators and grouping...
  3569. else if (!combinatorFound
  3570. && (token.isWhiteSpace()
  3571. || token.isSymbol(">")
  3572. || token.isSymbol("+")
  3573. || token.isSymbol("~"))) {
  3574. if (token.isWhiteSpace()) {
  3575. s += " ";
  3576. var nextToken = this.lookAhead(true, true);
  3577. if (!nextToken.isNotNull()) {
  3578. if (aParseSelectorOnly)
  3579. return {selector: s, specificity: specificity };
  3580. return "";
  3581. }
  3582. if (nextToken.isSymbol(">")
  3583. || nextToken.isSymbol("+")
  3584. || nextToken.isSymbol("~")) {
  3585. token = this.getToken(true, true);
  3586. s += token.value + " ";
  3587. combinatorFound = true;
  3588. }
  3589. }
  3590. else {
  3591. s += token.value;
  3592. combinatorFound = true;
  3593. }
  3594. isFirstInChain = true;
  3595. token = this.getToken(true, true);
  3596. continue;
  3597. }
  3598. else {
  3599. var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, true);
  3600. if (!simpleSelector)
  3601. break; // error
  3602. s += simpleSelector.selector;
  3603. specificity.b += simpleSelector.specificity.b;
  3604. specificity.c += simpleSelector.specificity.c;
  3605. specificity.d += simpleSelector.specificity.d;
  3606. isFirstInChain = false;
  3607. combinatorFound = false;
  3608. }
  3609. token = this.getToken(false, true);
  3610. }
  3611. if (valid) {
  3612. return {selector: s, specificity: specificity };
  3613. }
  3614. return "";
  3615. },
  3616. isPseudoElement: function(aIdent)
  3617. {
  3618. switch (aIdent) {
  3619. case "first-letter":
  3620. case "first-line":
  3621. case "before":
  3622. case "after":
  3623. case "marker":
  3624. return true;
  3625. break;
  3626. default: return false;
  3627. break;
  3628. }
  3629. },
  3630. parseSimpleSelector: function(token, isFirstInChain, canNegate)
  3631. {
  3632. var s = "";
  3633. var specificity = {a: 0, b: 0, c: 0, d: 0}; // CSS 2.1 section 6.4.3
  3634. if (isFirstInChain
  3635. && (token.isSymbol("*") || token.isSymbol("|") || token.isIdent())) {
  3636. // type or universal selector
  3637. if (token.isSymbol("*") || token.isIdent()) {
  3638. // we don't know yet if it's a prefix or a universal
  3639. // selector
  3640. s += token.value;
  3641. var isIdent = token.isIdent();
  3642. token = this.getToken(false, true);
  3643. if (token.isSymbol("|")) {
  3644. // it's a prefix
  3645. s += token.value;
  3646. token = this.getToken(false, true);
  3647. if (token.isIdent() || token.isSymbol("*")) {
  3648. // ok we now have a type element or universal
  3649. // selector
  3650. s += token.value;
  3651. if (token.isIdent())
  3652. specificity.d++;
  3653. } else
  3654. // oops that's an error...
  3655. return null;
  3656. } else {
  3657. this.ungetToken();
  3658. if (isIdent)
  3659. specificity.d++;
  3660. }
  3661. } else if (token.isSymbol("|")) {
  3662. s += token.value;
  3663. token = this.getToken(false, true);
  3664. if (token.isIdent() || token.isSymbol("*")) {
  3665. s += token.value;
  3666. if (token.isIdent())
  3667. specificity.d++;
  3668. } else
  3669. // oops that's an error
  3670. return null;
  3671. }
  3672. }
  3673. else if (token.isSymbol(".") || token.isSymbol("#")) {
  3674. var isClass = token.isSymbol(".");
  3675. s += token.value;
  3676. token = this.getToken(false, true);
  3677. if (token.isIdent()) {
  3678. s += token.value;
  3679. if (isClass)
  3680. specificity.c++;
  3681. else
  3682. specificity.b++;
  3683. }
  3684. else
  3685. return null;
  3686. }
  3687. else if (token.isSymbol(":")) {
  3688. s += token.value;
  3689. token = this.getToken(false, true);
  3690. if (token.isSymbol(":")) {
  3691. s += token.value;
  3692. token = this.getToken(false, true);
  3693. }
  3694. if (token.isIdent()) {
  3695. s += token.value;
  3696. if (this.isPseudoElement(token.value))
  3697. specificity.d++;
  3698. else
  3699. specificity.c++;
  3700. }
  3701. else if (token.isFunction()) {
  3702. s += token.value;
  3703. if (token.isFunction(":not(")) {
  3704. if (!canNegate)
  3705. return null;
  3706. token = this.getToken(true, true);
  3707. var simpleSelector = this.parseSimpleSelector(token, isFirstInChain, false);
  3708. if (!simpleSelector)
  3709. return null;
  3710. else {
  3711. s += simpleSelector.selector;
  3712. token = this.getToken(true, true);
  3713. if (token.isSymbol(")"))
  3714. s += ")";
  3715. else
  3716. return null;
  3717. }
  3718. specificity.c++;
  3719. }
  3720. else {
  3721. while (true) {
  3722. token = this.getToken(false, true);
  3723. if (token.isSymbol(")")) {
  3724. s += ")";
  3725. break;
  3726. } else
  3727. s += token.value;
  3728. }
  3729. specificity.c++;
  3730. }
  3731. } else
  3732. return null;
  3733. } else if (token.isSymbol("[")) {
  3734. s += "[";
  3735. token = this.getToken(true, true);
  3736. if (token.isIdent() || token.isSymbol("*")) {
  3737. s += token.value;
  3738. var nextToken = this.getToken(true, true);
  3739. if (token.isSymbol("|")) {
  3740. s += "|";
  3741. token = this.getToken(true, true);
  3742. if (token.isIdent())
  3743. s += token.value;
  3744. else
  3745. return null;
  3746. } else
  3747. this.ungetToken();
  3748. } else if (token.isSymbol("|")) {
  3749. s += "|";
  3750. token = this.getToken(true, true);
  3751. if (token.isIdent())
  3752. s += token.value;
  3753. else
  3754. return null;
  3755. }
  3756. else
  3757. return null;
  3758. // nothing, =, *=, $=, ^=, |=
  3759. token = this.getToken(true, true);
  3760. if (token.isIncludes()
  3761. || token.isDashmatch()
  3762. || token.isBeginsmatch()
  3763. || token.isEndsmatch()
  3764. || token.isContainsmatch()
  3765. || token.isSymbol("=")) {
  3766. s += token.value;
  3767. token = this.getToken(true, true);
  3768. if (token.isString() || token.isIdent()) {
  3769. s += token.value;
  3770. token = this.getToken(true, true);
  3771. }
  3772. else
  3773. return null;
  3774. if (token.isSymbol("]")) {
  3775. s += token.value;
  3776. specificity.c++;
  3777. }
  3778. else
  3779. return null;
  3780. }
  3781. else if (token.isSymbol("]")) {
  3782. s += token.value;
  3783. specificity.c++;
  3784. }
  3785. else
  3786. return null;
  3787. }
  3788. else if (token.isWhiteSpace()) {
  3789. var t = this.lookAhead(true, true);
  3790. if (t.isSymbol('{'))
  3791. return ""
  3792. }
  3793. if (s)
  3794. return {selector: s, specificity: specificity };
  3795. return null;
  3796. },
  3797. preserveState: function() {
  3798. this.mPreservedTokens.push(this.currentToken());
  3799. this.mScanner.preserveState();
  3800. },
  3801. restoreState: function() {
  3802. if (this.mPreservedTokens.length) {
  3803. this.mScanner.restoreState();
  3804. this.mToken = this.mPreservedTokens.pop();
  3805. }
  3806. },
  3807. forgetState: function() {
  3808. if (this.mPreservedTokens.length) {
  3809. this.mScanner.forgetState();
  3810. this.mPreservedTokens.pop();
  3811. }
  3812. },
  3813. parse: function(aString, aTryToPreserveWhitespaces, aTryToPreserveComments) {
  3814. if (!aString)
  3815. return null; // early way out if we can
  3816. this.mPreserveWS = aTryToPreserveWhitespaces;
  3817. this.mPreserveComments = aTryToPreserveComments;
  3818. this.mPreservedTokens = [];
  3819. this.mScanner.init(aString);
  3820. var sheet = new jscsspStylesheet();
  3821. // @charset can only appear at first char of the stylesheet
  3822. var token = this.getToken(false, false);
  3823. if (!token.isNotNull())
  3824. return;
  3825. if (token.isAtRule("@charset")) {
  3826. this.parseCharsetRule(token, sheet);
  3827. token = this.getToken(false, false);
  3828. }
  3829. var foundStyleRules = false;
  3830. var foundImportRules = false;
  3831. var foundNameSpaceRules = false;
  3832. while (true) {
  3833. if (!token.isNotNull())
  3834. break;
  3835. if (token.isWhiteSpace())
  3836. {
  3837. if (aTryToPreserveWhitespaces)
  3838. this.addWhitespace(sheet, token.value);
  3839. }
  3840. else if (token.isComment())
  3841. {
  3842. if (this.mPreserveComments)
  3843. this.addComment(sheet, token.value);
  3844. }
  3845. else if (token.isAtRule()) {
  3846. if (token.isAtRule("@variables")) {
  3847. if (!foundImportRules && !foundStyleRules)
  3848. this.parseVariablesRule(token, sheet);
  3849. else {
  3850. this.reportError(kVARIABLES_RULE_POSITION);
  3851. this.addUnknownAtRule(sheet, token.value);
  3852. }
  3853. }
  3854. else if (token.isAtRule("@import")) {
  3855. // @import rules MUST occur before all style and namespace
  3856. // rules
  3857. if (!foundStyleRules && !foundNameSpaceRules)
  3858. foundImportRules = this.parseImportRule(token, sheet);
  3859. else {
  3860. this.reportError(kIMPORT_RULE_POSITION);
  3861. this.addUnknownAtRule(sheet, token.value);
  3862. }
  3863. }
  3864. else if (token.isAtRule("@namespace")) {
  3865. // @namespace rules MUST occur before all style rule and
  3866. // after all @import rules
  3867. if (!foundStyleRules)
  3868. foundNameSpaceRules = this.parseNamespaceRule(token, sheet);
  3869. else {
  3870. this.reportError(kNAMESPACE_RULE_POSITION);
  3871. this.addUnknownAtRule(sheet, token.value);
  3872. }
  3873. }
  3874. else if (token.isAtRule("@font-face")) {
  3875. if (this.parseFontFaceRule(token, sheet))
  3876. foundStyleRules = true;
  3877. else
  3878. this.addUnknownAtRule(sheet, token.value);
  3879. }
  3880. else if (token.isAtRule("@page")) {
  3881. if (this.parsePageRule(token, sheet))
  3882. foundStyleRules = true;
  3883. else
  3884. this.addUnknownAtRule(sheet, token.value);
  3885. }
  3886. else if (token.isAtRule("@media")) {
  3887. if (this.parseMediaRule(token, sheet))
  3888. foundStyleRules = true;
  3889. else
  3890. this.addUnknownAtRule(sheet, token.value);
  3891. }
  3892. else if (token.isAtRule("@keyframes")) {
  3893. if (!this.parseKeyframesRule(token, sheet))
  3894. this.addUnknownAtRule(sheet, token.value);
  3895. }
  3896. else if (token.isAtRule("@charset")) {
  3897. this.reportError(kCHARSET_RULE_CHARSET_SOF);
  3898. this.addUnknownAtRule(sheet, token.value);
  3899. }
  3900. else {
  3901. this.reportError(kUNKNOWN_AT_RULE);
  3902. this.addUnknownAtRule(sheet, token.value);
  3903. }
  3904. }
  3905. else // plain style rules
  3906. {
  3907. var ruleText = this.parseStyleRule(token, sheet, false);
  3908. if (ruleText)
  3909. foundStyleRules = true;
  3910. }
  3911. token = this.getToken(false);
  3912. }
  3913. return sheet;
  3914. }
  3915. };
  3916. function jscsspToken(aType, aValue, aUnit)
  3917. {
  3918. this.type = aType;
  3919. this.value = aValue;
  3920. this.unit = aUnit;
  3921. }
  3922. jscsspToken.NULL_TYPE = 0;
  3923. jscsspToken.WHITESPACE_TYPE = 1;
  3924. jscsspToken.STRING_TYPE = 2;
  3925. jscsspToken.COMMENT_TYPE = 3;
  3926. jscsspToken.NUMBER_TYPE = 4;
  3927. jscsspToken.IDENT_TYPE = 5;
  3928. jscsspToken.FUNCTION_TYPE = 6;
  3929. jscsspToken.ATRULE_TYPE = 7;
  3930. jscsspToken.INCLUDES_TYPE = 8;
  3931. jscsspToken.DASHMATCH_TYPE = 9;
  3932. jscsspToken.BEGINSMATCH_TYPE = 10;
  3933. jscsspToken.ENDSMATCH_TYPE = 11;
  3934. jscsspToken.CONTAINSMATCH_TYPE = 12;
  3935. jscsspToken.SYMBOL_TYPE = 13;
  3936. jscsspToken.DIMENSION_TYPE = 14;
  3937. jscsspToken.PERCENTAGE_TYPE = 15;
  3938. jscsspToken.HEX_TYPE = 16;
  3939. jscsspToken.prototype = {
  3940. isNotNull: function ()
  3941. {
  3942. return this.type;
  3943. },
  3944. _isOfType: function (aType, aValue)
  3945. {
  3946. return (this.type == aType && (!aValue || this.value.toLowerCase() == aValue));
  3947. },
  3948. isWhiteSpace: function(w)
  3949. {
  3950. return this._isOfType(jscsspToken.WHITESPACE_TYPE, w);
  3951. },
  3952. isString: function()
  3953. {
  3954. return this._isOfType(jscsspToken.STRING_TYPE);
  3955. },
  3956. isComment: function()
  3957. {
  3958. return this._isOfType(jscsspToken.COMMENT_TYPE);
  3959. },
  3960. isNumber: function(n)
  3961. {
  3962. return this._isOfType(jscsspToken.NUMBER_TYPE, n);
  3963. },
  3964. isSymbol: function(c)
  3965. {
  3966. return this._isOfType(jscsspToken.SYMBOL_TYPE, c);
  3967. },
  3968. isIdent: function(i)
  3969. {
  3970. return this._isOfType(jscsspToken.IDENT_TYPE, i);
  3971. },
  3972. isFunction: function(f)
  3973. {
  3974. return this._isOfType(jscsspToken.FUNCTION_TYPE, f);
  3975. },
  3976. isAtRule: function(a)
  3977. {
  3978. return this._isOfType(jscsspToken.ATRULE_TYPE, a);
  3979. },
  3980. isIncludes: function()
  3981. {
  3982. return this._isOfType(jscsspToken.INCLUDES_TYPE);
  3983. },
  3984. isDashmatch: function()
  3985. {
  3986. return this._isOfType(jscsspToken.DASHMATCH_TYPE);
  3987. },
  3988. isBeginsmatch: function()
  3989. {
  3990. return this._isOfType(jscsspToken.BEGINSMATCH_TYPE);
  3991. },
  3992. isEndsmatch: function()
  3993. {
  3994. return this._isOfType(jscsspToken.ENDSMATCH_TYPE);
  3995. },
  3996. isContainsmatch: function()
  3997. {
  3998. return this._isOfType(jscsspToken.CONTAINSMATCH_TYPE);
  3999. },
  4000. isSymbol: function(c)
  4001. {
  4002. return this._isOfType(jscsspToken.SYMBOL_TYPE, c);
  4003. },
  4004. isDimension: function()
  4005. {
  4006. return this._isOfType(jscsspToken.DIMENSION_TYPE);
  4007. },
  4008. isPercentage: function()
  4009. {
  4010. return this._isOfType(jscsspToken.PERCENTAGE_TYPE);
  4011. },
  4012. isHex: function()
  4013. {
  4014. return this._isOfType(jscsspToken.HEX_TYPE);
  4015. },
  4016. isDimensionOfUnit: function(aUnit)
  4017. {
  4018. return (this.isDimension() && this.unit == aUnit);
  4019. },
  4020. isLength: function()
  4021. {
  4022. return (this.isPercentage() ||
  4023. this.isDimensionOfUnit("cm") ||
  4024. this.isDimensionOfUnit("mm") ||
  4025. this.isDimensionOfUnit("in") ||
  4026. this.isDimensionOfUnit("pc") ||
  4027. this.isDimensionOfUnit("px") ||
  4028. this.isDimensionOfUnit("em") ||
  4029. this.isDimensionOfUnit("ex") ||
  4030. this.isDimensionOfUnit("pt"));
  4031. },
  4032. isAngle: function()
  4033. {
  4034. return (this.isDimensionOfUnit("deg") ||
  4035. this.isDimensionOfUnit("rad") ||
  4036. this.isDimensionOfUnit("grad"));
  4037. }
  4038. }
  4039. var kJscsspUNKNOWN_RULE = 0;
  4040. var kJscsspSTYLE_RULE = 1
  4041. var kJscsspCHARSET_RULE = 2;
  4042. var kJscsspIMPORT_RULE = 3;
  4043. var kJscsspMEDIA_RULE = 4;
  4044. var kJscsspFONT_FACE_RULE = 5;
  4045. var kJscsspPAGE_RULE = 6;
  4046. var kJscsspKEYFRAMES_RULE = 7;
  4047. var kJscsspKEYFRAME_RULE = 8;
  4048. var kJscsspNAMESPACE_RULE = 100;
  4049. var kJscsspCOMMENT = 101;
  4050. var kJscsspWHITE_SPACE = 102;
  4051. var kJscsspVARIABLES_RULE = 200;
  4052. var kJscsspSTYLE_DECLARATION = 1000;
  4053. var gTABS = "";
  4054. function jscsspStylesheet()
  4055. {
  4056. this.cssRules = [];
  4057. this.variables = {};
  4058. }
  4059. jscsspStylesheet.prototype = {
  4060. insertRule: function(aRule, aIndex) {
  4061. try {
  4062. this.cssRules.splice(aIndex, 1, aRule);
  4063. }
  4064. catch(e) {
  4065. }
  4066. },
  4067. deleteRule: function(aIndex) {
  4068. try {
  4069. this.cssRules.splice(aIndex);
  4070. }
  4071. catch(e) {
  4072. }
  4073. },
  4074. cssText: function() {
  4075. var rv = "";
  4076. for (var i = 0; i < this.cssRules.length; i++)
  4077. rv += this.cssRules[i].cssText() + "\n";
  4078. return rv;
  4079. },
  4080. resolveVariables: function(aMedium) {
  4081. function ItemFoundInArray(aArray, aItem) {
  4082. for (var i = 0; i < aArray.length; i++)
  4083. if (aItem == aArray[i])
  4084. return true;
  4085. return false;
  4086. }
  4087. for (var i = 0; i < this.cssRules.length; i++)
  4088. {
  4089. var rule = this.cssRules[i];
  4090. if (rule.type == kJscsspSTYLE_RULE || rule.type == kJscsspIMPORT_RULE)
  4091. break;
  4092. else if (rule.type == kJscsspVARIABLES_RULE &&
  4093. (!rule.media.length || ItemFoundInArray(rule.media, aMedium))) {
  4094. for (var j = 0; j < rule.declarations.length; j++) {
  4095. var valueText = "";
  4096. for (var k = 0; k < rule.declarations[j].values.length; k++)
  4097. valueText += (k ? " " : "") + rule.declarations[j].values[k].value;
  4098. this.variables[rule.declarations[j].property] = valueText;
  4099. }
  4100. }
  4101. }
  4102. }
  4103. };
  4104. /* kJscsspCHARSET_RULE */
  4105. function jscsspCharsetRule()
  4106. {
  4107. this.type = kJscsspCHARSET_RULE;
  4108. this.encoding = null;
  4109. this.parsedCssText = null;
  4110. this.parentStyleSheet = null;
  4111. this.parentRule = null;
  4112. }
  4113. jscsspCharsetRule.prototype = {
  4114. cssText: function() {
  4115. return "@charset " + this.encoding + ";";
  4116. },
  4117. setCssText: function(val) {
  4118. var sheet = {cssRules: []};
  4119. var parser = new CSSParser(val);
  4120. var token = parser.getToken(false, false);
  4121. if (token.isAtRule("@charset")) {
  4122. if (parser.parseCharsetRule(token, sheet)) {
  4123. var newRule = sheet.cssRules[0];
  4124. this.encoding = newRule.encoding;
  4125. this.parsedCssText = newRule.parsedCssText;
  4126. return;
  4127. }
  4128. }
  4129. throw DOMException.SYNTAX_ERR;
  4130. }
  4131. };
  4132. /* kJscsspUNKNOWN_RULE */
  4133. function jscsspErrorRule(aErrorMsg)
  4134. {
  4135. this.error = aErrorMsg ? aErrorMsg : "INVALID";
  4136. this.type = kJscsspUNKNOWN_RULE;
  4137. this.parsedCssText = null;
  4138. this.parentStyleSheet = null;
  4139. this.parentRule = null;
  4140. }
  4141. jscsspErrorRule.prototype = {
  4142. cssText: function() {
  4143. return this.parsedCssText;
  4144. }
  4145. };
  4146. /* kJscsspCOMMENT */
  4147. function jscsspComment()
  4148. {
  4149. this.type = kJscsspCOMMENT;
  4150. this.parsedCssText = null;
  4151. this.parentStyleSheet = null;
  4152. this.parentRule = null;
  4153. }
  4154. jscsspComment.prototype = {
  4155. cssText: function() {
  4156. return this.parsedCssText;
  4157. },
  4158. setCssText: function(val) {
  4159. var parser = new CSSParser(val);
  4160. var token = parser.getToken(true, false);
  4161. if (token.isComment())
  4162. this.parsedCssText = token.value;
  4163. else
  4164. throw DOMException.SYNTAX_ERR;
  4165. }
  4166. };
  4167. /* kJscsspWHITE_SPACE */
  4168. function jscsspWhitespace()
  4169. {
  4170. this.type = kJscsspWHITE_SPACE;
  4171. this.parsedCssText = null;
  4172. this.parentStyleSheet = null;
  4173. this.parentRule = null;
  4174. }
  4175. jscsspWhitespace.prototype = {
  4176. cssText: function() {
  4177. return this.parsedCssText;
  4178. }
  4179. };
  4180. /* kJscsspIMPORT_RULE */
  4181. function jscsspImportRule()
  4182. {
  4183. this.type = kJscsspIMPORT_RULE;
  4184. this.parsedCssText = null;
  4185. this.href = null;
  4186. this.media = [];
  4187. this.parentStyleSheet = null;
  4188. this.parentRule = null;
  4189. }
  4190. jscsspImportRule.prototype = {
  4191. cssText: function() {
  4192. var mediaString = this.media.join(", ");
  4193. return "@import " + this.href
  4194. + ((mediaString && mediaString != "all") ? mediaString + " " : "")
  4195. + ";";
  4196. },
  4197. setCssText: function(val) {
  4198. var sheet = {cssRules: []};
  4199. var parser = new CSSParser(val);
  4200. var token = parser.getToken(true, true);
  4201. if (token.isAtRule("@import")) {
  4202. if (parser.parseImportRule(token, sheet)) {
  4203. var newRule = sheet.cssRules[0];
  4204. this.href = newRule.href;
  4205. this.media = newRule.media;
  4206. this.parsedCssText = newRule.parsedCssText;
  4207. return;
  4208. }
  4209. }
  4210. throw DOMException.SYNTAX_ERR;
  4211. }
  4212. };
  4213. /* kJscsspNAMESPACE_RULE */
  4214. function jscsspNamespaceRule()
  4215. {
  4216. this.type = kJscsspNAMESPACE_RULE;
  4217. this.parsedCssText = null;
  4218. this.prefix = null;
  4219. this.url = null;
  4220. this.parentStyleSheet = null;
  4221. this.parentRule = null;
  4222. }
  4223. jscsspNamespaceRule.prototype = {
  4224. cssText: function() {
  4225. return "@namespace " + (this.prefix ? this.prefix + " ": "")
  4226. + this.url
  4227. + ";";
  4228. },
  4229. setCssText: function(val) {
  4230. var sheet = {cssRules: []};
  4231. var parser = new CSSParser(val);
  4232. var token = parser.getToken(true, true);
  4233. if (token.isAtRule("@namespace")) {
  4234. if (parser.parseNamespaceRule(token, sheet)) {
  4235. var newRule = sheet.cssRules[0];
  4236. this.url = newRule.url;
  4237. this.prefix = newRule.prefix;
  4238. this.parsedCssText = newRule.parsedCssText;
  4239. return;
  4240. }
  4241. }
  4242. throw DOMException.SYNTAX_ERR;
  4243. }
  4244. };
  4245. /* kJscsspSTYLE_DECLARATION */
  4246. function jscsspDeclaration()
  4247. {
  4248. this.type = kJscsspSTYLE_DECLARATION;
  4249. this.property = null;
  4250. this.values = [];
  4251. this.valueText = null;
  4252. this.priority = null;
  4253. this.parsedCssText = null;
  4254. this.parentStyleSheet = null;
  4255. this.parentRule = null;
  4256. }
  4257. jscsspDeclaration.prototype = {
  4258. kCOMMA_SEPARATED: {
  4259. "cursor": true,
  4260. "font-family": true,
  4261. "voice-family": true,
  4262. "background-image": true
  4263. },
  4264. kUNMODIFIED_COMMA_SEPARATED_PROPERTIES: {
  4265. "text-shadow": true,
  4266. "box-shadow": true,
  4267. "-moz-transition": true,
  4268. "-moz-transition-property": true,
  4269. "-moz-transition-duration": true,
  4270. "-moz-transition-timing-function": true,
  4271. "-moz-transition-delay": true
  4272. },
  4273. cssText: function() {
  4274. var prefixes = CssInspector.prefixesForProperty(this.property);
  4275. if (this.property in this.kUNMODIFIED_COMMA_SEPARATED_PROPERTIES) {
  4276. if (prefixes) {
  4277. var rv = "";
  4278. for (var propertyIndex = 0; propertyIndex < prefixes.length; propertyIndex++) {
  4279. var property = prefixes[propertyIndex];
  4280. rv += (propertyIndex ? gTABS : "") + property + ": ";
  4281. rv += this.valueText + (this.priority ? " !important" : "") + ";";
  4282. rv += ((prefixes.length > 1 && propertyIndex != prefixes.length -1) ? "\n" : "");
  4283. }
  4284. return rv;
  4285. }
  4286. return this.property + ": " + this.valueText +
  4287. (this.priority ? " !important" : "") + ";"
  4288. }
  4289. if (prefixes) {
  4290. var rv = "";
  4291. for (var propertyIndex = 0; propertyIndex < prefixes.length; propertyIndex++) {
  4292. var property = prefixes[propertyIndex];
  4293. rv += (propertyIndex ? gTABS : "") + property + ": ";
  4294. var separator = (property in this.kCOMMA_SEPARATED) ? ", " : " ";
  4295. for (var i = 0; i < this.values.length; i++)
  4296. if (this.values[i].cssText() != null)
  4297. rv += (i ? separator : "") + this.values[i].cssText();
  4298. else
  4299. return null;
  4300. rv += (this.priority ? " !important" : "") + ";" +
  4301. ((prefixes.length > 1 && propertyIndex != prefixes.length -1) ? "\n" : "");
  4302. }
  4303. return rv;
  4304. }
  4305. var rv = this.property + ": ";
  4306. var separator = (this.property in this.kCOMMA_SEPARATED) ? ", " : " ";
  4307. var extras = {"webkit": false, "presto": false, "trident": false, "generic": false }
  4308. for (var i = 0; i < this.values.length; i++) {
  4309. var v = this.values[i].cssText();
  4310. if (v != null) {
  4311. var paren = v.indexOf("(");
  4312. var kwd = v;
  4313. if (paren != -1)
  4314. kwd = v.substr(0, paren);
  4315. if (kwd in kCSS_VENDOR_VALUES) {
  4316. for (var j in kCSS_VENDOR_VALUES[kwd]) {
  4317. extras[j] = extras[j] || (kCSS_VENDOR_VALUES[kwd][j] != "");
  4318. }
  4319. }
  4320. rv += (i ? separator : "") + v;
  4321. }
  4322. else
  4323. return null;
  4324. }
  4325. rv += (this.priority ? " !important" : "") + ";";
  4326. for (var j in extras) {
  4327. if (extras[j]) {
  4328. var str = "\n" + gTABS + this.property + ": ";
  4329. for (var i = 0; i < this.values.length; i++) {
  4330. var v = this.values[i].cssText();
  4331. if (v != null) {
  4332. var paren = v.indexOf("(");
  4333. var kwd = v;
  4334. if (paren != -1)
  4335. kwd = v.substr(0, paren);
  4336. if (kwd in kCSS_VENDOR_VALUES) {
  4337. functor = kCSS_VENDOR_VALUES[kwd][j];
  4338. if (functor) {
  4339. v = (typeof functor == "string") ? functor : functor(v, j);
  4340. if (!v) {
  4341. str = null;
  4342. break;
  4343. }
  4344. }
  4345. }
  4346. str += (i ? separator : "") + v;
  4347. }
  4348. else
  4349. return null;
  4350. }
  4351. if (str)
  4352. rv += str + ";"
  4353. else
  4354. rv += "\n" + gTABS + "/* Impossible to translate property " + this.property + " for " + j + " */";
  4355. }
  4356. }
  4357. return rv;
  4358. },
  4359. setCssText: function(val) {
  4360. var declarations = [];
  4361. var parser = new CSSParser(val);
  4362. var token = parser.getToken(true, true);
  4363. if (parser.parseDeclaration(token, declarations, true, true, null)
  4364. && declarations.length
  4365. && declarations[0].type == kJscsspSTYLE_DECLARATION) {
  4366. var newDecl = declarations.cssRules[0];
  4367. this.property = newDecl.property;
  4368. this.value = newDecl.value;
  4369. this.priority = newDecl.priority;
  4370. this.parsedCssText = newRule.parsedCssText;
  4371. return;
  4372. }
  4373. throw DOMException.SYNTAX_ERR;
  4374. }
  4375. };
  4376. /* kJscsspFONT_FACE_RULE */
  4377. function jscsspFontFaceRule()
  4378. {
  4379. this.type = kJscsspFONT_FACE_RULE;
  4380. this.parsedCssText = null;
  4381. this.descriptors = [];
  4382. this.parentStyleSheet = null;
  4383. this.parentRule = null;
  4384. }
  4385. jscsspFontFaceRule.prototype = {
  4386. cssText: function() {
  4387. var rv = gTABS + "@font-face {\n";
  4388. var preservedGTABS = gTABS;
  4389. gTABS += " ";
  4390. for (var i = 0; i < this.descriptors.length; i++)
  4391. rv += gTABS + this.descriptors[i].cssText() + "\n";
  4392. gTABS = preservedGTABS;
  4393. return rv + gTABS + "}";
  4394. },
  4395. setCssText: function(val) {
  4396. var sheet = {cssRules: []};
  4397. var parser = new CSSParser(val);
  4398. var token = parser.getToken(true, true);
  4399. if (token.isAtRule("@font-face")) {
  4400. if (parser.parseFontFaceRule(token, sheet)) {
  4401. var newRule = sheet.cssRules[0];
  4402. this.descriptors = newRule.descriptors;
  4403. this.parsedCssText = newRule.parsedCssText;
  4404. return;
  4405. }
  4406. }
  4407. throw DOMException.SYNTAX_ERR;
  4408. }
  4409. };
  4410. /* kJscsspKEYFRAMES_RULE */
  4411. function jscsspKeyframesRule()
  4412. {
  4413. this.type = kJscsspKEYFRAMES_RULE;
  4414. this.parsedCssText = null;
  4415. this.cssRules = [];
  4416. this.name = null;
  4417. this.parentStyleSheet = null;
  4418. this.parentRule = null;
  4419. }
  4420. jscsspKeyframesRule.prototype = {
  4421. cssText: function() {
  4422. var rv = gTABS
  4423. + "@keyframes "
  4424. + this.name + " {\n";
  4425. var preservedGTABS = gTABS;
  4426. gTABS += " ";
  4427. for (var i = 0; i < this.cssRules.length; i++)
  4428. rv += gTABS + this.cssRules[i].cssText() + "\n";
  4429. gTABS = preservedGTABS;
  4430. rv += gTABS + "}\n";
  4431. return rv;
  4432. },
  4433. setCssText: function(val) {
  4434. var sheet = {cssRules: []};
  4435. var parser = new CSSParser(val);
  4436. var token = parser.getToken(true, true);
  4437. if (token.isAtRule("@keyframes")) {
  4438. if (parser.parseKeyframesRule(token, sheet)) {
  4439. var newRule = sheet.cssRules[0];
  4440. this.cssRules = newRule.cssRules;
  4441. this.name = newRule.name;
  4442. this.parsedCssText = newRule.parsedCssText;
  4443. return;
  4444. }
  4445. }
  4446. throw DOMException.SYNTAX_ERR;
  4447. }
  4448. };
  4449. /* kJscsspKEYFRAME_RULE */
  4450. function jscsspKeyframeRule()
  4451. {
  4452. this.type = kJscsspKEYFRAME_RULE;
  4453. this.parsedCssText = null;
  4454. this.declarations = []
  4455. this.keyText = null;
  4456. this.parentStyleSheet = null;
  4457. this.parentRule = null;
  4458. }
  4459. jscsspKeyframeRule.prototype = {
  4460. cssText: function() {
  4461. var rv = this.keyText + " {\n";
  4462. var preservedGTABS = gTABS;
  4463. gTABS += " ";
  4464. for (var i = 0; i < this.declarations.length; i++) {
  4465. var declText = this.declarations[i].cssText();
  4466. if (declText)
  4467. rv += gTABS + this.declarations[i].cssText() + "\n";
  4468. }
  4469. gTABS = preservedGTABS;
  4470. return rv + gTABS + "}";
  4471. },
  4472. setCssText: function(val) {
  4473. var sheet = {cssRules: []};
  4474. var parser = new CSSParser(val);
  4475. var token = parser.getToken(true, true);
  4476. if (!token.isNotNull()) {
  4477. if (parser.parseKeyframeRule(token, sheet, false)) {
  4478. var newRule = sheet.cssRules[0];
  4479. this.keyText = newRule.keyText;
  4480. this.declarations = newRule.declarations;
  4481. this.parsedCssText = newRule.parsedCssText;
  4482. return;
  4483. }
  4484. }
  4485. throw DOMException.SYNTAX_ERR;
  4486. }
  4487. };
  4488. /* kJscsspMEDIA_RULE */
  4489. function jscsspMediaRule()
  4490. {
  4491. this.type = kJscsspMEDIA_RULE;
  4492. this.parsedCssText = null;
  4493. this.cssRules = [];
  4494. this.media = [];
  4495. this.parentStyleSheet = null;
  4496. this.parentRule = null;
  4497. }
  4498. jscsspMediaRule.prototype = {
  4499. cssText: function() {
  4500. var rv = gTABS + "@media " + this.media.join(", ") + " {\n";
  4501. var preservedGTABS = gTABS;
  4502. gTABS += " ";
  4503. for (var i = 0; i < this.cssRules.length; i++)
  4504. rv += gTABS + this.cssRules[i].cssText() + "\n";
  4505. gTABS = preservedGTABS;
  4506. return rv + gTABS + "}";
  4507. },
  4508. setCssText: function(val) {
  4509. var sheet = {cssRules: []};
  4510. var parser = new CSSParser(val);
  4511. var token = parser.getToken(true, true);
  4512. if (token.isAtRule("@media")) {
  4513. if (parser.parseMediaRule(token, sheet)) {
  4514. var newRule = sheet.cssRules[0];
  4515. this.cssRules = newRule.cssRules;
  4516. this.media = newRule.media;
  4517. this.parsedCssText = newRule.parsedCssText;
  4518. return;
  4519. }
  4520. }
  4521. throw DOMException.SYNTAX_ERR;
  4522. }
  4523. };
  4524. /* kJscsspSTYLE_RULE */
  4525. function jscsspStyleRule()
  4526. {
  4527. this.type = kJscsspSTYLE_RULE;
  4528. this.parsedCssText = null;
  4529. this.declarations = []
  4530. this.mSelectorText = null;
  4531. this.parentStyleSheet = null;
  4532. this.parentRule = null;
  4533. }
  4534. jscsspStyleRule.prototype = {
  4535. cssText: function() {
  4536. var rv = this.mSelectorText + " {\n";
  4537. var preservedGTABS = gTABS;
  4538. gTABS += " ";
  4539. for (var i = 0; i < this.declarations.length; i++) {
  4540. var declText = this.declarations[i].cssText();
  4541. if (declText)
  4542. rv += gTABS + this.declarations[i].cssText() + "\n";
  4543. }
  4544. gTABS = preservedGTABS;
  4545. return rv + gTABS + "}";
  4546. },
  4547. setCssText: function(val) {
  4548. var sheet = {cssRules: []};
  4549. var parser = new CSSParser(val);
  4550. var token = parser.getToken(true, true);
  4551. if (!token.isNotNull()) {
  4552. if (parser.parseStyleRule(token, sheet, false)) {
  4553. var newRule = sheet.cssRules[0];
  4554. this.mSelectorText = newRule.mSelectorText;
  4555. this.declarations = newRule.declarations;
  4556. this.parsedCssText = newRule.parsedCssText;
  4557. return;
  4558. }
  4559. }
  4560. throw DOMException.SYNTAX_ERR;
  4561. },
  4562. selectorText: function() {
  4563. return this.mSelectorText;
  4564. },
  4565. setSelectorText: function(val) {
  4566. var parser = new CSSParser(val);
  4567. var token = parser.getToken(true, true);
  4568. if (!token.isNotNull()) {
  4569. var s = parser.parseSelector(token, true);
  4570. if (s) {
  4571. this.mSelectorText = s.selector;
  4572. return;
  4573. }
  4574. }
  4575. throw DOMException.SYNTAX_ERR;
  4576. }
  4577. };
  4578. /* kJscsspPAGE_RULE */
  4579. function jscsspPageRule()
  4580. {
  4581. this.type = kJscsspPAGE_RULE;
  4582. this.parsedCssText = null;
  4583. this.pageSelector = null;
  4584. this.declarations = [];
  4585. this.parentStyleSheet = null;
  4586. this.parentRule = null;
  4587. }
  4588. jscsspPageRule.prototype = {
  4589. cssText: function() {
  4590. var rv = gTABS + "@page "
  4591. + (this.pageSelector ? this.pageSelector + " ": "")
  4592. + "{\n";
  4593. var preservedGTABS = gTABS;
  4594. gTABS += " ";
  4595. for (var i = 0; i < this.declarations.length; i++)
  4596. rv += gTABS + this.declarations[i].cssText() + "\n";
  4597. gTABS = preservedGTABS;
  4598. return rv + gTABS + "}";
  4599. },
  4600. setCssText: function(val) {
  4601. var sheet = {cssRules: []};
  4602. var parser = new CSSParser(val);
  4603. var token = parser.getToken(true, true);
  4604. if (token.isAtRule("@page")) {
  4605. if (parser.parsePageRule(token, sheet)) {
  4606. var newRule = sheet.cssRules[0];
  4607. this.pageSelector = newRule.pageSelector;
  4608. this.declarations = newRule.declarations;
  4609. this.parsedCssText = newRule.parsedCssText;
  4610. return;
  4611. }
  4612. }
  4613. throw DOMException.SYNTAX_ERR;
  4614. }
  4615. };
  4616. /* kJscsspVARIABLES_RULE */
  4617. function jscsspVariablesRule()
  4618. {
  4619. this.type = kJscsspVARIABLES_RULE;
  4620. this.parsedCssText = null;
  4621. this.declarations = [];
  4622. this.parentStyleSheet = null;
  4623. this.parentRule = null;
  4624. this.media = null;
  4625. }
  4626. jscsspVariablesRule.prototype = {
  4627. cssText: function() {
  4628. var rv = gTABS + "@variables " +
  4629. (this.media.length ? this.media.join(", ") + " " : "") +
  4630. "{\n";
  4631. var preservedGTABS = gTABS;
  4632. gTABS += " ";
  4633. for (var i = 0; i < this.declarations.length; i++)
  4634. rv += gTABS + this.declarations[i].cssText() + "\n";
  4635. gTABS = preservedGTABS;
  4636. return rv + gTABS + "}";
  4637. },
  4638. setCssText: function(val) {
  4639. var sheet = {cssRules: []};
  4640. var parser = new CSSParser(val);
  4641. var token = parser.getToken(true, true);
  4642. if (token.isAtRule("@variables")) {
  4643. if (parser.parseVariablesRule(token, sheet)) {
  4644. var newRule = sheet.cssRules[0];
  4645. this.declarations = newRule.declarations;
  4646. this.parsedCssText = newRule.parsedCssText;
  4647. return;
  4648. }
  4649. }
  4650. throw DOMException.SYNTAX_ERR;
  4651. }
  4652. };
  4653. var kJscsspINHERIT_VALUE = 0;
  4654. var kJscsspPRIMITIVE_VALUE = 1;
  4655. var kJscsspVARIABLE_VALUE = 4;
  4656. function jscsspVariable(aType, aSheet)
  4657. {
  4658. this.value = "";
  4659. this.type = aType;
  4660. this.name = null;
  4661. this.parentRule = null;
  4662. this.parentStyleSheet = aSheet;
  4663. }
  4664. jscsspVariable.prototype = {
  4665. cssText: function() {
  4666. if (this.type == kJscsspVARIABLE_VALUE)
  4667. return this.resolveVariable(this.name, this.parentRule, this.parentStyleSheet);
  4668. else
  4669. return this.value;
  4670. },
  4671. setCssText: function(val) {
  4672. if (this.type == kJscsspVARIABLE_VALUE)
  4673. throw DOMException.SYNTAX_ERR;
  4674. else
  4675. this.value = val;
  4676. },
  4677. resolveVariable: function(aName, aRule, aSheet)
  4678. {
  4679. if (aName.toLowerCase() in aSheet.variables)
  4680. return aSheet.variables[aName.toLowerCase()];
  4681. return null;
  4682. }
  4683. };
  4684. function ParseURL(buffer) {
  4685. var result = { };
  4686. result.protocol = "";
  4687. result.user = "";
  4688. result.password = "";
  4689. result.host = "";
  4690. result.port = "";
  4691. result.path = "";
  4692. result.query = "";
  4693. var section = "PROTOCOL";
  4694. var start = 0;
  4695. var wasSlash = false;
  4696. while(start < buffer.length) {
  4697. if(section == "PROTOCOL") {
  4698. if(buffer.charAt(start) == ':') {
  4699. section = "AFTER_PROTOCOL";
  4700. start++;
  4701. } else if(buffer.charAt(start) == '/' && result.protocol.length() == 0) {
  4702. section = PATH;
  4703. } else {
  4704. result.protocol += buffer.charAt(start++);
  4705. }
  4706. } else if(section == "AFTER_PROTOCOL") {
  4707. if(buffer.charAt(start) == '/') {
  4708. if(!wasSlash) {
  4709. wasSlash = true;
  4710. } else {
  4711. wasSlash = false;
  4712. section = "USER";
  4713. }
  4714. start ++;
  4715. } else {
  4716. throw new ParseException("Protocol shell be separated with 2 slashes");
  4717. }
  4718. } else if(section == "USER") {
  4719. if(buffer.charAt(start) == '/') {
  4720. result.host = result.user;
  4721. result.user = "";
  4722. section = "PATH";
  4723. } else if(buffer.charAt(start) == '?') {
  4724. result.host = result.user;
  4725. result.user = "";
  4726. section = "QUERY";
  4727. start++;
  4728. } else if(buffer.charAt(start) == ':') {
  4729. section = "PASSWORD";
  4730. start++;
  4731. } else if(buffer.charAt(start) == '@') {
  4732. section = "HOST";
  4733. start++;
  4734. } else {
  4735. result.user += buffer.charAt(start++);
  4736. }
  4737. } else if(section == "PASSWORD") {
  4738. if(buffer.charAt(start) == '/') {
  4739. result.host = result.user;
  4740. result.port = result.password;
  4741. result.user = "";
  4742. result.password = "";
  4743. section = "PATH";
  4744. } else if(buffer.charAt(start) == '?') {
  4745. result.host = result.user;
  4746. result.port = result.password;
  4747. result.user = "";
  4748. result.password = "";
  4749. section = "QUERY";
  4750. start ++;
  4751. } else if(buffer.charAt(start) == '@') {
  4752. section = "HOST";
  4753. start++;
  4754. } else {
  4755. result.password += buffer.charAt(start++);
  4756. }
  4757. } else if(section == "HOST") {
  4758. if(buffer.charAt(start) == '/') {
  4759. section = "PATH";
  4760. } else if(buffer.charAt(start) == ':') {
  4761. section = "PORT";
  4762. start++;
  4763. } else if(buffer.charAt(start) == '?') {
  4764. section = "QUERY";
  4765. start++;
  4766. } else {
  4767. result.host += buffer.charAt(start++);
  4768. }
  4769. } else if(section == "PORT") {
  4770. if(buffer.charAt(start) == '/') {
  4771. section = "PATH";
  4772. } else if(buffer.charAt(start) == '?') {
  4773. section = "QUERY";
  4774. start++;
  4775. } else {
  4776. result.port += buffer.charAt(start++);
  4777. }
  4778. } else if(section == "PATH") {
  4779. if(buffer.charAt(start) == '?') {
  4780. section = "QUERY";
  4781. start ++;
  4782. } else {
  4783. result.path += buffer.charAt(start++);
  4784. }
  4785. } else if(section == "QUERY") {
  4786. result.query += buffer.charAt(start++);
  4787. }
  4788. }
  4789. if(section == "PROTOCOL") {
  4790. result.host = result.protocol;
  4791. result.protocol = "http";
  4792. } else if(section == "AFTER_PROTOCOL") {
  4793. throw new ParseException("Invalid url");
  4794. } else if(section == "USER") {
  4795. result.host = result.user;
  4796. result.user = "";
  4797. } else if(section == "PASSWORD") {
  4798. result.host = result.user;
  4799. result.port = result.password;
  4800. result.user = "";
  4801. result.password = "";
  4802. }
  4803. return result;
  4804. }
  4805. function ParseException(description) {
  4806. this.description = description;
  4807. }
  4808. function CountLF(s)
  4809. {
  4810. var nCR = s.match( /\n/g );
  4811. return nCR ? nCR.length + 1 : 1;
  4812. }
  4813. function FilterLinearGradientForOutput(aValue, aEngine)
  4814. {
  4815. if (aEngine == "generic")
  4816. return aValue.substr(5);
  4817. if (aEngine == "webkit")
  4818. return aValue.replace( /\-moz\-/g , "-webkit-")
  4819. if (aEngine != "webkit20110101")
  4820. return "";
  4821. var g = CssInspector.parseBackgroundImages(aValue)[0];
  4822. var cancelled = false;
  4823. var str = "-webkit-gradient(linear, ";
  4824. var position = ("position" in g.value) ? g.value.position.toLowerCase() : "";
  4825. var angle = ("angle" in g.value) ? g.value.angle.toLowerCase() : "";
  4826. // normalize angle
  4827. if (angle) {
  4828. var match = angle.match(/^([0-9\-\.\\+]+)([a-z]*)/);
  4829. var angle = parseFloat(match[1]);
  4830. var unit = match[2];
  4831. switch (unit) {
  4832. case "grad": angle = angle * 90 / 100; break;
  4833. case "rad": angle = angle * 180 / Math.PI; break;
  4834. default: break;
  4835. }
  4836. while (angle < 0)
  4837. angle += 360;
  4838. while (angle >= 360)
  4839. angle -= 360;
  4840. }
  4841. // get startpoint w/o keywords
  4842. var startpoint = [];
  4843. var endpoint = [];
  4844. if (position != "") {
  4845. if (position == "center")
  4846. position = "center center";
  4847. startpoint = position.split(" ");
  4848. if (angle == "" && angle != 0) {
  4849. // no angle, then we just turn the point 180 degrees around center
  4850. switch (startpoint[0]) {
  4851. case "left": endpoint.push("right"); break;
  4852. case "center": endpoint.push("center"); break;
  4853. case "right": endpoint.push("left"); break;
  4854. default: {
  4855. var match = startpoint[0].match(/^([0-9\-\.\\+]+)([a-z]*)/);
  4856. var v = parseFloat(match[0]);
  4857. var unit = match[1];
  4858. if (unit == "%") {
  4859. endpoint.push((100-v) + "%");
  4860. }
  4861. else
  4862. cancelled = true;
  4863. }
  4864. break;
  4865. }
  4866. if (!cancelled)
  4867. switch (startpoint[1]) {
  4868. case "top": endpoint.push("bottom"); break;
  4869. case "center": endpoint.push("center"); break;
  4870. case "bottom": endpoint.push("top"); break;
  4871. default: {
  4872. var match = startpoint[1].match(/^([0-9\-\.\\+]+)([a-z]*)/);
  4873. var v = parseFloat(match[0]);
  4874. var unit = match[1];
  4875. if (unit == "%") {
  4876. endpoint.push((100-v) + "%");
  4877. }
  4878. else
  4879. cancelled = true;
  4880. }
  4881. break;
  4882. }
  4883. }
  4884. else {
  4885. switch (angle) {
  4886. case 0: endpoint.push("right"); endpoint.push(startpoint[1]); break;
  4887. case 90: endpoint.push(startpoint[0]); endpoint.push("top"); break;
  4888. case 180: endpoint.push("left"); endpoint.push(startpoint[1]); break;
  4889. case 270: endpoint.push(startpoint[0]); endpoint.push("bottom"); break;
  4890. default: cancelled = true; break;
  4891. }
  4892. }
  4893. }
  4894. else {
  4895. // no position defined, we accept only vertical and horizontal
  4896. if (angle == "")
  4897. angle = 270;
  4898. switch (angle) {
  4899. case 0: startpoint= ["left", "center"]; endpoint = ["right", "center"]; break;
  4900. case 90: startpoint= ["center", "bottom"]; endpoint = ["center", "top"]; break;
  4901. case 180: startpoint= ["right", "center"]; endpoint = ["left", "center"]; break;
  4902. case 270: startpoint= ["center", "top"]; endpoint = ["center", "bottom"]; break;
  4903. default: cancelled = true; break;
  4904. }
  4905. }
  4906. if (cancelled)
  4907. return "";
  4908. str += startpoint.join(" ") + ", " + endpoint.join(" ");
  4909. if (!g.value.stops[0].position)
  4910. g.value.stops[0].position = "0%";
  4911. if (!g.value.stops[g.value.stops.length-1].position)
  4912. g.value.stops[g.value.stops.length-1].position = "100%";
  4913. var current = 0;
  4914. for (var i = 0; i < g.value.stops.length && !cancelled; i++) {
  4915. var s = g.value.stops[i];
  4916. if (s.position) {
  4917. if (s.position.indexOf("%") == -1) {
  4918. cancelled = true;
  4919. break;
  4920. }
  4921. }
  4922. else {
  4923. var j = i + 1;
  4924. while (j < g.value.stops.length && !g.value.stops[j].position)
  4925. j++;
  4926. var inc = parseFloat(g.value.stops[j].position) - current;
  4927. for (var k = i; k < j; k++) {
  4928. g.value.stops[k].position = (current + inc * (k - i + 1) / (j - i + 1)) + "%";
  4929. }
  4930. }
  4931. current = parseFloat(s.position);
  4932. str += ", color-stop(" + (parseFloat(current) / 100) + ", " + s.color + ")";
  4933. }
  4934. if (cancelled)
  4935. return "";
  4936. return str + ")";
  4937. }
  4938. function FilterRadialGradientForOutput(aValue, aEngine)
  4939. {
  4940. if (aEngine == "generic")
  4941. return aValue.substr(5);
  4942. else if (aEngine == "webkit")
  4943. return aValue.replace( /\-moz\-/g , "-webkit-")
  4944. else if (aEngine != "webkit20110101")
  4945. return "";
  4946. var g = CssInspector.parseBackgroundImages(aValue)[0];
  4947. var shape = ("shape" in g.value) ? g.value.shape : "";
  4948. var size = ("size" in g.value) ? g.value.size : "";
  4949. if (shape != "circle"
  4950. || (size != "farthest-corner" && size != "cover"))
  4951. return "";
  4952. if (g.value.stops.length < 2
  4953. || !("position" in g.value.stops[0])
  4954. || !g.value.stops[g.value.stops.length - 1].position
  4955. || !("position" in g.value.stops[0])
  4956. || !g.value.stops[g.value.stops.length - 1].position)
  4957. return "";
  4958. for (var i = 0; i < g.value.stops.length; i++) {
  4959. var s = g.value.stops[i];
  4960. if (("position" in s) && s.position && s.position.indexOf("px") == -1)
  4961. return "";
  4962. }
  4963. var str = "-webkit-gradient(radial, ";
  4964. var position = ("position" in g.value) ? g.value.position : "center center";
  4965. str += position + ", " + parseFloat(g.value.stops[0].position) + ", ";
  4966. str += position + ", " + parseFloat(g.value.stops[g.value.stops.length - 1].position);
  4967. // at this point we're sure to deal with pixels
  4968. var current = parseFloat(g.value.stops[0].position);
  4969. for (var i = 0; i < g.value.stops.length; i++) {
  4970. var s = g.value.stops[i];
  4971. if (!("position" in s) || !s.position) {
  4972. var j = i + 1;
  4973. while (j < g.value.stops.length && !g.value.stops[j].position)
  4974. j++;
  4975. var inc = parseFloat(g.value.stops[j].position) - current;
  4976. for (var k = i; k < j; k++) {
  4977. g.value.stops[k].position = (current + inc * (k - i + 1) / (j - i + 1)) + "px";
  4978. }
  4979. }
  4980. current = parseFloat(s.position);
  4981. var c = (current - parseFloat(g.value.stops[0].position)) /
  4982. (parseFloat(g.value.stops[g.value.stops.length - 1].position) - parseFloat(g.value.stops[0].position));
  4983. str += ", color-stop(" + c + ", " + s.color + ")";
  4984. }
  4985. str += ")"
  4986. return str;
  4987. }
  4988. function FilterRepeatingGradientForOutput(aValue, aEngine)
  4989. {
  4990. if (aEngine == "generic")
  4991. return aValue.substr(5);
  4992. else if (aEngine == "webkit")
  4993. return aValue.replace( /\-moz\-/g , "-webkit-")
  4994. return "";
  4995. }