HtmlToWmlCssApplier.cs 165 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743
  1. // Copyright (c) Microsoft. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Xml.Linq;
  9. using OpenXmlPowerTools;
  10. using OpenXmlPowerTools.HtmlToWml;
  11. using OpenXmlPowerTools.HtmlToWml.CSS;
  12. using System.Globalization;
  13. #if false
  14. Sort:
  15. 1. User agent declarations
  16. 1. Default value
  17. 2. Specified in default style sheet (which I am going to supply)
  18. 2. User normal declarations
  19. 1. Specified in user-supplied style sheet
  20. 3. Author normal declarations
  21. 1. Specified in style sheet (can defer this until later)
  22. 2. Specified in style element
  23. 3. Specified in style attribute
  24. 4. Author important declarations
  25. 1. Specified in style sheet
  26. 5. User important declarations
  27. 1. Specified in style sheet
  28. Sort Key (most significant first)
  29. {0} 9 if user supplied style sheet, high
  30. {0} 8 if author supplied style sheet, high
  31. {0} 7 if style attribute, high
  32. {0} 6 if style attribute, normal
  33. {0} 5 if author suplied style sheet, normal
  34. {0} 4 if user supplied style sheet, normal
  35. {0} 3 if user-agent default style sheet, high
  36. {0} 2 if user-agent default style sheet, normal
  37. {0} 1 if inherited
  38. {1} count of number of ID attributes in selector
  39. {2} count of number of attributes and pseudo classes in selector
  40. {3} count of number of element names and pseudo elements in selector
  41. {4} sequence number in order added to list
  42. 1. Process user-agent default style sheet
  43. 2. Process user-supplied style sheet
  44. 3. process author-supplied style sheet
  45. 4. process STYLE element
  46. 5. process style attribute on all elements
  47. 6. expand all shorthand properties - the new properties have the same sort key as shorthand prop
  48. 7. Add initial values for all properties that don't have values
  49. The various types of properties:
  50. - Set by the style sheet explicitely
  51. - Set at root level of hierarchy so that other elements can inherit (if no other ancestor)
  52. - Set as initial value for certain elements - all properties have an initial value. Some properties apply to only certain elements.
  53. - Some properties inherit automatically, such as font-family.
  54. - Some properties are set to inherit in the stylesheet.
  55. - border-top-color etc. are set to the color property, which then inherits.
  56. Properties either inherit, or are set to an initial value. Those properties that inherit are set to initial value only at the top of
  57. the tree. Those props that are set to an initial value throughout the tree do not inherit. It is either one or the other.
  58. Following is my new theory of the correct algorithm:
  59. - set all properties from the cascade.
  60. - Set initial values for properties at the top of the tree. These specifically need to be set for other properties that will
  61. inherit from them.
  62. - create a matrix of all elements, and which properties need to be set for each element.
  63. - iterate through the tree.
  64. SetAllValues
  65. for each element
  66. for each property
  67. call GetComputedPropertyValue // implemented in a recursive fashion to set & get its computed value.
  68. GetComputedPropertyValue
  69. if (property is already computed)
  70. return the computed value
  71. if (property is set)
  72. compute value
  73. set the computed value
  74. return the computed value
  75. if (property is inherited (either because it was set to inherit, or because it is an inherited property))
  76. if (parent exists)
  77. call GetComputedValue on parent
  78. set the computed value
  79. return the computed value
  80. else
  81. call GetInitialValue for property
  82. compute value
  83. set the computed value
  84. return the computed value
  85. else
  86. call GetInitialValue for property
  87. compute value
  88. set the computed value
  89. return the computed value
  90. ComputeValue
  91. this needs to be specifically coded for each property
  92. if value is relative (em, ex, percentage,
  93. if property is not on font-size
  94. GetComputedValue for font-size
  95. compute value accordingly
  96. return value
  97. if property is on font-size
  98. call GetComputedValue for font-size of parent
  99. compute value accordingly
  100. return value
  101. if value is percentage
  102. if margin-top, margin-bottom, margin-right, margin-left, padding-top, padding-bottom, padding-right, padding-left
  103. call GetComputedValue for width of containing block
  104. if value is absolute (in, cm, mm, pt, pc, px)
  105. return value
  106. #endif
  107. namespace OpenXmlPowerTools.HtmlToWml
  108. {
  109. class CssApplier
  110. {
  111. private static List<PropertyInfo> PropertyInfoList = new List<PropertyInfo>()
  112. {
  113. // color
  114. // Value: <color> | inherit
  115. // Initial: depends on UA
  116. // Applies to: all elements
  117. // Inherited: yes
  118. // Percentages: N/A
  119. // Computed value: as spec
  120. new PropertyInfo
  121. {
  122. Names = new[] { "color" },
  123. Inherits = true,
  124. Includes = (e, settings) => true,
  125. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "black", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  126. ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = GetWmlColorFromExpression(assignedValue), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  127. },
  128. // direction
  129. // Value: ltr | rtl | inherit
  130. // Initial: ltr
  131. // Applies to: all elements
  132. // Inherited: yes
  133. // Percentages: N/A
  134. // Computed value: as spec
  135. new PropertyInfo
  136. {
  137. Names = new[] { "direction" },
  138. Inherits = true,
  139. Includes = (e, settings) => true,
  140. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "ltr", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  141. ComputedValue = null,
  142. },
  143. // line-height
  144. // Value: normal | <number> | <length> | <percentage> | <inherit>
  145. // Initial: normal
  146. // Applies to: all elements
  147. // Inherited: yes
  148. // Percentages: refer to the font size of the element itself
  149. // Computed value: for <length> and <percentage> the absolute value, otherwise as specified.
  150. new PropertyInfo
  151. {
  152. Names = new[] { "line-height" },
  153. Inherits = true,
  154. Includes = (e, settings) => true,
  155. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  156. ComputedValue = (element, assignedValue, settings) =>
  157. {
  158. CssExpression valueForPercentage = null;
  159. if (element.Parent != null)
  160. valueForPercentage = GetComputedPropertyValue(null, element, "font-size", settings);
  161. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  162. },
  163. },
  164. // visibility
  165. // Value: visible | hidden | collapse | inherit
  166. // Initial: visible
  167. // Applies to: all elements
  168. // Inherited: yes
  169. // Percentages: N/A
  170. // Computed value: as spec
  171. new PropertyInfo
  172. {
  173. Names = new[] { "visibility" },
  174. Inherits = true,
  175. Includes = (e, settings) => true,
  176. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "visible", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  177. ComputedValue = null,
  178. },
  179. // list-style-type
  180. // Value: disc | circle | square | decimal | decimal-leading-zero |
  181. // lower-roman | upper-roman | lower-greek | lower-latin |
  182. // upper-latin | armenian | georgian | lower-alpha | upper-alpha |
  183. // none | inherit
  184. // Initial: disc
  185. // Applies to: elements with display: list-item
  186. // Inherited: yes
  187. // Percentages: N/A
  188. // Computed value: as spec
  189. new PropertyInfo
  190. {
  191. Names = new[] { "list-style-type" },
  192. Inherits = true,
  193. Includes = (e, settings) =>
  194. {
  195. var display = GetComputedPropertyValue(null, e, "display", settings);
  196. if (display.ToString() == "list-item")
  197. return true;
  198. return false;
  199. },
  200. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "disc", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  201. ComputedValue = null,
  202. },
  203. // list-style-image
  204. // Value: <uri> | none | inherit
  205. // Initial: none
  206. // Applies to: elements with ’display: list-item’
  207. // Inherited: yes
  208. // Percentages: N/A
  209. // Computed value: absolute URI or ’none’
  210. new PropertyInfo
  211. {
  212. Names = new[] { "list-style-image" },
  213. Inherits = true,
  214. Includes = (e, settings) =>
  215. {
  216. var display = GetComputedPropertyValue(null, e, "display", settings);
  217. if (display.ToString() == "list-item")
  218. return true;
  219. return false;
  220. },
  221. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  222. ComputedValue = null,
  223. },
  224. // list-style-position
  225. // Value: inside | outside | inherit
  226. // Initial: outside
  227. // Applies to: elements with ’display: list-item’
  228. // Inherited: yes
  229. // Percentages: N/A
  230. // Computed value: as spec
  231. new PropertyInfo
  232. {
  233. Names = new[] { "list-style-position" },
  234. Inherits = true,
  235. Includes = (e, settings) =>
  236. {
  237. var display = GetComputedPropertyValue(null, e, "display", settings);
  238. if (display.ToString() == "list-item")
  239. return true;
  240. return false;
  241. },
  242. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  243. ComputedValue = null,
  244. },
  245. // font-family
  246. // Value: [[ <family-name> | <generic-family> ] [, <family-name>|
  247. // <generic-family>]* ] | inherit
  248. // Initial: depends on user agent
  249. // Applies to: all elements
  250. // Inherited: yes
  251. // Percentages: N/A
  252. // Computed value: as spec
  253. new PropertyInfo
  254. {
  255. Names = new[] { "font-family" },
  256. Inherits = true,
  257. Includes = (e, settings) => true,
  258. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = settings.MinorLatinFont, Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  259. ComputedValue = (element, assignedValue, settings) => assignedValue,
  260. },
  261. // font-style
  262. // Value: normal | italic | oblique | inherit
  263. // Initial: normal
  264. // Applies to: all elements
  265. // Inherited: yes
  266. // Percentages: N/A
  267. // Computed value: as spec
  268. new PropertyInfo
  269. {
  270. Names = new[] { "font-style" },
  271. Inherits = true,
  272. Includes = (e, settings) => true,
  273. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  274. ComputedValue = null,
  275. },
  276. // font-variant
  277. // Value: normal | small-caps | inherit
  278. // Initial: normal
  279. // Applies to: all elements
  280. // Inherited: yes
  281. // Percentages: N/A
  282. // Computed value: as spec
  283. new PropertyInfo
  284. {
  285. Names = new[] { "font-variant" },
  286. Inherits = true,
  287. Includes = (e, settings) => true,
  288. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  289. ComputedValue = null,
  290. },
  291. // font-weight
  292. // Value: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 |
  293. // 600 | 700 | 800 | 900 | inherit
  294. // Initial: normal
  295. // Applies to: all elements
  296. // Inherited: yes
  297. // Percentages: N/A
  298. // Computed value: see text
  299. new PropertyInfo
  300. {
  301. Names = new[] { "font-weight" },
  302. Inherits = true,
  303. Includes = (e, settings) => true,
  304. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  305. ComputedValue = null,
  306. },
  307. // font-size
  308. // Value: <absolute-size> | <relative-size> | <length> | <percentage> |
  309. // inherit
  310. // Initial: medium
  311. // Applies to: all elements
  312. // Inherited: yes
  313. // Percentages: refer to inherited font size
  314. // Computed value: absolute length
  315. new PropertyInfo
  316. {
  317. Names = new[] { "font-size" },
  318. Inherits = true,
  319. Includes = (e, settings) => true,
  320. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = ((double)settings.DefaultFontSize).ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, Unit = CssUnit.PT } } },
  321. ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteFontSize(element, assignedValue, settings),
  322. },
  323. // text-indent
  324. // Value: <length> | <percentage> | inherit
  325. // Initial: 0
  326. // Applies to: block containers
  327. // Inherited: yes
  328. // Percentages: refer to width of containing block
  329. // Computed value: the percentage as specified or the absolute length
  330. new PropertyInfo
  331. {
  332. Names = new[] { "text-indent" },
  333. Inherits = true,
  334. Includes = (e, settings) =>
  335. {
  336. var display = GetComputedPropertyValue(null, e, "display", settings);
  337. if (display.ToString() == "block")
  338. return true;
  339. return false;
  340. },
  341. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  342. ComputedValue = (element, assignedValue, settings) =>
  343. {
  344. CssExpression valueForPercentage = null;
  345. if (element.Parent != null)
  346. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  347. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  348. },
  349. },
  350. // text-align
  351. // Value: left | right | center | justify | inherit
  352. // Initial: a nameless value that acts as ’left’ if ’direction’ is ’ltr’, ’right’ if
  353. // ’direction’ is ’rtl’
  354. // Applies to: block containers
  355. // Inherited: yes
  356. // Percentages: N/A
  357. // Computed value: the initial value or as spec
  358. new PropertyInfo
  359. {
  360. Names = new[] { "text-align" },
  361. Inherits = true,
  362. Includes = (e, settings) =>
  363. {
  364. var display = GetComputedPropertyValue(null, e, "display", settings);
  365. if (display.ToString() == "block")
  366. return true;
  367. return false;
  368. },
  369. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "left", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } }, // todo should be based on the direction property
  370. ComputedValue = null,
  371. },
  372. // text-decoration
  373. // Value: none | [ underline || overline || line-through || blink ] | inherit
  374. // Initial: none
  375. // Applies to: all elements
  376. // Inherited: no
  377. // Percentages: N/A
  378. // Computed value: as spec
  379. new PropertyInfo
  380. {
  381. Names = new[] { "text-decoration" },
  382. Inherits = true, // todo need to read css 16.3.1 in full detail to understand how this is implemented.
  383. Includes = (e, settings) => true,
  384. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  385. ComputedValue = null,
  386. },
  387. // letter-spacing
  388. // Value: normal | <length> | inherit
  389. // Initial: normal
  390. // Applies to: all elements
  391. // Inherited: yes
  392. // Percentages: N/A
  393. // Computed value: ’normal’ or absolute length
  394. // word-spacing
  395. // Value: normal | <length> | inherit
  396. // Initial: normal
  397. // Applies to: all elements
  398. // Inherited: yes
  399. // Percentages: N/A
  400. // Computed value: for ’normal’ the value 0; otherwise the absolute length
  401. new PropertyInfo
  402. {
  403. Names = new[] { "letter-spacing", "word-spacing" },
  404. Inherits = true,
  405. Includes = (e, settings) => true,
  406. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  407. ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteLength(element, assignedValue, settings, null),
  408. },
  409. // white-space
  410. // Value: normal | pre | nowrap | pre-wrap | pre-line | inherit
  411. // Initial: normal
  412. // Applies to: all elements
  413. // Inherited: yes
  414. // Percentages: N/A
  415. // Computed value: as spec
  416. new PropertyInfo
  417. {
  418. Names = new[] { "white-space" },
  419. Inherits = true,
  420. Includes = (e, settings) => true,
  421. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  422. ComputedValue = null,
  423. },
  424. // caption-side
  425. // Value: top | bottom | inherit
  426. // Initial: top
  427. // Applies to: 'table-caption' elements
  428. // Inherited: yes
  429. // Percentages: N/A
  430. // Computed value: as spec
  431. new PropertyInfo
  432. {
  433. Names = new[] { "caption-side" },
  434. Inherits = true,
  435. Includes = (e, settings) =>
  436. {
  437. var display = GetComputedPropertyValue(null, e, "display", settings);
  438. if (display.ToString() == "table-caption")
  439. return true;
  440. return false;
  441. },
  442. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "top", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  443. ComputedValue = null,
  444. },
  445. // border-collapse
  446. // Value: collapse | separate | inherit
  447. // Initial: separate
  448. // Applies to: ’table’ and ’inline-table’ elements
  449. // Inherited: yes
  450. // Percentages: N/A
  451. // Computed value: as spec
  452. new PropertyInfo
  453. {
  454. Names = new[] { "border-collapse" },
  455. Inherits = true,
  456. Includes = (e, settings) =>
  457. {
  458. var display = GetComputedPropertyValue(null, e, "display", settings);
  459. if (display.ToString() == "table" || display.ToString() == "inline-table")
  460. return true;
  461. return false;
  462. },
  463. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "separate", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  464. ComputedValue = null,
  465. },
  466. // border-spacing
  467. // Value: <length> <length>? | inherit
  468. // Initial: 0
  469. // Applies to: ’table’ and ’inline-table’ elements
  470. // Inherited: yes
  471. // Percentages: N/A
  472. // Computed value: two absolute lengths
  473. new PropertyInfo
  474. {
  475. Names = new[] { "border-spacing" },
  476. Inherits = true,
  477. Includes = (e, settings) =>
  478. {
  479. var display = GetComputedPropertyValue(null, e, "display", settings);
  480. if (display.ToString() == "table" || display.ToString() == "inline-table")
  481. return true;
  482. return false;
  483. },
  484. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  485. ComputedValue = (element, assignedValue, settings) => ComputeAbsoluteLength(element, assignedValue, settings, null), // todo need to handle two lengths here
  486. },
  487. // empty-cells
  488. // Value: show | hide | inherit
  489. // Initial: show
  490. // Applies to: 'table-cell' elements
  491. // Inherited: yes
  492. // Percentages: N/A
  493. // Computed value: as spec
  494. new PropertyInfo
  495. {
  496. Names = new[] { "empty-cells" },
  497. Inherits = true,
  498. Includes = (e, settings) =>
  499. {
  500. var display = GetComputedPropertyValue(null, e, "display", settings);
  501. if (display.ToString() == "table" || display.ToString() == "table-cell")
  502. return true;
  503. return false;
  504. },
  505. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "show", } } },
  506. ComputedValue = null,
  507. },
  508. // margin-top, margin-bottom
  509. // Value: <margin-width> | inherit
  510. // Initial: 0
  511. // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table
  512. // all elements except th, td, tr
  513. // Inherited: no
  514. // Percentages: refer to width of containing block
  515. // Computed value: the percentage as specified or the absolute length
  516. new PropertyInfo
  517. {
  518. Names = new[] { "margin-top", "margin-bottom", },
  519. Inherits = false,
  520. Includes = (e, settings) =>
  521. {
  522. var display = GetComputedPropertyValue(null, e, "display", settings);
  523. if (display.ToString() == "table-caption" || display.ToString() == "table" || display.ToString() == "inline-table")
  524. return false;
  525. return true;
  526. },
  527. InitialValue = (element, settings) =>
  528. {
  529. if (settings.DefaultBlockContentMargin != null)
  530. {
  531. if (settings.DefaultBlockContentMargin == "auto")
  532. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } };
  533. else if (settings.DefaultBlockContentMargin.ToLower().EndsWith("pt"))
  534. {
  535. string s1 = settings.DefaultBlockContentMargin.Substring(0, settings.DefaultBlockContentMargin.Length - 2);
  536. double d1;
  537. if (double.TryParse(s1, NumberStyles.Float, CultureInfo.InvariantCulture, out d1))
  538. {
  539. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = d1.ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT } } };
  540. }
  541. }
  542. throw new OpenXmlPowerToolsException("invalid setting");
  543. }
  544. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT } } };
  545. },
  546. ComputedValue = (element, assignedValue, settings) =>
  547. {
  548. CssExpression valueForPercentage = null;
  549. if (element.Parent != null)
  550. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  551. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  552. },
  553. },
  554. // margin-right, margin-left
  555. // Value: <margin-width> | inherit
  556. // Initial: 0
  557. // Applies to: all elements except elements with table display types other than table-caption, table, and inline-table
  558. // all elements except th, td, tr
  559. // Inherited: no
  560. // Percentages: refer to width of containing block
  561. // Computed value: the percentage as specified or the absolute length
  562. new PropertyInfo
  563. {
  564. Names = new[] { "margin-right", "margin-left", },
  565. Inherits = false,
  566. Includes = (e, settings) =>
  567. {
  568. var display = GetComputedPropertyValue(null, e, "display", settings);
  569. if (display.ToString() == "table-caption" || display.ToString() == "table" || display.ToString() == "inline-table")
  570. return false;
  571. return true;
  572. },
  573. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  574. ComputedValue = (element, assignedValue, settings) =>
  575. {
  576. CssExpression valueForPercentage = null;
  577. if (element.Parent != null)
  578. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  579. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  580. },
  581. },
  582. // padding-top, padding-right, padding-bottom, padding-left
  583. // Value: <padding-width> | inherit
  584. // Initial: 0
  585. // Applies to: all elements except table-row-group, table-header-group,
  586. // table-footer-group, table-row, table-column-group and table-column
  587. // all elements except tr
  588. // Inherited: no
  589. // Percentages: refer to width of containing block
  590. // Computed value: the percentage as specified or the absolute length
  591. new PropertyInfo
  592. {
  593. Names = new[] { "padding-top", "padding-right", "padding-bottom", "padding-left" },
  594. Inherits = false,
  595. Includes = (e, settings) =>
  596. {
  597. var display = GetComputedPropertyValue(null, e, "display", settings);
  598. string dv = display.ToString();
  599. if (dv == "table-row-group" || dv == "table-header-group" || dv == "table-footer-group" || dv == "table-row" ||
  600. dv == "table-column-group" || dv == "table-column")
  601. return false;
  602. return true;
  603. },
  604. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  605. ComputedValue = (element, assignedValue, settings) =>
  606. {
  607. CssExpression valueForPercentage = null;
  608. if (element.Parent != null)
  609. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  610. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  611. },
  612. },
  613. // border-top-width, border-right-width, border-bottom-width, border-left-width
  614. // Value: <border-width> | inherit
  615. // Initial: medium
  616. // Applies to: all elements
  617. // Inherited: no
  618. // Percentages: N/A
  619. // Computed value: absolute length; '0' if the border style is 'none' or 'hidden'
  620. new PropertyInfo
  621. {
  622. Names = new[] { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", },
  623. Inherits = false,
  624. Includes = (e, settings) => true,
  625. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  626. ComputedValue = (element, assignedValue, settings) =>
  627. {
  628. string assignedValueStr = assignedValue.ToString();
  629. if (assignedValueStr == "thin")
  630. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0.75", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  631. if (assignedValueStr == "medium")
  632. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "3.0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  633. if (assignedValueStr == "thick")
  634. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "4.5", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  635. return ComputeAbsoluteLength(element, assignedValue, settings, null);
  636. },
  637. },
  638. // border-top-style, border-right-style, border-bottom-style, border-left-style
  639. // Value: <border-style> | inherit
  640. // Initial: none
  641. // Applies to: all elements
  642. // Inherited: no
  643. // Percentages: N/A
  644. // Computed value: as specified
  645. new PropertyInfo
  646. {
  647. Names = new[] { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", },
  648. Inherits = false,
  649. Includes = (e, settings) => true,
  650. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  651. ComputedValue = null,
  652. },
  653. // display
  654. // Value: inline | block | list-item | inline-block | table | inline-table |
  655. // table-row-group | table-header-group | table-footer-group |
  656. // table-row | table-column-group | table-column | table-cell |
  657. // table-caption | none | inherit
  658. // Initial: inline
  659. // Applies to: all elements
  660. // Inherited: no
  661. // Percentages: N/A
  662. // Computed value: see text
  663. new PropertyInfo
  664. {
  665. Names = new[] { "display", },
  666. Inherits = false,
  667. Includes = (e, settings) => true,
  668. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inline", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  669. ComputedValue = null,
  670. },
  671. // position
  672. // Value: static | relative | absolute | fixed | inherit
  673. // Initial: static
  674. // Applies to: all elements
  675. // Inherited: no
  676. // Percentages: N/A
  677. // Computed value: as specified
  678. new PropertyInfo
  679. {
  680. Names = new[] { "position", },
  681. Inherits = false,
  682. Includes = (e, settings) => true,
  683. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "static", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  684. ComputedValue = null,
  685. },
  686. // float
  687. // Value: left | right | none | inherit
  688. // Initial: none
  689. // Applies to: all, but see 9.7 p. 153
  690. // Inherited: no
  691. // Percentages: N/A
  692. // Computed value: as specified
  693. new PropertyInfo
  694. {
  695. Names = new[] { "float", },
  696. Inherits = false,
  697. Includes = (e, settings) => true,
  698. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  699. ComputedValue = null,
  700. },
  701. // unicode-bidi
  702. // Value: normal | embed | bidi-override | inherit
  703. // Initial: normal
  704. // Applies to: all elements, but see prose
  705. // Inherited: no
  706. // Percentages: N/A
  707. // Computed value: as spec
  708. new PropertyInfo
  709. {
  710. Names = new[] { "unicode-bidi", },
  711. Inherits = false,
  712. Includes = (e, settings) => true,
  713. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  714. ComputedValue = null,
  715. },
  716. // background-color
  717. // Value: <color> | transparent | inherit
  718. // Initial: transparent
  719. // Applies to: all elements
  720. // Inherited: no
  721. // Percentages: N/A
  722. // Computed value: as spec
  723. new PropertyInfo
  724. {
  725. Names = new[] { "background-color", },
  726. Inherits = false,
  727. Includes = (e, settings) => true,
  728. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "transparent", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  729. ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = GetWmlColorFromExpression(assignedValue), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  730. },
  731. // text-transform
  732. // Value: capitalize | uppercase | lowercase | none | inherit
  733. // Initial: none
  734. // Applies to: all elements
  735. // Inherited: yes
  736. // Percentages: N/A
  737. // Computed value: as spec
  738. new PropertyInfo
  739. {
  740. Names = new[] { "text-transform", },
  741. Inherits = true,
  742. Includes = (e, settings) => true,
  743. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  744. ComputedValue = null,
  745. },
  746. // table-layout
  747. // Value: auto | fixed | inherit
  748. // Initial: auto
  749. // Applies to: ’table’ and ’inline-table’ elements
  750. // Inherited: no
  751. // Percentages: N/A
  752. // Computed value: as spec
  753. new PropertyInfo
  754. {
  755. Names = new[] { "table-layout" },
  756. Inherits = true,
  757. Includes = (e, settings) =>
  758. {
  759. var display = GetComputedPropertyValue(null, e, "display", settings);
  760. if (display.ToString() == "table" || display.ToString() == "inline-table")
  761. return true;
  762. return false;
  763. },
  764. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  765. ComputedValue = null,
  766. },
  767. // empty-cells
  768. // Value: show | hide | inherit
  769. // Initial: show
  770. // Applies to: 'table-cell' elements
  771. // Inherited: yes
  772. // Percentages: N/A
  773. // Computed value: as spec
  774. new PropertyInfo
  775. {
  776. Names = new[] { "border-spacing" },
  777. Inherits = true,
  778. Includes = (e, settings) =>
  779. {
  780. var display = GetComputedPropertyValue(null, e, "display", settings);
  781. if (display.ToString() == "table-cell")
  782. return true;
  783. return false;
  784. },
  785. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "show", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  786. ComputedValue = null,
  787. },
  788. // border-top-color, border-right-color, border-bottom-color, border-left-color
  789. // Value: <color> | transparent | inherit
  790. // Initial: the value of the color property
  791. // Applies to: all elements
  792. // Inherited: no
  793. // Percentages: N/A
  794. // Computed value: when taken from the ’color’ property, the computed value of
  795. // ’color’; otherwise, as specified
  796. new PropertyInfo
  797. {
  798. Names = new[] { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", },
  799. Inherits = false,
  800. Includes = (e, settings) => true,
  801. InitialValue = (e, settings) => {
  802. var display = GetComputedPropertyValue(null, e, "color", settings);
  803. return display;
  804. },
  805. ComputedValue = (element, assignedValue, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = GetWmlColorFromExpression(assignedValue), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } },
  806. },
  807. // width
  808. // Value: <length> | <percentage> | auto | inherit
  809. // Initial: auto
  810. // Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  811. // Inherited: no
  812. // Percentages: refer to width of containing block
  813. // Computed value: the percentage or 'auto' as specified or the absolute length
  814. new PropertyInfo
  815. {
  816. Names = new[] { "width" },
  817. Inherits = false,
  818. Includes = (e, settings) =>
  819. {
  820. if (e.Name == XhtmlNoNamespace.img)
  821. return true;
  822. var display = GetComputedPropertyValue(null, e, "display", settings);
  823. var dv = display.ToString();
  824. if (dv == "inline" || dv == "table-row" || dv == "table-row-group")
  825. return false;
  826. return true;
  827. },
  828. InitialValue = (element, settings) =>
  829. {
  830. if (element.Parent == null)
  831. {
  832. double? pageWidth = (double?)settings.SectPr.Elements(W.pgSz).Attributes(W._w).FirstOrDefault();
  833. if (pageWidth == null)
  834. pageWidth = 12240;
  835. double? leftMargin = (double?)settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault();
  836. if (leftMargin == null)
  837. leftMargin = 1440;
  838. double? rightMargin = (double?)settings.SectPr.Elements(W.pgMar).Attributes(W.left).FirstOrDefault();
  839. if (rightMargin == null)
  840. rightMargin = 1440;
  841. double width = (double)(pageWidth - leftMargin - rightMargin) / 20;
  842. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = width.ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, Unit = CssUnit.PT, } } };
  843. }
  844. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } };
  845. },
  846. ComputedValue = (element, assignedValue, settings) =>
  847. {
  848. if (element.Name != XhtmlNoNamespace.caption &&
  849. element.Name != XhtmlNoNamespace.td &&
  850. element.Name != XhtmlNoNamespace.th &&
  851. element.Name != XhtmlNoNamespace.tr &&
  852. element.Name != XhtmlNoNamespace.table &&
  853. assignedValue.IsAuto)
  854. {
  855. PropertyInfo pi = PropertyInfoList.FirstOrDefault(p => p.Names.Contains("width"));
  856. string display = GetComputedPropertyValue(pi, element, "display", settings).ToString();
  857. if (display != "inline")
  858. {
  859. CssExpression parentPropertyValue = GetComputedPropertyValue(pi, element.Parent, "width", settings);
  860. return parentPropertyValue;
  861. }
  862. }
  863. CssExpression valueForPercentage = null;
  864. XElement elementToQuery = element.Parent;
  865. while (elementToQuery != null)
  866. {
  867. valueForPercentage = GetComputedPropertyValue(null, elementToQuery, "width", settings);
  868. if (valueForPercentage.IsAuto)
  869. {
  870. elementToQuery = elementToQuery.Parent;
  871. continue;
  872. }
  873. break;
  874. }
  875. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  876. },
  877. },
  878. // min-width
  879. // Value: <length> | <percentage> | inherit
  880. // Initial: 0
  881. // Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  882. // Inherited: no
  883. // Percentages: refer to width of containing block
  884. // Computed value: the percentage as spec or the absolute length
  885. new PropertyInfo
  886. {
  887. Names = new[] { "min-width" },
  888. Inherits = false,
  889. Includes = (e, settings) =>
  890. {
  891. var display = GetComputedPropertyValue(null, e, "display", settings);
  892. var dv = display.ToString();
  893. if (dv == "inline" || dv == "table-row" || dv == "table-row-group")
  894. return false;
  895. return true;
  896. },
  897. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  898. ComputedValue = (element, assignedValue, settings) =>
  899. {
  900. CssExpression valueForPercentage = null;
  901. if (element.Parent != null)
  902. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  903. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  904. },
  905. },
  906. // max-width
  907. // Value: <length> | <percentage> | none | inherit
  908. // Initial: none
  909. // Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  910. // Inherited: no
  911. // Percentages: refer to width of containing block
  912. // Computed value: the percentage as spec or the absolute length
  913. new PropertyInfo
  914. {
  915. Names = new[] { "max-width" },
  916. Inherits = false,
  917. Includes = (e, settings) =>
  918. {
  919. var display = GetComputedPropertyValue(null, e, "display", settings);
  920. var dv = display.ToString();
  921. if (dv == "inline" || dv == "table-row" || dv == "table-row-group")
  922. return false;
  923. return true;
  924. },
  925. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  926. ComputedValue = (element, assignedValue, settings) =>
  927. {
  928. CssExpression valueForPercentage = null;
  929. if (element.Parent != null)
  930. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "width", settings);
  931. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  932. },
  933. },
  934. // height
  935. // Value: <length> | <percentage> | auto | inherit
  936. // Initial: auto
  937. // Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  938. // Inherited: no
  939. // Percentages: see prose
  940. // Computed value: the percentage as spec or the absolute length
  941. new PropertyInfo
  942. {
  943. Names = new[] { "height" },
  944. Inherits = false,
  945. Includes = (e, settings) =>
  946. {
  947. if (e.Name == XhtmlNoNamespace.img)
  948. return true;
  949. var display = GetComputedPropertyValue(null, e, "display", settings);
  950. var dv = display.ToString();
  951. if (dv == "inline" || dv == "table-row" || dv == "table-row-group")
  952. return false;
  953. return true;
  954. },
  955. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  956. ComputedValue = (element, assignedValue, settings) =>
  957. {
  958. CssExpression valueForPercentage = null;
  959. if (element.Parent != null)
  960. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings);
  961. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  962. },
  963. },
  964. // min-height
  965. // Value: <length> | <percentage> | inherit
  966. // Initial: 0
  967. // Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  968. // Inherited: no
  969. // Percentages: see prose
  970. // Computed value: the percentage as spec or the absolute length
  971. new PropertyInfo
  972. {
  973. Names = new[] { "min-height" },
  974. Inherits = false,
  975. Includes = (e, settings) =>
  976. {
  977. var display = GetComputedPropertyValue(null, e, "display", settings);
  978. var dv = display.ToString();
  979. if (dv == "inline" || dv == "table-column" || dv == "table-column-group")
  980. return false;
  981. return true;
  982. },
  983. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "0", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } },
  984. ComputedValue = (element, assignedValue, settings) =>
  985. {
  986. CssExpression valueForPercentage = null;
  987. if (element.Parent != null)
  988. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings);
  989. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  990. },
  991. },
  992. // max-height
  993. // Value: <length> | <percentage> | none | inherit
  994. // Initial: none
  995. // Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  996. // Inherited: no
  997. // Percentages: refer to height of containing block
  998. // Computed value: the percentage as spec or the absolute length
  999. new PropertyInfo
  1000. {
  1001. Names = new[] { "max-height" },
  1002. Inherits = false,
  1003. Includes = (e, settings) =>
  1004. {
  1005. var display = GetComputedPropertyValue(null, e, "display", settings);
  1006. var dv = display.ToString();
  1007. if (dv == "inline" || dv == "table-column" || dv == "table-column-group")
  1008. return false;
  1009. return true;
  1010. },
  1011. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  1012. ComputedValue = (element, assignedValue, settings) =>
  1013. {
  1014. CssExpression valueForPercentage = null;
  1015. if (element.Parent != null)
  1016. valueForPercentage = GetComputedPropertyValue(null, element.Parent, "height", settings);
  1017. return ComputeAbsoluteLength(element, assignedValue, settings, valueForPercentage);
  1018. },
  1019. },
  1020. // vertical-align
  1021. // Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom |
  1022. // <percentage> | <length> | inherit
  1023. // Initial: baseline
  1024. // Applies to: inline-level and 'table-cell' elements
  1025. // Inherited: no
  1026. // Percentages: refer to the line height of the element itself
  1027. // Computed value: for <length> and <percentage> the absolute length, otherwise as specified.
  1028. new PropertyInfo
  1029. {
  1030. Names = new[] { "vertical-align" },
  1031. Inherits = false,
  1032. Includes = (e, settings) =>
  1033. {
  1034. var display = GetComputedPropertyValue(null, e, "display", settings);
  1035. var dv = display.ToString();
  1036. if (dv == "inline" || dv == "table-cell")
  1037. return true;
  1038. return false;
  1039. },
  1040. InitialValue = (element, settings) => new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "baseline", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String, } } },
  1041. ComputedValue = (element, assignedValue, settings) => assignedValue, // todo fix
  1042. },
  1043. // positioned elements are not supported
  1044. //
  1045. // top
  1046. // Value: <length> | <percentage> | auto | inherit
  1047. // Initial: auto
  1048. // Applies to: positioned elements
  1049. // Inherited: no
  1050. // Percentages: refer to height of containing block
  1051. // Computed value: if specified as a length, the corresponding absolute length; if
  1052. // specified as a percentage, the specified value; otherwise, ’auto’.
  1053. //
  1054. // right
  1055. // Value: <length> | <percentage> | auto | inherit
  1056. // Initial: auto
  1057. // Applies to: positioned elements
  1058. // Inherited: no
  1059. // Percentages: refer to width of containing block
  1060. // Computed value: if specified as a length, the corresponding absolute length; if
  1061. // specified as a percentage, the specified value; otherwise, ’auto’.
  1062. //
  1063. // bottom
  1064. // Value: <length> | <percentage> | auto | inherit
  1065. // Initial: auto
  1066. // Applies to: positioned elements
  1067. // Inherited: no
  1068. // Percentages: refer to height of containing block
  1069. // Computed value: if specified as a length, the corresponding absolute length; if
  1070. // specified as a percentage, the specified value; otherwise, ’auto’.
  1071. //
  1072. // left
  1073. // Value: <length> | <percentage> | auto | inherit
  1074. // Initial: auto
  1075. // Applies to: positioned elements
  1076. // Inherited: no
  1077. // Percentages: refer to width of containing block
  1078. // Computed value: if specified as a length, the corresponding absolute length; if
  1079. // specified as a percentage, the specified value; otherwise, ’auto’.
  1080. // floated elements are not supported
  1081. //
  1082. // clear
  1083. // Value: none | left | right | both | inherit
  1084. // Initial: none
  1085. // Applies to: block-level elements
  1086. // Inherited: no
  1087. // Percentages: N/A
  1088. // Computed value: as specified
  1089. //
  1090. // z-index
  1091. // Value: auto | integer | inherit
  1092. // Initial: auto
  1093. // Applies to: positioned elements
  1094. // Inherited: no
  1095. // Percentages: N/A
  1096. // Computed value: as spec
  1097. };
  1098. /*
  1099. * 1. Process user-agent default style sheet
  1100. * 2. Process user-supplied style sheet
  1101. * 3. process author-supplied style sheet
  1102. * 4. process STYLE element
  1103. * 5. process style attribute on all elements
  1104. * 6. expand all shorthand properties - the new properties have the same sort key as shorthand prop
  1105. * 7. Add initial values for all properties that don't have values
  1106. */
  1107. public static void ApplyAllCss(
  1108. string defaultCss,
  1109. string authorCss,
  1110. string userCss,
  1111. XElement newXHtml,
  1112. HtmlToWmlConverterSettings settings,
  1113. out CssDocument defaultCssDoc,
  1114. out CssDocument authorCssDoc,
  1115. out CssDocument userCssDoc,
  1116. string annotatedHtmlDumpFileName)
  1117. {
  1118. int propertySequence = 1;
  1119. CssParser defaultCssParser = new CssParser();
  1120. defaultCssDoc = defaultCssParser.ParseText(defaultCss);
  1121. ApplyCssDocument(
  1122. defaultCssDoc,
  1123. newXHtml,
  1124. Property.HighOrderPriority.UserAgentNormal,
  1125. Property.HighOrderPriority.UserAgentHigh,
  1126. ref propertySequence);
  1127. //// todo dump here, see if margin is set on body.
  1128. //if (annotatedHtmlDumpFileName != null)
  1129. //{
  1130. // StringBuilder sb = new StringBuilder();
  1131. // WriteXHtmlWithAnnotations(newXHtml, sb);
  1132. // File.WriteAllText(annotatedHtmlDumpFileName, sb.ToString());
  1133. // Environment.Exit(0);
  1134. //}
  1135. //DumpCss(userAgentCssDoc);
  1136. //Environment.Exit(0);
  1137. CssParser userCssParser = new CssParser();
  1138. userCssDoc = userCssParser.ParseText(userCss);
  1139. ApplyCssDocument(
  1140. userCssDoc,
  1141. newXHtml,
  1142. Property.HighOrderPriority.UserHigh,
  1143. Property.HighOrderPriority.UserNormal,
  1144. ref propertySequence);
  1145. //DumpCss(userCssDoc);
  1146. //Environment.Exit(0);
  1147. CssParser authorCssParser = new CssParser();
  1148. authorCssDoc = authorCssParser.ParseText(authorCss);
  1149. ApplyCssDocument(
  1150. authorCssDoc,
  1151. newXHtml,
  1152. Property.HighOrderPriority.AuthorNormal,
  1153. Property.HighOrderPriority.AuthorHigh,
  1154. ref propertySequence);
  1155. //string s = DumpCss(authorCssDoc);
  1156. //File.WriteAllText("CssTreeDump.txt", s);
  1157. //Environment.Exit(0);
  1158. // If processing style element, do it here.
  1159. ApplyStyleAttributes(newXHtml, ref propertySequence);
  1160. ExpandShorthandProperties(newXHtml, settings);
  1161. SetAllValues(newXHtml, settings);
  1162. if (annotatedHtmlDumpFileName != null)
  1163. {
  1164. StringBuilder sb = new StringBuilder();
  1165. WriteXHtmlWithAnnotations(newXHtml, sb);
  1166. File.WriteAllText(annotatedHtmlDumpFileName, sb.ToString());
  1167. }
  1168. }
  1169. private static void SetAllValues(XElement xHtml, HtmlToWmlConverterSettings settings)
  1170. {
  1171. foreach (var element in xHtml.DescendantsAndSelf())
  1172. {
  1173. foreach (var propertyInfo in PropertyInfoList)
  1174. {
  1175. if (propertyInfo.Includes(element, settings))
  1176. {
  1177. foreach (var name in propertyInfo.Names)
  1178. {
  1179. GetComputedPropertyValue(propertyInfo, element, name, settings);
  1180. }
  1181. }
  1182. }
  1183. }
  1184. }
  1185. #if false
  1186. GetComputedPropertyValue
  1187. if (property is already computed)
  1188. return the computed value
  1189. if (property is set)
  1190. compute value
  1191. set the computed value
  1192. return the computed value
  1193. if (property is inherited (either because it was set to inherit, or because it is an inherited property))
  1194. if (parent exists)
  1195. call GetComputedValue on parent
  1196. return the computed value
  1197. else
  1198. call GetInitialValue for property
  1199. compute value
  1200. set the computed value
  1201. return the computed value
  1202. #endif
  1203. public static CssExpression GetComputedPropertyValue(PropertyInfo propertyInfo, XElement element, string propertyName,
  1204. HtmlToWmlConverterSettings settings)
  1205. {
  1206. // if (property is already computed)
  1207. // return the computed value
  1208. Dictionary<string, CssExpression> computedValues = element.Annotation<Dictionary<string, CssExpression>>();
  1209. if (computedValues == null)
  1210. {
  1211. computedValues = new Dictionary<string, CssExpression>();
  1212. element.AddAnnotation(computedValues);
  1213. }
  1214. if (computedValues.ContainsKey(propertyName))
  1215. {
  1216. CssExpression r = computedValues[propertyName];
  1217. return r;
  1218. }
  1219. // if property is not set or property is set to inherited value, then get inherited or initialized value.
  1220. string pName = propertyName.ToLower();
  1221. if (propertyInfo == null)
  1222. {
  1223. propertyInfo = PropertyInfoList.FirstOrDefault(pi => pi.Names.Contains(pName));
  1224. if (propertyInfo == null)
  1225. throw new OpenXmlPowerToolsException("all possible properties should be in the list");
  1226. }
  1227. Dictionary<string, Property> propList = element.Annotation<Dictionary<string, Property>>();
  1228. if (propList == null)
  1229. {
  1230. CssExpression computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, false, settings);
  1231. return computedValue;
  1232. }
  1233. if (!propList.ContainsKey(pName))
  1234. {
  1235. CssExpression computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, false, settings);
  1236. return computedValue;
  1237. }
  1238. Property prop = propList[pName];
  1239. string propStr = prop.Expression.ToString();
  1240. if (propStr == "inherited" || propStr == "auto")
  1241. {
  1242. CssExpression computedValue = GetInheritedOrInitializedValue(computedValues, propertyInfo, element, propertyName, true, settings);
  1243. return computedValue;
  1244. }
  1245. // if property is set, then compute the value, return the computed value
  1246. CssExpression computedValue2;
  1247. if (propertyInfo.ComputedValue == null)
  1248. computedValue2 = prop.Expression;
  1249. else
  1250. {
  1251. computedValue2 = propertyInfo.ComputedValue(element, prop.Expression, settings);
  1252. }
  1253. computedValues.Add(propertyName, computedValue2);
  1254. return computedValue2;
  1255. }
  1256. //if (property is inherited (either because it was set to inherit, or because it is an inherited property))
  1257. // if (parent exists)
  1258. // call GetComputedValue on parent
  1259. // return the computed value
  1260. //else
  1261. // call GetInitialValue for property
  1262. // compute value
  1263. // set the computed value
  1264. // return the computed value
  1265. public static CssExpression GetInheritedOrInitializedValue(Dictionary<string, CssExpression> computedValues, PropertyInfo propertyInfo, XElement element, string propertyName, bool valueIsInherit, HtmlToWmlConverterSettings settings)
  1266. {
  1267. if ((propertyInfo.Inherits || valueIsInherit) && element.Parent != null && propertyInfo.Includes(element.Parent, settings))
  1268. {
  1269. CssExpression parentPropertyValue = GetComputedPropertyValue(propertyInfo, element.Parent, propertyName, settings);
  1270. computedValues.Add(propertyName, parentPropertyValue);
  1271. return parentPropertyValue;
  1272. }
  1273. CssExpression initialPropertyValue = propertyInfo.InitialValue(element, settings);
  1274. CssExpression computedValue;
  1275. if (propertyInfo.ComputedValue == null)
  1276. computedValue = initialPropertyValue;
  1277. else
  1278. computedValue = propertyInfo.ComputedValue(element, initialPropertyValue, settings);
  1279. computedValues.Add(propertyName, computedValue);
  1280. return computedValue;
  1281. }
  1282. private static void ApplyCssDocument(
  1283. CssDocument cssDoc,
  1284. XElement xHtml,
  1285. Property.HighOrderPriority notImportantHighOrderSort,
  1286. Property.HighOrderPriority importantHighOrderSort,
  1287. ref int propertySequence)
  1288. {
  1289. foreach (var ruleSet in cssDoc.RuleSets)
  1290. {
  1291. foreach (var selector in ruleSet.Selectors)
  1292. {
  1293. ApplySelector(selector, ruleSet, xHtml, notImportantHighOrderSort,
  1294. importantHighOrderSort, ref propertySequence);
  1295. }
  1296. }
  1297. }
  1298. private static CssExpression ComputeAbsoluteLength(XElement element, CssExpression assignedValue, HtmlToWmlConverterSettings settings,
  1299. CssExpression lengthForPercentage)
  1300. {
  1301. if (assignedValue.Terms.Count != 1)
  1302. throw new OpenXmlPowerToolsException("Should not have a unit with more than one term");
  1303. string value = assignedValue.Terms.First().Value;
  1304. bool negative = assignedValue.Terms.First().Sign == '-';
  1305. if (value == "thin")
  1306. {
  1307. CssExpression newExpr1 = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = ".3", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1308. return newExpr1;
  1309. }
  1310. if (value == "medium")
  1311. {
  1312. CssExpression newExpr2 = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "1.20", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1313. return newExpr2;
  1314. }
  1315. if (value == "thick")
  1316. {
  1317. CssExpression newExpr3 = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "1.80", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1318. return newExpr3;
  1319. }
  1320. if (value == "auto" || value == "normal" || value == "none")
  1321. return assignedValue;
  1322. CssUnit? unit = assignedValue.Terms.First().Unit;
  1323. if (unit == CssUnit.PT || unit == null)
  1324. return assignedValue;
  1325. if (unit == CssUnit.Percent && lengthForPercentage == null)
  1326. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "auto", Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.String } } };
  1327. double decValue;
  1328. if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out decValue))
  1329. throw new OpenXmlPowerToolsException("value did not parse");
  1330. if (negative)
  1331. decValue = -decValue;
  1332. double? newPtSize = null;
  1333. if (unit == CssUnit.Percent)
  1334. {
  1335. double ptSize;
  1336. if (!double.TryParse(lengthForPercentage.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out ptSize))
  1337. throw new OpenXmlPowerToolsException("did not return a double?");
  1338. newPtSize = ptSize * decValue / 100d;
  1339. }
  1340. else if (unit == CssUnit.EM || unit == CssUnit.EX)
  1341. {
  1342. CssExpression fontSize = GetComputedPropertyValue(null, element, "font-size", settings);
  1343. double decFontSize;
  1344. if (!double.TryParse(fontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out decFontSize))
  1345. throw new OpenXmlPowerToolsException("Internal error");
  1346. newPtSize = (unit == CssUnit.EM) ? decFontSize * decValue : decFontSize * decValue / 2;
  1347. }
  1348. else
  1349. {
  1350. if (unit == null && decValue == 0d)
  1351. newPtSize = 0d;
  1352. if (unit == CssUnit.IN)
  1353. newPtSize = decValue * 72.0d;
  1354. if (unit == CssUnit.CM)
  1355. newPtSize = (decValue / 2.54d) * 72.0d;
  1356. if (unit == CssUnit.MM)
  1357. newPtSize = (decValue / 25.4d) * 72.0d;
  1358. if (unit == CssUnit.PC)
  1359. newPtSize = decValue * 12d;
  1360. if (unit == CssUnit.PX)
  1361. newPtSize = decValue * 0.75d;
  1362. }
  1363. if (!newPtSize.HasValue)
  1364. throw new OpenXmlPowerToolsException("Internal error: should not have reached this exception");
  1365. CssExpression newExpr = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1366. return newExpr;
  1367. }
  1368. private static CssExpression ComputeAbsoluteFontSize(XElement element, CssExpression assignedValue, HtmlToWmlConverterSettings settings)
  1369. {
  1370. if (assignedValue.Terms.Count != 1)
  1371. throw new OpenXmlPowerToolsException("Should not have a unit with more than one term, I think");
  1372. string value = assignedValue.Terms.First().Value;
  1373. CssUnit? unit = assignedValue.Terms.First().Unit;
  1374. if (unit == CssUnit.PT)
  1375. return assignedValue;
  1376. if (FontSizeMap.ContainsKey(value))
  1377. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = FontSizeMap[value].ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1378. // todo what should the calculation be for computing larger / smaller?
  1379. if (value == "larger" || value == "smaller")
  1380. {
  1381. CssExpression parentFontSize = GetComputedPropertyValue(null, element.Parent, "font-size", settings);
  1382. double ptSize;
  1383. if (!double.TryParse(parentFontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out ptSize))
  1384. throw new OpenXmlPowerToolsException("did not return a double?");
  1385. double newPtSize2 = 0;
  1386. if (value == "larger")
  1387. {
  1388. if (ptSize < 10)
  1389. newPtSize2 = 10d;
  1390. if (ptSize == 10 || ptSize == 11)
  1391. newPtSize2 = 12d;
  1392. if (ptSize == 12)
  1393. newPtSize2 = 13.5d;
  1394. if (ptSize >= 13 && ptSize <= 15)
  1395. newPtSize2 = 18d;
  1396. if (ptSize >= 16 && ptSize <= 20)
  1397. newPtSize2 = 24d;
  1398. if (ptSize >= 21)
  1399. newPtSize2 = 36d;
  1400. }
  1401. if (value == "smaller")
  1402. {
  1403. if (ptSize <= 11)
  1404. newPtSize2 = 7.5d;
  1405. if (ptSize == 12)
  1406. newPtSize2 = 10d;
  1407. if (ptSize >= 13 && ptSize <= 15)
  1408. newPtSize2 = 12d;
  1409. if (ptSize >= 16 && ptSize <= 20)
  1410. newPtSize2 = 13.5d;
  1411. if (ptSize >= 21 && ptSize <= 29)
  1412. newPtSize2 = 18d;
  1413. if (ptSize >= 30)
  1414. newPtSize2 = 24d;
  1415. }
  1416. return new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = newPtSize2.ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1417. }
  1418. double decValue;
  1419. if (!double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out decValue))
  1420. throw new OpenXmlPowerToolsException("em value did not parse");
  1421. double? newPtSize = null;
  1422. if (unit == CssUnit.EM || unit == CssUnit.EX || unit == CssUnit.Percent)
  1423. {
  1424. CssExpression parentFontSize = GetComputedPropertyValue(null, element.Parent, "font-size", settings);
  1425. double ptSize;
  1426. if (!double.TryParse(parentFontSize.Terms.First().Value, NumberStyles.Float, CultureInfo.InvariantCulture, out ptSize))
  1427. throw new OpenXmlPowerToolsException("did not return a double?");
  1428. if (unit == CssUnit.EM)
  1429. newPtSize = ptSize * decValue;
  1430. if (unit == CssUnit.EX)
  1431. newPtSize = ptSize / 2 * decValue;
  1432. if (unit == CssUnit.Percent)
  1433. newPtSize = ptSize * decValue / 100d;
  1434. }
  1435. else
  1436. {
  1437. if (unit == CssUnit.IN)
  1438. newPtSize = decValue * 72.0d;
  1439. if (unit == CssUnit.CM)
  1440. newPtSize = (decValue / 2.54d) * 72.0d;
  1441. if (unit == CssUnit.MM)
  1442. newPtSize = (decValue / 25.4d) * 72.0d;
  1443. if (unit == CssUnit.PC)
  1444. newPtSize = decValue * 12d;
  1445. if (unit == CssUnit.PX)
  1446. newPtSize = decValue * 0.75d;
  1447. }
  1448. if (!newPtSize.HasValue)
  1449. throw new OpenXmlPowerToolsException("Internal error: should not have reached this exception");
  1450. CssExpression newExpr = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = newPtSize.Value.ToString(CultureInfo.InvariantCulture), Type = OpenXmlPowerTools.HtmlToWml.CSS.CssTermType.Number, Unit = CssUnit.PT, } } };
  1451. return newExpr;
  1452. }
  1453. private static Dictionary<string, double> FontSizeMap = new Dictionary<string, double>()
  1454. {
  1455. { "xx-small", 7.5d },
  1456. { "x-small", 10d },
  1457. { "small", 12d },
  1458. { "medium", 13.5d },
  1459. { "large", 18d },
  1460. { "x-large", 24d },
  1461. { "xx-large", 36d },
  1462. };
  1463. private static void ApplySelector(
  1464. CssSelector selector,
  1465. CssRuleSet ruleSet,
  1466. XElement xHtml,
  1467. Property.HighOrderPriority notImportantHighOrderSort,
  1468. Property.HighOrderPriority importantHighOrderSort,
  1469. ref int propertySequence)
  1470. {
  1471. foreach (var element in xHtml.DescendantsAndSelf())
  1472. {
  1473. if (DoesSelectorMatch(selector, element))
  1474. {
  1475. foreach (CssDeclaration declaration in ruleSet.Declarations)
  1476. {
  1477. Property prop = new Property()
  1478. {
  1479. Name = declaration.Name.ToLower(),
  1480. Expression = declaration.Expression,
  1481. HighOrderSort = declaration.Important ? importantHighOrderSort : notImportantHighOrderSort,
  1482. IdAttributesInSelector = CountIdAttributesInSelector(selector),
  1483. AttributesInSelector = CountAttributesInSelector(selector),
  1484. ElementNamesInSelector = CountElementNamesInSelector(selector),
  1485. SequenceNumber = propertySequence++,
  1486. };
  1487. AddPropertyToElement(element, prop);
  1488. }
  1489. }
  1490. }
  1491. }
  1492. private static bool DoesSelectorMatch(
  1493. CssSelector selector,
  1494. XElement element)
  1495. {
  1496. int currentSimpleSelector = selector.SimpleSelectors.Count() - 1;
  1497. XElement currentElement = element;
  1498. while (true)
  1499. {
  1500. if (!DoesSimpleSelectorMatch(selector.SimpleSelectors[currentSimpleSelector], currentElement))
  1501. return false;
  1502. if (currentSimpleSelector == 0)
  1503. return true;
  1504. if (selector.SimpleSelectors[currentSimpleSelector].Combinator == CssCombinator.ChildOf)
  1505. {
  1506. currentElement = currentElement.Parent;
  1507. if (currentElement == null)
  1508. return false;
  1509. currentSimpleSelector--;
  1510. continue;
  1511. }
  1512. if (selector.SimpleSelectors[currentSimpleSelector].Combinator == CssCombinator.PrecededImmediatelyBy)
  1513. {
  1514. currentElement = currentElement.ElementsBeforeSelf().Reverse().FirstOrDefault();
  1515. if (currentElement == null)
  1516. return false;
  1517. currentSimpleSelector--;
  1518. continue;
  1519. }
  1520. if (selector.SimpleSelectors[currentSimpleSelector].Combinator == null)
  1521. {
  1522. bool continueOuter = false;
  1523. foreach (XElement ancestor in element.Ancestors())
  1524. {
  1525. if (DoesSimpleSelectorMatch(selector.SimpleSelectors[currentSimpleSelector - 1], ancestor))
  1526. {
  1527. currentElement = ancestor;
  1528. currentSimpleSelector--;
  1529. continueOuter = true;
  1530. break;
  1531. }
  1532. }
  1533. if (continueOuter)
  1534. continue;
  1535. return false;
  1536. }
  1537. }
  1538. }
  1539. private static bool DoesSimpleSelectorMatch(
  1540. CssSimpleSelector simpleSelector,
  1541. XElement element)
  1542. {
  1543. bool elemantNameMatch = true;
  1544. bool classNameMatch = true;
  1545. bool childSimpleSelectorMatch = true;
  1546. bool idMatch = true;
  1547. bool attributeMatch = true;
  1548. if (simpleSelector.Pseudo != null)
  1549. return false;
  1550. if (simpleSelector.ElementName != null && simpleSelector.ElementName != "" && simpleSelector.ElementName != "*")
  1551. elemantNameMatch = element.Name.ToString() == simpleSelector.ElementName.ToString();
  1552. if (elemantNameMatch)
  1553. {
  1554. if (simpleSelector.Class != null && simpleSelector.Class != "")
  1555. classNameMatch = ClassesOf(element).Contains(simpleSelector.Class);
  1556. if (classNameMatch)
  1557. {
  1558. if (simpleSelector.Child != null)
  1559. childSimpleSelectorMatch = DoesSimpleSelectorMatch(simpleSelector.Child, element);
  1560. if (childSimpleSelectorMatch)
  1561. {
  1562. if (simpleSelector.ID != null && simpleSelector.ID != "")
  1563. {
  1564. string id = (string)element.Attribute("ID");
  1565. if (id == null)
  1566. id = (string)element.Attribute("id");
  1567. idMatch = simpleSelector.ID == id;
  1568. }
  1569. if (idMatch)
  1570. {
  1571. if (simpleSelector.Attribute != null)
  1572. attributeMatch = DoesAttributeMatch(simpleSelector.Attribute, element);
  1573. }
  1574. }
  1575. }
  1576. }
  1577. bool result =
  1578. elemantNameMatch &&
  1579. classNameMatch &&
  1580. childSimpleSelectorMatch &&
  1581. idMatch &&
  1582. attributeMatch;
  1583. return result;
  1584. }
  1585. private static bool DoesAttributeMatch(OpenXmlPowerTools.HtmlToWml.CSS.CssAttribute attribute, XElement element)
  1586. {
  1587. string attName = attribute.Operand.ToLower();
  1588. string attValue = (string)element.Attribute(attName);
  1589. if (attValue == null)
  1590. return false;
  1591. if (attribute.Operator == null)
  1592. return true;
  1593. string value = attribute.Value;
  1594. switch (attribute.Operator)
  1595. {
  1596. case CssAttributeOperator.Equals:
  1597. return attValue == value;
  1598. case CssAttributeOperator.BeginsWith:
  1599. return attValue.StartsWith(value);
  1600. case CssAttributeOperator.Contains:
  1601. return attValue.Contains(value);
  1602. case CssAttributeOperator.EndsWith:
  1603. return attValue.EndsWith(value);
  1604. case CssAttributeOperator.InList:
  1605. return attValue.Split(' ').Contains(value);
  1606. case CssAttributeOperator.Hyphenated:
  1607. return attValue.Split('-')[0] == value;
  1608. default:
  1609. return false;
  1610. }
  1611. }
  1612. private static int CountIdAttributesInSimpleSelector(CssSimpleSelector simpleSelector)
  1613. {
  1614. int count = simpleSelector.ID != null ? 1 : 0 +
  1615. (simpleSelector.Child != null ? CountIdAttributesInSimpleSelector(simpleSelector.Child) : 0);
  1616. return count;
  1617. }
  1618. private static int CountIdAttributesInSelector(CssSelector selector)
  1619. {
  1620. int count = selector.SimpleSelectors.Select(ss => CountIdAttributesInSimpleSelector(ss)).Sum();
  1621. return count;
  1622. }
  1623. private static int CountAttributesInSimpleSelector(CssSimpleSelector simpleSelector)
  1624. {
  1625. int count = (simpleSelector.Attribute != null ? 1 : 0) +
  1626. ((simpleSelector.Class != null && simpleSelector.Class != "") ? 1 : 0) +
  1627. (simpleSelector.Child != null ? CountAttributesInSimpleSelector(simpleSelector.Child) : 0);
  1628. return count;
  1629. }
  1630. private static int CountAttributesInSelector(CssSelector selector)
  1631. {
  1632. int count = selector.SimpleSelectors.Select(ss => CountAttributesInSimpleSelector(ss)).Sum();
  1633. return count;
  1634. }
  1635. private static int CountElementNamesInSimpleSelector(CssSimpleSelector simpleSelector)
  1636. {
  1637. int count = (simpleSelector.ElementName != null &&
  1638. simpleSelector.ElementName != "" &&
  1639. simpleSelector.ElementName != "*")
  1640. ? 1 : 0 +
  1641. (simpleSelector.Child != null ? CountElementNamesInSimpleSelector(simpleSelector.Child) : 0);
  1642. return count;
  1643. }
  1644. private static int CountElementNamesInSelector(CssSelector selector)
  1645. {
  1646. int count = selector.SimpleSelectors.Select(ss => CountElementNamesInSimpleSelector(ss)).Sum();
  1647. return count;
  1648. }
  1649. private static void AddPropertyToElement(
  1650. XElement element,
  1651. Property property)
  1652. {
  1653. //if (property.Name == "direction")
  1654. // Console.WriteLine(1);
  1655. Dictionary<string, Property> propList = element.Annotation<Dictionary<string, Property>>();
  1656. if (propList == null)
  1657. {
  1658. propList = new Dictionary<string, Property>();
  1659. element.AddAnnotation(propList);
  1660. }
  1661. if (!propList.ContainsKey(property.Name))
  1662. propList.Add(property.Name, property);
  1663. else
  1664. {
  1665. Property current = propList[property.Name];
  1666. if (((System.IComparable<Property>)property).CompareTo(current) == 1)
  1667. propList[property.Name] = property;
  1668. }
  1669. }
  1670. private static void AddPropertyToDictionary(
  1671. Dictionary<string, Property> propList,
  1672. Property property)
  1673. {
  1674. if (!propList.ContainsKey(property.Name))
  1675. propList.Add(property.Name, property);
  1676. else
  1677. {
  1678. Property current = propList[property.Name];
  1679. if (((System.IComparable<Property>)property).CompareTo(current) == 1)
  1680. propList[property.Name] = property;
  1681. }
  1682. }
  1683. private static string[] ClassesOf(XElement element)
  1684. {
  1685. string classesString = (string)element.Attribute("class");
  1686. if (classesString == null)
  1687. return new string[0];
  1688. return classesString.Split(' ');
  1689. }
  1690. private static void ApplyDeclarationsToElement(
  1691. CssRuleSet ruleSet,
  1692. XElement element,
  1693. Property.HighOrderPriority notImportantHighOrderSort,
  1694. Property.HighOrderPriority importantHighOrderSort,
  1695. ref int propertySequence)
  1696. {
  1697. foreach (var declaration in ruleSet.Declarations)
  1698. {
  1699. Property prop = new Property()
  1700. {
  1701. Name = declaration.Name.ToLower(),
  1702. Expression = declaration.Expression,
  1703. HighOrderSort = declaration.Important ? importantHighOrderSort : notImportantHighOrderSort,
  1704. IdAttributesInSelector = 0,
  1705. AttributesInSelector = 0,
  1706. ElementNamesInSelector = 0,
  1707. SequenceNumber = propertySequence++,
  1708. };
  1709. AddPropertyToElement(element, prop);
  1710. }
  1711. }
  1712. private static void ApplyCssToElement(
  1713. CssDocument cssDoc,
  1714. XElement element,
  1715. Property.HighOrderPriority notImportantHighOrderSort,
  1716. Property.HighOrderPriority importantHighOrderSort,
  1717. ref int propertySequence)
  1718. {
  1719. foreach (var ruleSet in cssDoc.RuleSets)
  1720. {
  1721. ApplyDeclarationsToElement(ruleSet, element, notImportantHighOrderSort, importantHighOrderSort, ref propertySequence);
  1722. }
  1723. }
  1724. private static void ApplyStyleAttributes(XElement xHtml, ref int propertySequence)
  1725. {
  1726. foreach (var element in xHtml.DescendantsAndSelf())
  1727. {
  1728. XAttribute styleAtt = element.Attribute(XhtmlNoNamespace.style);
  1729. if (styleAtt != null)
  1730. {
  1731. string style = (string)styleAtt;
  1732. string cssString = element.Name + "{" + style + "}";
  1733. cssString = cssString.Replace('\"', '\'');
  1734. CssParser cssParser = new CssParser();
  1735. CssDocument cssDoc = cssParser.ParseText(cssString);
  1736. ApplyCssToElement(
  1737. cssDoc,
  1738. element,
  1739. Property.HighOrderPriority.StyleAttributeNormal,
  1740. Property.HighOrderPriority.StyleAttributeHigh,
  1741. ref propertySequence);
  1742. }
  1743. XAttribute dirAtt = element.Attribute(XhtmlNoNamespace.dir);
  1744. if (dirAtt != null)
  1745. {
  1746. string dir = dirAtt.Value.ToLower();
  1747. Property prop = new Property()
  1748. {
  1749. Name = "direction",
  1750. Expression = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = dir, Type = CssTermType.String } } },
  1751. HighOrderSort = Property.HighOrderPriority.HtmlAttribute,
  1752. IdAttributesInSelector = 0,
  1753. AttributesInSelector = 0,
  1754. ElementNamesInSelector = 0,
  1755. SequenceNumber = propertySequence++,
  1756. };
  1757. AddPropertyToElement(element, prop);
  1758. }
  1759. }
  1760. }
  1761. private enum CssDataType
  1762. {
  1763. BorderWidth,
  1764. BorderStyle,
  1765. Color,
  1766. ListStyleType,
  1767. ListStylePosition,
  1768. ListStyleImage,
  1769. BackgroundColor,
  1770. BackgroundImage,
  1771. BackgroundRepeat,
  1772. BackgroundAttachment,
  1773. BackgroundPosition,
  1774. FontStyle,
  1775. FontVarient,
  1776. FontWeight,
  1777. FontSize,
  1778. LineHeight,
  1779. FontFamily,
  1780. Length,
  1781. };
  1782. private class ShorthandPropertiesInfo
  1783. {
  1784. public string Name;
  1785. public string Pattern;
  1786. }
  1787. private static ShorthandPropertiesInfo[] ShorthandProperties = new[]
  1788. {
  1789. new ShorthandPropertiesInfo
  1790. {
  1791. Name = "margin",
  1792. Pattern = "margin-{0}",
  1793. },
  1794. new ShorthandPropertiesInfo
  1795. {
  1796. Name = "padding",
  1797. Pattern = "padding-{0}",
  1798. },
  1799. new ShorthandPropertiesInfo
  1800. {
  1801. Name = "border-width",
  1802. Pattern = "border-{0}-width",
  1803. },
  1804. new ShorthandPropertiesInfo
  1805. {
  1806. Name = "border-color",
  1807. Pattern = "border-{0}-color",
  1808. },
  1809. new ShorthandPropertiesInfo
  1810. {
  1811. Name = "border-style",
  1812. Pattern = "border-{0}-style",
  1813. },
  1814. };
  1815. private static void ExpandShorthandProperties(XElement xHtml, HtmlToWmlConverterSettings settings)
  1816. {
  1817. foreach (var element in xHtml.DescendantsAndSelf())
  1818. {
  1819. ExpandShorthandPropertiesForElement(element, settings);
  1820. }
  1821. }
  1822. private static void ExpandShorthandPropertiesForElement(XElement element, HtmlToWmlConverterSettings settings)
  1823. {
  1824. Dictionary<string, Property> propertyList = element.Annotation<Dictionary<string, Property>>();
  1825. if (propertyList == null)
  1826. {
  1827. propertyList = new Dictionary<string, Property>();
  1828. element.AddAnnotation(propertyList);
  1829. }
  1830. foreach (var kvp in propertyList.ToList())
  1831. {
  1832. Property p = kvp.Value;
  1833. if (p.Name == "border")
  1834. {
  1835. CssExpression borderColor;
  1836. CssExpression borderWidth;
  1837. CssExpression borderStyle;
  1838. if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit")
  1839. {
  1840. borderColor = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1841. borderWidth = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1842. borderStyle = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1843. }
  1844. else
  1845. {
  1846. //borderColor = GetComputedPropertyValue(null, element, "color", settings);
  1847. //borderWidth = new Expression { Terms = new List<Term> { new Term { Value = "medium", Type = TermType.String } } };
  1848. //borderStyle = new Expression { Terms = new List<Term> { new Term { Value = "none", Type = TermType.String } } };
  1849. borderColor = null;
  1850. borderWidth = null;
  1851. borderStyle = null;
  1852. foreach (var term in p.Expression.Terms)
  1853. {
  1854. CssDataType dataType = GetDatatypeFromBorderTerm(term);
  1855. switch (dataType)
  1856. {
  1857. case CssDataType.Color:
  1858. borderColor = new CssExpression { Terms = new List<CssTerm> { term } };
  1859. break;
  1860. case CssDataType.BorderWidth:
  1861. borderWidth = new CssExpression { Terms = new List<CssTerm> { term } };
  1862. break;
  1863. case CssDataType.BorderStyle:
  1864. borderStyle = new CssExpression { Terms = new List<CssTerm> { term } };
  1865. break;
  1866. }
  1867. }
  1868. }
  1869. foreach (var side in new[] { "top", "left", "bottom", "right" })
  1870. {
  1871. if (borderWidth != null)
  1872. {
  1873. Property bwp = new Property
  1874. {
  1875. Name = "border-" + side + "-width",
  1876. Expression = borderWidth,
  1877. HighOrderSort = p.HighOrderSort,
  1878. IdAttributesInSelector = p.IdAttributesInSelector,
  1879. ElementNamesInSelector = p.ElementNamesInSelector,
  1880. AttributesInSelector = p.AttributesInSelector,
  1881. SequenceNumber = p.SequenceNumber,
  1882. };
  1883. AddPropertyToDictionary(propertyList, bwp);
  1884. }
  1885. if (borderStyle != null)
  1886. {
  1887. Property bsp = new Property
  1888. {
  1889. Name = "border-" + side + "-style",
  1890. Expression = borderStyle,
  1891. HighOrderSort = p.HighOrderSort,
  1892. IdAttributesInSelector = p.IdAttributesInSelector,
  1893. ElementNamesInSelector = p.ElementNamesInSelector,
  1894. AttributesInSelector = p.AttributesInSelector,
  1895. SequenceNumber = p.SequenceNumber,
  1896. };
  1897. AddPropertyToDictionary(propertyList, bsp);
  1898. }
  1899. if (borderColor != null)
  1900. {
  1901. Property bc = new Property
  1902. {
  1903. Name = "border-" + side + "-color",
  1904. Expression = borderColor,
  1905. HighOrderSort = p.HighOrderSort,
  1906. IdAttributesInSelector = p.IdAttributesInSelector,
  1907. ElementNamesInSelector = p.ElementNamesInSelector,
  1908. AttributesInSelector = p.AttributesInSelector,
  1909. SequenceNumber = p.SequenceNumber,
  1910. };
  1911. AddPropertyToDictionary(propertyList, bc);
  1912. }
  1913. }
  1914. continue;
  1915. }
  1916. if (p.Name == "border-top" || p.Name == "border-right" || p.Name == "border-bottom" || p.Name == "border-left")
  1917. {
  1918. CssExpression borderColor;
  1919. CssExpression borderWidth;
  1920. CssExpression borderStyle;
  1921. if (p.Expression.Terms.Count() == 1 && p.Expression.Terms.First().Value == "inherit")
  1922. {
  1923. borderColor = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1924. borderWidth = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1925. borderStyle = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  1926. }
  1927. else
  1928. {
  1929. //borderColor = GetComputedPropertyValue(null, element, "color", settings);
  1930. //borderWidth = new Expression { Terms = new List<Term> { new Term { Value = "medium", Type = TermType.String } } };
  1931. //borderStyle = new Expression { Terms = new List<Term> { new Term { Value = "none", Type = TermType.String } } };
  1932. borderColor = null;
  1933. borderWidth = null;
  1934. borderStyle = null;
  1935. foreach (var term in p.Expression.Terms)
  1936. {
  1937. CssDataType dataType = GetDatatypeFromBorderTerm(term);
  1938. switch (dataType)
  1939. {
  1940. case CssDataType.Color:
  1941. borderColor = new CssExpression { Terms = new List<CssTerm> { term } };
  1942. break;
  1943. case CssDataType.BorderWidth:
  1944. borderWidth = new CssExpression { Terms = new List<CssTerm> { term } };
  1945. break;
  1946. case CssDataType.BorderStyle:
  1947. borderStyle = new CssExpression { Terms = new List<CssTerm> { term } };
  1948. break;
  1949. }
  1950. }
  1951. }
  1952. if (borderWidth != null)
  1953. {
  1954. Property bwp = new Property
  1955. {
  1956. Name = p.Name + "-width",
  1957. Expression = borderWidth,
  1958. HighOrderSort = p.HighOrderSort,
  1959. IdAttributesInSelector = p.IdAttributesInSelector,
  1960. ElementNamesInSelector = p.ElementNamesInSelector,
  1961. AttributesInSelector = p.AttributesInSelector,
  1962. SequenceNumber = p.SequenceNumber,
  1963. };
  1964. AddPropertyToDictionary(propertyList, bwp);
  1965. }
  1966. if (borderStyle != null)
  1967. {
  1968. Property bsp = new Property
  1969. {
  1970. Name = p.Name + "-style",
  1971. Expression = borderStyle,
  1972. HighOrderSort = p.HighOrderSort,
  1973. IdAttributesInSelector = p.IdAttributesInSelector,
  1974. ElementNamesInSelector = p.ElementNamesInSelector,
  1975. AttributesInSelector = p.AttributesInSelector,
  1976. SequenceNumber = p.SequenceNumber,
  1977. };
  1978. AddPropertyToDictionary(propertyList, bsp);
  1979. }
  1980. if (borderColor != null)
  1981. {
  1982. Property bc = new Property
  1983. {
  1984. Name = p.Name + "-color",
  1985. Expression = borderColor,
  1986. HighOrderSort = p.HighOrderSort,
  1987. IdAttributesInSelector = p.IdAttributesInSelector,
  1988. ElementNamesInSelector = p.ElementNamesInSelector,
  1989. AttributesInSelector = p.AttributesInSelector,
  1990. SequenceNumber = p.SequenceNumber,
  1991. };
  1992. AddPropertyToDictionary(propertyList, bc);
  1993. }
  1994. continue;
  1995. }
  1996. if (p.Name == "list-style")
  1997. {
  1998. CssExpression listStyleType;
  1999. CssExpression listStylePosition;
  2000. CssExpression listStyleImage;
  2001. if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit")
  2002. {
  2003. listStyleType = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2004. listStylePosition = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2005. listStyleImage = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2006. }
  2007. else
  2008. {
  2009. listStyleType = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "disc", Type = CssTermType.String } } };
  2010. listStylePosition = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "outside", Type = CssTermType.String } } };
  2011. listStyleImage = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = CssTermType.String } } };
  2012. foreach (var term in p.Expression.Terms)
  2013. {
  2014. CssDataType dataType = GetDatatypeFromListStyleTerm(term);
  2015. switch (dataType)
  2016. {
  2017. case CssDataType.ListStyleType:
  2018. listStyleType = new CssExpression { Terms = new List<CssTerm> { term } };
  2019. break;
  2020. case CssDataType.ListStylePosition:
  2021. listStylePosition = new CssExpression { Terms = new List<CssTerm> { term } };
  2022. break;
  2023. case CssDataType.ListStyleImage:
  2024. listStyleImage = new CssExpression { Terms = new List<CssTerm> { term } };
  2025. break;
  2026. }
  2027. }
  2028. }
  2029. Property lst = new Property
  2030. {
  2031. Name = "list-style-type",
  2032. Expression = listStyleType,
  2033. HighOrderSort = p.HighOrderSort,
  2034. IdAttributesInSelector = p.IdAttributesInSelector,
  2035. ElementNamesInSelector = p.ElementNamesInSelector,
  2036. AttributesInSelector = p.AttributesInSelector,
  2037. SequenceNumber = p.SequenceNumber,
  2038. };
  2039. AddPropertyToDictionary(propertyList, lst);
  2040. Property lsp = new Property
  2041. {
  2042. Name = "list-style-position",
  2043. Expression = listStylePosition,
  2044. HighOrderSort = p.HighOrderSort,
  2045. IdAttributesInSelector = p.IdAttributesInSelector,
  2046. ElementNamesInSelector = p.ElementNamesInSelector,
  2047. AttributesInSelector = p.AttributesInSelector,
  2048. SequenceNumber = p.SequenceNumber,
  2049. };
  2050. AddPropertyToDictionary(propertyList, lsp);
  2051. Property lsi = new Property
  2052. {
  2053. Name = "list-style-image",
  2054. Expression = listStyleImage,
  2055. HighOrderSort = p.HighOrderSort,
  2056. IdAttributesInSelector = p.IdAttributesInSelector,
  2057. ElementNamesInSelector = p.ElementNamesInSelector,
  2058. AttributesInSelector = p.AttributesInSelector,
  2059. SequenceNumber = p.SequenceNumber,
  2060. };
  2061. AddPropertyToDictionary(propertyList, lsi);
  2062. continue;
  2063. }
  2064. if (p.Name == "background")
  2065. {
  2066. CssExpression backgroundColor;
  2067. CssExpression backgroundImage;
  2068. CssExpression backgroundRepeat;
  2069. CssExpression backgroundAttachment;
  2070. CssExpression backgroundPosition;
  2071. if (p.Expression.Terms.Count == 1 && p.Expression.Terms.First().Value == "inherit")
  2072. {
  2073. backgroundColor = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2074. backgroundImage = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2075. backgroundRepeat = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2076. backgroundAttachment = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2077. backgroundPosition = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2078. }
  2079. else
  2080. {
  2081. backgroundColor = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "transparent", Type = CssTermType.String } } };
  2082. backgroundImage = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "none", Type = CssTermType.String } } };
  2083. backgroundRepeat = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "repeat", Type = CssTermType.String } } };
  2084. backgroundAttachment = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "scroll", Type = CssTermType.String } } };
  2085. backgroundPosition = new CssExpression
  2086. {
  2087. Terms = new List<CssTerm> {
  2088. new CssTerm {
  2089. Value = "0",
  2090. Unit = OpenXmlPowerTools.HtmlToWml.CSS.CssUnit.Percent,
  2091. Type = CssTermType.Number },
  2092. new CssTerm {
  2093. Value = "0",
  2094. Unit = OpenXmlPowerTools.HtmlToWml.CSS.CssUnit.Percent,
  2095. Type = CssTermType.Number },
  2096. }
  2097. };
  2098. List<CssTerm> backgroundPositionList = new List<CssTerm>();
  2099. foreach (var term in p.Expression.Terms)
  2100. {
  2101. CssDataType dataType = GetDatatypeFromBackgroundTerm(term);
  2102. switch (dataType)
  2103. {
  2104. case CssDataType.BackgroundColor:
  2105. backgroundColor = new CssExpression { Terms = new List<CssTerm> { term } };
  2106. break;
  2107. case CssDataType.BackgroundImage:
  2108. backgroundImage = new CssExpression { Terms = new List<CssTerm> { term } };
  2109. break;
  2110. case CssDataType.BackgroundRepeat:
  2111. backgroundRepeat = new CssExpression { Terms = new List<CssTerm> { term } };
  2112. break;
  2113. case CssDataType.BackgroundAttachment:
  2114. backgroundAttachment = new CssExpression { Terms = new List<CssTerm> { term } };
  2115. break;
  2116. case CssDataType.BackgroundPosition:
  2117. backgroundPositionList.Add(term);
  2118. break;
  2119. }
  2120. }
  2121. if (backgroundPositionList.Count() == 1)
  2122. {
  2123. backgroundPosition = new CssExpression
  2124. {
  2125. Terms = new List<CssTerm> {
  2126. backgroundPositionList.First(),
  2127. new CssTerm {
  2128. Value = "center",
  2129. Type = CssTermType.String
  2130. },
  2131. }
  2132. };
  2133. }
  2134. if (backgroundPositionList.Count() == 2)
  2135. {
  2136. backgroundPosition = new CssExpression
  2137. {
  2138. Terms = backgroundPositionList
  2139. };
  2140. }
  2141. }
  2142. Property bc = new Property
  2143. {
  2144. Name = "background-color",
  2145. Expression = backgroundColor,
  2146. HighOrderSort = p.HighOrderSort,
  2147. IdAttributesInSelector = p.IdAttributesInSelector,
  2148. ElementNamesInSelector = p.ElementNamesInSelector,
  2149. AttributesInSelector = p.AttributesInSelector,
  2150. SequenceNumber = p.SequenceNumber,
  2151. };
  2152. AddPropertyToDictionary(propertyList, bc);
  2153. Property bgi = new Property
  2154. {
  2155. Name = "background-image",
  2156. Expression = backgroundImage,
  2157. HighOrderSort = p.HighOrderSort,
  2158. IdAttributesInSelector = p.IdAttributesInSelector,
  2159. ElementNamesInSelector = p.ElementNamesInSelector,
  2160. AttributesInSelector = p.AttributesInSelector,
  2161. SequenceNumber = p.SequenceNumber,
  2162. };
  2163. AddPropertyToDictionary(propertyList, bgi);
  2164. Property bgr = new Property
  2165. {
  2166. Name = "background-repeat",
  2167. Expression = backgroundRepeat,
  2168. HighOrderSort = p.HighOrderSort,
  2169. IdAttributesInSelector = p.IdAttributesInSelector,
  2170. ElementNamesInSelector = p.ElementNamesInSelector,
  2171. AttributesInSelector = p.AttributesInSelector,
  2172. SequenceNumber = p.SequenceNumber,
  2173. };
  2174. AddPropertyToDictionary(propertyList, bgr);
  2175. Property bga = new Property
  2176. {
  2177. Name = "background-attachment",
  2178. Expression = backgroundAttachment,
  2179. HighOrderSort = p.HighOrderSort,
  2180. IdAttributesInSelector = p.IdAttributesInSelector,
  2181. ElementNamesInSelector = p.ElementNamesInSelector,
  2182. AttributesInSelector = p.AttributesInSelector,
  2183. SequenceNumber = p.SequenceNumber,
  2184. };
  2185. AddPropertyToDictionary(propertyList, bga);
  2186. Property bgp = new Property
  2187. {
  2188. Name = "background-position",
  2189. Expression = backgroundPosition,
  2190. HighOrderSort = p.HighOrderSort,
  2191. IdAttributesInSelector = p.IdAttributesInSelector,
  2192. ElementNamesInSelector = p.ElementNamesInSelector,
  2193. AttributesInSelector = p.AttributesInSelector,
  2194. SequenceNumber = p.SequenceNumber,
  2195. };
  2196. AddPropertyToDictionary(propertyList, bgp);
  2197. continue;
  2198. }
  2199. if (p.Name == "font")
  2200. {
  2201. CssExpression fontStyle;
  2202. CssExpression fontVarient;
  2203. CssExpression fontWeight;
  2204. CssExpression fontSize;
  2205. CssExpression lineHeight;
  2206. CssExpression fontFamily;
  2207. if (p.Expression.Terms.Count() == 1 && p.Expression.Terms.First().Value == "inherit")
  2208. {
  2209. fontStyle = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2210. fontVarient = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2211. fontWeight = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2212. fontSize = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2213. lineHeight = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2214. fontFamily = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "inherit", Type = CssTermType.String } } };
  2215. }
  2216. else
  2217. {
  2218. fontStyle = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = CssTermType.String } } };
  2219. fontVarient = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = CssTermType.String } } };
  2220. fontWeight = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = CssTermType.String } } };
  2221. fontSize = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "medium", Type = CssTermType.String } } };
  2222. lineHeight = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "normal", Type = CssTermType.String } } };
  2223. fontFamily = new CssExpression { Terms = new List<CssTerm> { new CssTerm { Value = "serif", Type = CssTermType.String } } };
  2224. List<CssTerm> fontFamilyList = new List<CssTerm>();
  2225. foreach (var term in p.Expression.Terms)
  2226. {
  2227. CssDataType dataType = GetDatatypeFromFontTerm(term);
  2228. switch (dataType)
  2229. {
  2230. case CssDataType.FontStyle:
  2231. fontStyle = new CssExpression { Terms = new List<CssTerm> { term } };
  2232. break;
  2233. case CssDataType.FontVarient:
  2234. fontVarient = new CssExpression { Terms = new List<CssTerm> { term } };
  2235. break;
  2236. case CssDataType.FontWeight:
  2237. fontWeight = new CssExpression { Terms = new List<CssTerm> { term } };
  2238. break;
  2239. case CssDataType.FontSize:
  2240. fontSize = new CssExpression { Terms = new List<CssTerm> { term } };
  2241. break;
  2242. case CssDataType.Length:
  2243. if (term.SeparatorChar == "/")
  2244. lineHeight = new CssExpression { Terms = new List<CssTerm> { term } };
  2245. else
  2246. fontSize = new CssExpression { Terms = new List<CssTerm> { term } };
  2247. break;
  2248. case CssDataType.FontFamily:
  2249. fontFamilyList.Add(term);
  2250. break;
  2251. }
  2252. }
  2253. if (fontFamilyList.Count > 0)
  2254. fontFamily = new CssExpression { Terms = fontFamilyList };
  2255. }
  2256. Property fs = new Property
  2257. {
  2258. Name = "font-style",
  2259. Expression = fontStyle,
  2260. HighOrderSort = p.HighOrderSort,
  2261. IdAttributesInSelector = p.IdAttributesInSelector,
  2262. ElementNamesInSelector = p.ElementNamesInSelector,
  2263. AttributesInSelector = p.AttributesInSelector,
  2264. SequenceNumber = p.SequenceNumber,
  2265. };
  2266. AddPropertyToDictionary(propertyList, fs);
  2267. Property fv = new Property
  2268. {
  2269. Name = "font-varient",
  2270. Expression = fontVarient,
  2271. HighOrderSort = p.HighOrderSort,
  2272. IdAttributesInSelector = p.IdAttributesInSelector,
  2273. ElementNamesInSelector = p.ElementNamesInSelector,
  2274. AttributesInSelector = p.AttributesInSelector,
  2275. SequenceNumber = p.SequenceNumber,
  2276. };
  2277. AddPropertyToDictionary(propertyList, fv);
  2278. Property fw = new Property
  2279. {
  2280. Name = "font-weight",
  2281. Expression = fontWeight,
  2282. HighOrderSort = p.HighOrderSort,
  2283. IdAttributesInSelector = p.IdAttributesInSelector,
  2284. ElementNamesInSelector = p.ElementNamesInSelector,
  2285. AttributesInSelector = p.AttributesInSelector,
  2286. SequenceNumber = p.SequenceNumber,
  2287. };
  2288. AddPropertyToDictionary(propertyList, fw);
  2289. Property fsz = new Property
  2290. {
  2291. Name = "font-size",
  2292. Expression = fontSize,
  2293. HighOrderSort = p.HighOrderSort,
  2294. IdAttributesInSelector = p.IdAttributesInSelector,
  2295. ElementNamesInSelector = p.ElementNamesInSelector,
  2296. AttributesInSelector = p.AttributesInSelector,
  2297. SequenceNumber = p.SequenceNumber,
  2298. };
  2299. AddPropertyToDictionary(propertyList, fsz);
  2300. Property lh = new Property
  2301. {
  2302. Name = "line-height",
  2303. Expression = lineHeight,
  2304. HighOrderSort = p.HighOrderSort,
  2305. IdAttributesInSelector = p.IdAttributesInSelector,
  2306. ElementNamesInSelector = p.ElementNamesInSelector,
  2307. AttributesInSelector = p.AttributesInSelector,
  2308. SequenceNumber = p.SequenceNumber,
  2309. };
  2310. AddPropertyToDictionary(propertyList, lh);
  2311. Property ff = new Property
  2312. {
  2313. Name = "font-family",
  2314. Expression = fontFamily,
  2315. HighOrderSort = p.HighOrderSort,
  2316. IdAttributesInSelector = p.IdAttributesInSelector,
  2317. ElementNamesInSelector = p.ElementNamesInSelector,
  2318. AttributesInSelector = p.AttributesInSelector,
  2319. SequenceNumber = p.SequenceNumber,
  2320. };
  2321. AddPropertyToDictionary(propertyList, ff);
  2322. continue;
  2323. }
  2324. foreach (var shPr in ShorthandProperties)
  2325. {
  2326. if (p.Name == shPr.Name)
  2327. {
  2328. switch (p.Expression.Terms.Count)
  2329. {
  2330. case 1:
  2331. foreach (var direction in new[] { "top", "right", "bottom", "left" })
  2332. {
  2333. Property ep = new Property()
  2334. {
  2335. Name = String.Format(shPr.Pattern, direction),
  2336. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.First() } },
  2337. HighOrderSort = p.HighOrderSort,
  2338. IdAttributesInSelector = p.IdAttributesInSelector,
  2339. AttributesInSelector = p.AttributesInSelector,
  2340. ElementNamesInSelector = p.ElementNamesInSelector,
  2341. SequenceNumber = p.SequenceNumber,
  2342. };
  2343. AddPropertyToDictionary(propertyList, ep);
  2344. }
  2345. break;
  2346. case 2:
  2347. foreach (var direction in new[] { "top", "bottom" })
  2348. {
  2349. Property ep = new Property()
  2350. {
  2351. Name = String.Format(shPr.Pattern, direction),
  2352. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.First() } },
  2353. HighOrderSort = p.HighOrderSort,
  2354. IdAttributesInSelector = p.IdAttributesInSelector,
  2355. AttributesInSelector = p.AttributesInSelector,
  2356. ElementNamesInSelector = p.ElementNamesInSelector,
  2357. SequenceNumber = p.SequenceNumber,
  2358. };
  2359. AddPropertyToDictionary(propertyList, ep);
  2360. }
  2361. foreach (var direction in new[] { "left", "right" })
  2362. {
  2363. Property ep = new Property()
  2364. {
  2365. Name = String.Format(shPr.Pattern, direction),
  2366. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.Skip(1).First() } },
  2367. HighOrderSort = p.HighOrderSort,
  2368. IdAttributesInSelector = p.IdAttributesInSelector,
  2369. AttributesInSelector = p.AttributesInSelector,
  2370. ElementNamesInSelector = p.ElementNamesInSelector,
  2371. SequenceNumber = p.SequenceNumber,
  2372. };
  2373. AddPropertyToDictionary(propertyList, ep);
  2374. }
  2375. break;
  2376. case 3:
  2377. Property ep3 = new Property()
  2378. {
  2379. Name = String.Format(shPr.Pattern, "top"),
  2380. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.First() } },
  2381. HighOrderSort = p.HighOrderSort,
  2382. IdAttributesInSelector = p.IdAttributesInSelector,
  2383. AttributesInSelector = p.AttributesInSelector,
  2384. ElementNamesInSelector = p.ElementNamesInSelector,
  2385. SequenceNumber = p.SequenceNumber,
  2386. };
  2387. AddPropertyToDictionary(propertyList, ep3);
  2388. foreach (var direction in new[] { "left", "right" })
  2389. {
  2390. Property ep2 = new Property()
  2391. {
  2392. Name = String.Format(shPr.Pattern, direction),
  2393. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.Skip(1).First() } },
  2394. HighOrderSort = p.HighOrderSort,
  2395. IdAttributesInSelector = p.IdAttributesInSelector,
  2396. AttributesInSelector = p.AttributesInSelector,
  2397. ElementNamesInSelector = p.ElementNamesInSelector,
  2398. SequenceNumber = p.SequenceNumber,
  2399. };
  2400. AddPropertyToDictionary(propertyList, ep2);
  2401. }
  2402. Property ep4 = new Property()
  2403. {
  2404. Name = String.Format(shPr.Pattern, "bottom"),
  2405. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.Skip(2).First() } },
  2406. HighOrderSort = p.HighOrderSort,
  2407. IdAttributesInSelector = p.IdAttributesInSelector,
  2408. AttributesInSelector = p.AttributesInSelector,
  2409. ElementNamesInSelector = p.ElementNamesInSelector,
  2410. SequenceNumber = p.SequenceNumber,
  2411. };
  2412. AddPropertyToDictionary(propertyList, ep4);
  2413. break;
  2414. case 4:
  2415. int skip = 0;
  2416. foreach (var direction in new[] { "top", "right", "bottom", "left" })
  2417. {
  2418. Property ep = new Property()
  2419. {
  2420. Name = String.Format(shPr.Pattern, direction),
  2421. Expression = new CssExpression { Terms = new List<CssTerm> { p.Expression.Terms.Skip(skip++).First() } },
  2422. HighOrderSort = p.HighOrderSort,
  2423. IdAttributesInSelector = p.IdAttributesInSelector,
  2424. AttributesInSelector = p.AttributesInSelector,
  2425. ElementNamesInSelector = p.ElementNamesInSelector,
  2426. SequenceNumber = p.SequenceNumber,
  2427. };
  2428. AddPropertyToDictionary(propertyList, ep);
  2429. }
  2430. break;
  2431. }
  2432. }
  2433. }
  2434. }
  2435. }
  2436. private static string[] BackgroundRepeatValues = new[]
  2437. {
  2438. "repeat",
  2439. "repeat-x",
  2440. "repeat-y",
  2441. "no-repeat",
  2442. };
  2443. private static string[] BackgroundAttachmentValues = new[]
  2444. {
  2445. "scroll",
  2446. "fixed",
  2447. };
  2448. private static string[] BackgroundPositionValues = new[]
  2449. {
  2450. "left",
  2451. "right",
  2452. "top",
  2453. "bottom",
  2454. "center",
  2455. };
  2456. private static CssDataType GetDatatypeFromBackgroundTerm(CssTerm term)
  2457. {
  2458. if (term.IsColor)
  2459. return CssDataType.BackgroundColor;
  2460. if (BackgroundRepeatValues.Contains(term.Value.ToLower()))
  2461. return CssDataType.BackgroundRepeat;
  2462. if (BackgroundAttachmentValues.Contains(term.Value.ToLower()))
  2463. return CssDataType.BackgroundAttachment;
  2464. if (term.Function != null)
  2465. return CssDataType.BackgroundImage;
  2466. if (term.Unit == CssUnit.CM ||
  2467. term.Unit == CssUnit.EM ||
  2468. term.Unit == CssUnit.IN ||
  2469. term.Unit == CssUnit.MM ||
  2470. term.Unit == CssUnit.PT ||
  2471. term.Unit == CssUnit.PX ||
  2472. term.Unit == CssUnit.Percent)
  2473. return CssDataType.BackgroundPosition;
  2474. if (BackgroundPositionValues.Contains(term.Value.ToLower()))
  2475. return CssDataType.BackgroundPosition;
  2476. return CssDataType.BackgroundPosition;
  2477. }
  2478. private static string[] ListStylePositionValues = new[]
  2479. {
  2480. "inside",
  2481. "outside",
  2482. };
  2483. private static string[] BorderStyleValues = new[]
  2484. {
  2485. "none",
  2486. "hidden",
  2487. "dotted",
  2488. "dashed",
  2489. "solid",
  2490. "double",
  2491. "groove",
  2492. "ridge",
  2493. "inset",
  2494. "outset",
  2495. };
  2496. private static CssDataType GetDatatypeFromBorderTerm(CssTerm term)
  2497. {
  2498. if (term.IsColor)
  2499. {
  2500. return CssDataType.Color;
  2501. }
  2502. if (BorderStyleValues.Contains(term.Value.ToLower()))
  2503. return CssDataType.BorderStyle;
  2504. return CssDataType.BorderWidth;
  2505. }
  2506. private static string[] ListStyleTypeValues = new[]
  2507. {
  2508. "disc",
  2509. "circle",
  2510. "square",
  2511. "decimal",
  2512. "decimal-leading-zero",
  2513. "lower-roman",
  2514. "upper-roman",
  2515. "lower-greek",
  2516. "lower-latin",
  2517. "upper-latin",
  2518. "armenian",
  2519. "georgian",
  2520. "lower-alpha",
  2521. "upper-alpha",
  2522. };
  2523. private static CssDataType GetDatatypeFromListStyleTerm(CssTerm term)
  2524. {
  2525. if (ListStyleTypeValues.Contains(term.Value.ToLower()))
  2526. return CssDataType.ListStyleType;
  2527. if (ListStylePositionValues.Contains(term.Value.ToLower()))
  2528. return CssDataType.ListStylePosition;
  2529. return CssDataType.ListStyleImage;
  2530. }
  2531. private static string[] FontStyleValues = new[]
  2532. {
  2533. "italic",
  2534. "oblique",
  2535. };
  2536. private static string[] FontVarientValues = new[]
  2537. {
  2538. "small-caps",
  2539. };
  2540. private static string[] FontWeightValues = new[]
  2541. {
  2542. "bold",
  2543. "bolder",
  2544. "lighter",
  2545. "100",
  2546. "200",
  2547. "300",
  2548. "400",
  2549. "500",
  2550. "600",
  2551. "700",
  2552. "800",
  2553. "900",
  2554. };
  2555. private static CssDataType GetDatatypeFromFontTerm(CssTerm term)
  2556. {
  2557. if (FontStyleValues.Contains(term.Value.ToLower()))
  2558. return CssDataType.FontStyle;
  2559. if (FontVarientValues.Contains(term.Value.ToLower()))
  2560. return CssDataType.FontVarient;
  2561. if (FontWeightValues.Contains(term.Value.ToLower()))
  2562. return CssDataType.FontWeight;
  2563. if (FontSizeMap.ContainsKey(term.Value.ToLower()))
  2564. return CssDataType.FontSize;
  2565. if (term.Unit == CssUnit.CM ||
  2566. term.Unit == CssUnit.EM ||
  2567. term.Unit == CssUnit.IN ||
  2568. term.Unit == CssUnit.MM ||
  2569. term.Unit == CssUnit.PT ||
  2570. term.Unit == CssUnit.PX ||
  2571. term.Unit == CssUnit.Percent)
  2572. return CssDataType.Length;
  2573. return CssDataType.FontFamily;
  2574. }
  2575. public class PropertyInfo
  2576. {
  2577. public string[] Names;
  2578. public bool Inherits;
  2579. public Func<XElement, HtmlToWmlConverterSettings, bool> Includes;
  2580. public Func<XElement, HtmlToWmlConverterSettings, CssExpression> InitialValue;
  2581. public Func<XElement, CssExpression, HtmlToWmlConverterSettings, CssExpression> ComputedValue;
  2582. }
  2583. private static void WriteXHtmlWithAnnotations(XElement element, StringBuilder sb)
  2584. {
  2585. int depth = element.Ancestors().Count() * 2;
  2586. XElement dummyElement = new XElement(element.Name, element.Attributes());
  2587. sb.Append(String.Format("{0}{1}", "".PadRight(depth), dummyElement) + Environment.NewLine);
  2588. Dictionary<string, Property> propList = element.Annotation<Dictionary<string, Property>>();
  2589. if (propList != null)
  2590. {
  2591. sb.Append("".PadRight(depth + 2) + "Properties from Stylesheets" + Environment.NewLine);
  2592. sb.Append("".PadRight(depth + 2) + "===========================" + Environment.NewLine);
  2593. foreach (var kvp in propList.OrderBy(p => p.Key).ThenBy(p => p.Value))
  2594. {
  2595. Property prop = kvp.Value;
  2596. string propString = String.Format("{0} High:{1} Id:{2} Att:{3} Ell:{4} Seq:{5}",
  2597. (prop.Name + ":" + prop.Expression + " ").PadRight(50 - depth + 2, '.'), (int)prop.HighOrderSort, prop.IdAttributesInSelector, prop.AttributesInSelector,
  2598. prop.ElementNamesInSelector, prop.SequenceNumber);
  2599. sb.Append(String.Format("{0}{1}", "".PadRight(depth + 2), propString) + Environment.NewLine);
  2600. }
  2601. sb.Append(Environment.NewLine);
  2602. }
  2603. Dictionary<string, CssExpression> computedProperties = element.Annotation<Dictionary<string, CssExpression>>();
  2604. if (computedProperties != null)
  2605. {
  2606. sb.Append("".PadRight(depth + 2) + "Computed Properties" + Environment.NewLine);
  2607. sb.Append("".PadRight(depth + 2) + "===================" + Environment.NewLine);
  2608. foreach (var prop in computedProperties.OrderBy(cp => cp.Key))
  2609. {
  2610. string propString = prop.Key + ":" + prop.Value;
  2611. sb.Append(String.Format("{0}{1}", "".PadRight(depth + 2), propString) + Environment.NewLine);
  2612. }
  2613. sb.Append(Environment.NewLine);
  2614. }
  2615. foreach (var child in element.Elements())
  2616. WriteXHtmlWithAnnotations(child, sb);
  2617. }
  2618. public static string DumpCss(CssDocument css)
  2619. {
  2620. StringBuilder sb = new StringBuilder();
  2621. int indent = 0;
  2622. Pr(sb, indent, "CSS Tree Dump");
  2623. Pr(sb, indent, "=============");
  2624. Pr(sb, indent, "Directives count: {0}", css.Directives.Count());
  2625. Pr(sb, indent, "RuleSet count: {0}", css.RuleSets.Count());
  2626. foreach (var rs in css.RuleSets)
  2627. DumpRuleSet(sb, indent, rs);
  2628. Pr(sb, indent, "");
  2629. return sb.ToString();
  2630. }
  2631. private static void DumpFunction(StringBuilder sb, int indent, CssFunction f)
  2632. {
  2633. Pr(sb, indent, "Function: {0}", f);
  2634. if (f != null)
  2635. {
  2636. indent++;
  2637. Pr(sb, indent, "Name: {0}", f.Name);
  2638. DumpExpression(sb, indent, f.Expression);
  2639. indent--;
  2640. }
  2641. }
  2642. private static void DumpAttribute(StringBuilder sb, int indent, OpenXmlPowerTools.HtmlToWml.CSS.CssAttribute a)
  2643. {
  2644. Pr(sb, indent, "Attribute: {0}", a);
  2645. if (a != null)
  2646. {
  2647. indent++;
  2648. Pr(sb, indent, "Operand: {0}", a.Operand);
  2649. Pr(sb, indent, "Operator: {0}", a.Operator);
  2650. Pr(sb, indent, "OperatorString: {0}", a.CssOperatorString);
  2651. Pr(sb, indent, "Value: {0}", a.Value);
  2652. indent--;
  2653. }
  2654. }
  2655. private static void DumpSimpleSelector(StringBuilder sb, int indent, CssSimpleSelector s)
  2656. {
  2657. indent++;
  2658. Pr(sb, indent, "SimpleSelector: {0}", s);
  2659. if (s != null)
  2660. {
  2661. indent++;
  2662. DumpAttribute(sb, indent, s.Attribute);
  2663. Pr(sb, indent, "Child: {0}", s.Child);
  2664. DumpSimpleSelector(sb, indent, s.Child);
  2665. Pr(sb, indent, "Class: {0}", s.Class);
  2666. Pr(sb, indent, "Combinator: {0}", s.Combinator);
  2667. Pr(sb, indent, "CombinatorString: {0}", s.CombinatorString);
  2668. Pr(sb, indent, "ElementName: >{0}<", s.ElementName);
  2669. DumpFunction(sb, indent, s.Function);
  2670. Pr(sb, indent, "ID: {0}", s.ID);
  2671. Pr(sb, indent, "Pseudo: {0}", s.Pseudo);
  2672. indent--;
  2673. }
  2674. indent--;
  2675. }
  2676. private static void DumpSelectors(StringBuilder sb, int indent, CssSelector s)
  2677. {
  2678. indent++;
  2679. Pr(sb, indent, "SimpleSelectors count: {0}", s.SimpleSelectors.Count());
  2680. foreach (var ss in s.SimpleSelectors)
  2681. DumpSimpleSelector(sb, indent, ss);
  2682. indent--;
  2683. }
  2684. private static void DumpTerm(StringBuilder sb, int indent, CssTerm t)
  2685. {
  2686. Pr(sb, indent, "Term >{0}<", t.ToString());
  2687. indent++;
  2688. DumpFunction(sb, indent, t.Function);
  2689. Pr(sb, indent, "IsColor: {0}", t.IsColor);
  2690. Pr(sb, indent, "Separator: {0}", t.Separator);
  2691. Pr(sb, indent, "SeparatorChar: {0}", t.SeparatorChar);
  2692. Pr(sb, indent, "Sign: {0}", t.Sign);
  2693. Pr(sb, indent, "SignChar: {0}", t.SignChar);
  2694. Pr(sb, indent, "Type: {0}", t.Type);
  2695. Pr(sb, indent, "Unit: {0}", t.Unit);
  2696. Pr(sb, indent, "UnitString: {0}", t.UnitString);
  2697. Pr(sb, indent, "Value: {0}", t.Value);
  2698. indent--;
  2699. }
  2700. private static void DumpExpression(StringBuilder sb, int indent, CssExpression e)
  2701. {
  2702. Pr(sb, indent, "Expression >{0}<", e.ToString());
  2703. indent++;
  2704. Pr(sb, indent, "Terms count: {0}", e.Terms.Count());
  2705. foreach (var t in e.Terms)
  2706. DumpTerm(sb, indent, t);
  2707. indent--;
  2708. }
  2709. private static void DumpDeclarations(StringBuilder sb, int indent, CssDeclaration d)
  2710. {
  2711. indent++;
  2712. Pr(sb, indent, "Declaration >{0}<", d.ToString());
  2713. indent++;
  2714. Pr(sb, indent, "Name: {0}", d.Name);
  2715. DumpExpression(sb, indent, d.Expression);
  2716. Pr(sb, indent, "Important: {0}", d.Important);
  2717. indent--;
  2718. indent--;
  2719. }
  2720. private static void DumpRuleSet(StringBuilder sb, int indent, CssRuleSet rs)
  2721. {
  2722. indent++;
  2723. Pr(sb, indent, "RuleSet");
  2724. indent++;
  2725. Pr(sb, indent, "Selectors count: {0}", rs.Selectors.Count());
  2726. foreach (var s in rs.Selectors)
  2727. DumpSelectors(sb, indent, s);
  2728. Pr(sb, indent, "Declarations count: {0}", rs.Declarations.Count());
  2729. foreach (var d in rs.Declarations)
  2730. DumpDeclarations(sb, indent, d);
  2731. indent--;
  2732. indent--;
  2733. }
  2734. private static void Pr(StringBuilder sb, int indent, string format, object o)
  2735. {
  2736. if (o == null)
  2737. return;
  2738. string text = String.Format(format, o);
  2739. StringBuilder sb2 = new StringBuilder("".PadRight(indent * 2) + text);
  2740. //sb2.Replace("&", "&amp;");
  2741. //sb2.Replace("<", "&lt;");
  2742. //sb2.Replace(">", "&gt;");
  2743. sb.Append(sb2);
  2744. sb.Append(Environment.NewLine);
  2745. //Console.WriteLine(sb2);
  2746. }
  2747. private static void Pr(StringBuilder sb, int indent, string text)
  2748. {
  2749. StringBuilder sb2 = new StringBuilder("".PadRight(indent * 2) + text);
  2750. //sb2.Replace("&", "&amp;");
  2751. //sb2.Replace("<", "&lt;");
  2752. //sb2.Replace(">", "&gt;");
  2753. sb.Append(sb2);
  2754. sb.Append(Environment.NewLine);
  2755. //Console.WriteLine(sb2);
  2756. }
  2757. public class Property : IComparable<Property>
  2758. {
  2759. public string Name { get; set; }
  2760. public CssExpression Expression { get; set; }
  2761. public HighOrderPriority HighOrderSort { get; set; }
  2762. public int IdAttributesInSelector { get; set; }
  2763. public int AttributesInSelector { get; set; }
  2764. public int ElementNamesInSelector { get; set; }
  2765. public int SequenceNumber { get; set; }
  2766. public enum HighOrderPriority
  2767. {
  2768. InitialValue = 0,
  2769. Inherited = 1,
  2770. UserAgentNormal = 2,
  2771. UserAgentHigh = 3,
  2772. UserNormal = 4,
  2773. AuthorNormal = 5,
  2774. HtmlAttribute = 6,
  2775. StyleAttributeNormal = 7,
  2776. StyleAttributeHigh = 8,
  2777. AuthorHigh = 9,
  2778. UserHigh = 10,
  2779. };
  2780. int System.IComparable<Property>.CompareTo(Property other)
  2781. {
  2782. // if this is less than other, return -1
  2783. // if this is greater than other, return 1
  2784. int gt = 1;
  2785. int lt = -1;
  2786. if (this.HighOrderSort < other.HighOrderSort)
  2787. return lt;
  2788. if (this.HighOrderSort > other.HighOrderSort)
  2789. return gt;
  2790. if (this.IdAttributesInSelector < other.IdAttributesInSelector)
  2791. return lt;
  2792. if (this.IdAttributesInSelector > other.IdAttributesInSelector)
  2793. return gt;
  2794. if (this.AttributesInSelector < other.AttributesInSelector)
  2795. return lt;
  2796. if (this.AttributesInSelector > other.AttributesInSelector)
  2797. return gt;
  2798. if (this.ElementNamesInSelector < other.ElementNamesInSelector)
  2799. return lt;
  2800. if (this.ElementNamesInSelector > other.ElementNamesInSelector)
  2801. return gt;
  2802. return this.SequenceNumber.CompareTo(other.SequenceNumber);
  2803. }
  2804. }
  2805. private static Dictionary<string, string> ColorMap = new Dictionary<string, string>()
  2806. {
  2807. { "maroon", "800000" },
  2808. { "red", "FF0000" },
  2809. { "orange", "FFA500" },
  2810. { "yellow", "FFFF00" },
  2811. { "olive", "808000" },
  2812. { "purple", "800080" },
  2813. { "fuchsia", "FF00FF" },
  2814. { "white", "FFFFFF" },
  2815. { "lime", "00FF00" },
  2816. { "green", "008000" },
  2817. { "navy", "000080" },
  2818. { "blue", "0000FF" },
  2819. { "mediumblue", "0000CD" },
  2820. { "aqua", "00FFFF" },
  2821. { "teal", "008080" },
  2822. { "black", "000000" },
  2823. { "silver", "C0C0C0" },
  2824. { "gray", "808080" },
  2825. { "darkgray", "A9A9A9" },
  2826. { "beige", "F5F5DC" },
  2827. { "windowtext", "000000" },
  2828. };
  2829. public static string GetWmlColorFromExpression(CssExpression color)
  2830. {
  2831. // todo have to handle all forms of colors here
  2832. if (color.Terms.Count() == 1)
  2833. {
  2834. CssTerm term = color.Terms.First();
  2835. if (term.Type == CssTermType.Function && term.Function.Name.ToUpper() == "RGB" && term.Function.Expression.Terms.Count == 3)
  2836. {
  2837. List<CssTerm> lt = term.Function.Expression.Terms;
  2838. if (lt.First().Unit == CssUnit.Percent)
  2839. {
  2840. string v1 = lt.First().Value;
  2841. string v2 = lt.ElementAt(1).Value;
  2842. string v3 = lt.ElementAt(2).Value;
  2843. string colorInHex = String.Format("{0:x2}{1:x2}{2:x2}", (int)((float.Parse(v1) / 100.0) * 255),
  2844. (int)((float.Parse(v2) / 100.0) * 255), (int)((float.Parse(v3) / 100.0) * 255));
  2845. return colorInHex;
  2846. }
  2847. else
  2848. {
  2849. string v1 = lt.First().Value;
  2850. string v2 = lt.ElementAt(1).Value;
  2851. string v3 = lt.ElementAt(2).Value;
  2852. string colorInHex = String.Format("{0:x2}{1:x2}{2:x2}", int.Parse(v1), int.Parse(v2), int.Parse(v3));
  2853. return colorInHex;
  2854. }
  2855. }
  2856. string value = term.Value;
  2857. if (value.Substring(0, 1) == "#" && value.Length == 4)
  2858. {
  2859. string e = ConvertSingleDigit(value.Substring(1, 1)) +
  2860. ConvertSingleDigit(value.Substring(2, 1)) +
  2861. ConvertSingleDigit(value.Substring(3, 1));
  2862. return e;
  2863. }
  2864. if (value.Substring(0, 1) == "#")
  2865. return value.Substring(1);
  2866. if (ColorMap.ContainsKey(value))
  2867. return ColorMap[value];
  2868. return value;
  2869. }
  2870. return "000000";
  2871. }
  2872. private static string ConvertSingleDigit(string singleDigit)
  2873. {
  2874. return singleDigit + singleDigit;
  2875. }
  2876. }
  2877. }
  2878. #if false
  2879. color
  2880. Value: <color> | inherit
  2881. Initial: depends on UA
  2882. Applies to: all elements
  2883. Inherited: yes
  2884. Percentages: N/A
  2885. Computed value: as spec
  2886. margin-top, margin-bottom
  2887. Value: <margin-width> | inherit
  2888. Initial: 0
  2889. Applies to: all elements except elements with table display types other than table-caption, table, and inline-table
  2890. all elements except th, td, tr
  2891. Inherited: no
  2892. Percentages: refer to width of containing block
  2893. Computed value: the percentage as specified or the absolute length
  2894. margin-right, margin-left
  2895. Value: <margin-width> | inherit
  2896. Initial: 0
  2897. Applies to: all elements except elements with table display types other than table-caption, table, and inline-table
  2898. all elements except th, td, tr
  2899. Inherited: no
  2900. Percentages: refer to width of containing block
  2901. Computed value: the percentage as specified or the absolute length
  2902. padding-top, padding-right, padding-bottom, padding-left
  2903. Value: <padding-width> | inherit
  2904. Initial: 0
  2905. Applies to: all elements except table-row-group, table-header-group,
  2906. table-footer-group, table-row, table-column-group and table-column
  2907. all elements except tr
  2908. Inherited: no
  2909. Percentages: refer to width of containing block
  2910. Computed value: the percentage as specified or the absolute length
  2911. border-top-width, border-right-width, border-bottom-width, border-left-width
  2912. Value: <border-width> | inherit
  2913. Initial: medium
  2914. Applies to: all elements
  2915. Inherited: no
  2916. Percentages: N/A
  2917. Computed value: absolute length; '0' if the border style is 'none' or 'hidden'
  2918. border-top-color, border-right-color, border-bottom-color, border-left-color
  2919. Value: <color> | transparent | inherit
  2920. Initial: the value of the color property
  2921. Applies to: all elements
  2922. Inherited: no
  2923. Percentages: N/A
  2924. Computed value: when taken from the ’color’ property, the computed value of
  2925. ’color’; otherwise, as specified
  2926. border-top-style, border-right-style, border-bottom-style, border-left-style
  2927. Value: <border-style> | inherit
  2928. Initial: none
  2929. Applies to: all elements
  2930. Inherited: no
  2931. Percentages: N/A
  2932. Computed value: as specified
  2933. display
  2934. Value: inline | block | list-item | inline-block | table | inline-table |
  2935. table-row-group | table-header-group | table-footer-group |
  2936. table-row | table-column-group | table-column | table-cell |
  2937. table-caption | none | inherit
  2938. Initial: inline
  2939. Applies to: all elements
  2940. Inherited: no
  2941. Percentages: N/A
  2942. Computed value: see text
  2943. position
  2944. Value: static | relative | absolute | fixed | inherit
  2945. Initial: static
  2946. Applies to: all elements
  2947. Inherited: no
  2948. Percentages: N/A
  2949. Computed value: as specified
  2950. top
  2951. Value: <length> | <percentage> | auto | inherit
  2952. Initial: auto
  2953. Applies to: positioned elements
  2954. Inherited: no
  2955. Percentages: refer to height of containing block
  2956. Computed value: if specified as a length, the corresponding absolute length; if
  2957. specified as a percentage, the specified value; otherwise, ’auto’.
  2958. right
  2959. Value: <length> | <percentage> | auto | inherit
  2960. Initial: auto
  2961. Applies to: positioned elements
  2962. Inherited: no
  2963. Percentages: refer to width of containing block
  2964. Computed value: if specified as a length, the corresponding absolute length; if
  2965. specified as a percentage, the specified value; otherwise, ’auto’.
  2966. bottom
  2967. Value: <length> | <percentage> | auto | inherit
  2968. Initial: auto
  2969. Applies to: positioned elements
  2970. Inherited: no
  2971. Percentages: refer to height of containing block
  2972. Computed value: if specified as a length, the corresponding absolute length; if
  2973. specified as a percentage, the specified value; otherwise, ’auto’.
  2974. left
  2975. Value: <length> | <percentage> | auto | inherit
  2976. Initial: auto
  2977. Applies to: positioned elements
  2978. Inherited: no
  2979. Percentages: refer to width of containing block
  2980. Computed value: if specified as a length, the corresponding absolute length; if
  2981. specified as a percentage, the specified value; otherwise, ’auto’.
  2982. float
  2983. Value: left | right | none | inherit
  2984. Initial: none
  2985. Applies to: all, but see 9.7 p. 153
  2986. Inherited: no
  2987. Percentages: N/A
  2988. Computed value: as specified
  2989. clear
  2990. Value: none | left | right | both | inherit
  2991. Initial: none
  2992. Applies to: block-level elements
  2993. Inherited: no
  2994. Percentages: N/A
  2995. Computed value: as specified
  2996. z-index
  2997. Value: auto | integer | inherit
  2998. Initial: auto
  2999. Applies to: positioned elements
  3000. Inherited: no
  3001. Percentages: N/A
  3002. Computed value: as spec
  3003. direction
  3004. Value: ltr | rtl | inherit
  3005. Initial: ltr
  3006. Applies to: all elements
  3007. Inherited: yes
  3008. Percentages: N/A
  3009. Computed value: as spec
  3010. unicode-bidi
  3011. Value: normal | embed | bidi-override | inherit
  3012. Initial: normal
  3013. Applies to: all elements, but see prose
  3014. Inherited: no
  3015. Percentages: N/A
  3016. Computed value: as spec
  3017. width
  3018. Value: <length> | <percentage> | auto | inherit
  3019. Initial: auto
  3020. Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  3021. Inherited: no
  3022. Percentages: refer to width of containing block
  3023. Computed value: the percentage or 'auto' as specified or the absolute length
  3024. min-width
  3025. Value: <length> | <percentage> | inherit
  3026. Initial: 0
  3027. Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  3028. Inherited: no
  3029. Percentages: refer to width of containing block
  3030. Computed value: the percentage as spec or the absolute length
  3031. max-width
  3032. Value: <length> | <percentage> | none | inherit
  3033. Initial: none
  3034. Applies to: all elements but non-replaced in-line elements, table rows, and row groups
  3035. Inherited: no
  3036. Percentages: refer to width of containing block
  3037. Computed value: the percentage as spec or the absolute length
  3038. height
  3039. Value: <length> | <percentage> | auto | inherit
  3040. Initial: auto
  3041. Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  3042. Inherited: no
  3043. Percentages: see prose
  3044. Computed value: the percentage as spec or the absolute length
  3045. min-height
  3046. Value: <length> | <percentage> | inherit
  3047. Initial: 0
  3048. Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  3049. Inherited: no
  3050. Percentages: see prose
  3051. Computed value: the percentage as spec or the absolute length
  3052. max-height
  3053. Value: <length> | <percentage> | none | inherit
  3054. Initial: none
  3055. Applies to: all elements but non-replaced in-line elements, table columns, and column groups
  3056. Inherited: no
  3057. Percentages: refer to height of containing block
  3058. Computed value: the percentage as spec or the absolute length
  3059. line-height
  3060. Value: normal | <number> | <length> | <percentage> | <inherit>
  3061. Initial: normal
  3062. Applies to: all elements
  3063. Inherited: yes
  3064. Percentages: refer to the font size of the element itself
  3065. Computed value: for <length> and <percentage> the absolute value, otherwise as specified.
  3066. vertical-align
  3067. Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom |
  3068. <percentage> | <length> | inherit
  3069. Initial: baseline
  3070. Applies to: inline-level and 'table-cell' elements
  3071. Inherited: no
  3072. Percentages: refer to the line height of the element itself
  3073. Computed value: for <length> and <percentage> the absolute length, otherwise as specified.
  3074. visibility
  3075. Value: visible | hidden | collapse | inherit
  3076. Initial: visible
  3077. Applies to: all elements
  3078. Inherited: yes
  3079. Percentages: N/A
  3080. Computed value: as spec
  3081. list-style-type
  3082. Value: disc | circle | square | decimal | decimal-leading-zero |
  3083. lower-roman | upper-roman | lower-greek | lower-latin |
  3084. upper-latin | armenian | georgian | lower-alpha | upper-alpha |
  3085. none | inherit
  3086. Initial: disc
  3087. Applies to: elements with display: list-item
  3088. Inherited: yes
  3089. Percentages: N/A
  3090. Computed value: as spec
  3091. list-style-image
  3092. Value: <uri> | none | inherit
  3093. Initial: none
  3094. Applies to: elements with ’display: list-item’
  3095. Inherited: yes
  3096. Percentages: N/A
  3097. Computed value: absolute URI or ’none’
  3098. list-style-position
  3099. Value: inside | outside | inherit
  3100. Initial: outside
  3101. Applies to: elements with ’display: list-item’
  3102. Inherited: yes
  3103. Percentages: N/A
  3104. Computed value: as spec
  3105. background-color
  3106. Value: <color> | transparent | inherit
  3107. Initial: transparent
  3108. Applies to: all elements
  3109. Inherited: no
  3110. Percentages: N/A
  3111. Computed value: as spec
  3112. font-family
  3113. Value: [[ <family-name> | <generic-family> ] [, <family-name>|
  3114. <generic-family>]* ] | inherit
  3115. Initial: depends on user agent
  3116. Applies to: all elements
  3117. Inherited: yes
  3118. Percentages: N/A
  3119. Computed value: as spec
  3120. font-style
  3121. Value: normal | italic | oblique | inherit
  3122. Initial: normal
  3123. Applies to: all elements
  3124. Inherited: yes
  3125. Percentages: N/A
  3126. Computed value: as spec
  3127. font-variant
  3128. Value: normal | small-caps | inherit
  3129. Initial: normal
  3130. Applies to: all elements
  3131. Inherited: yes
  3132. Percentages: N/A
  3133. Computed value: as spec
  3134. font-weight
  3135. Value: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 |
  3136. 600 | 700 | 800 | 900 | inherit
  3137. Initial: normal
  3138. Applies to: all elements
  3139. Inherited: yes
  3140. Percentages: N/A
  3141. Computed value: see text
  3142. font-size
  3143. Value: <absolute-size> | <relative-size> | <length> | <percentage> |
  3144. inherit
  3145. Initial: medium
  3146. Applies to: all elements
  3147. Inherited: yes
  3148. Percentages: refer to inherited font size
  3149. Computed value: absolute length
  3150. text-indent
  3151. Value: <length> | <percentage> | inherit
  3152. Initial: 0
  3153. Applies to: block containers
  3154. Inherited: yes
  3155. Percentages: refer to width of containing block
  3156. Computed value: the percentage as specified or the absolute length
  3157. text-align
  3158. Value: left | right | center | justify | inherit
  3159. Initial: a nameless value that acts as ’left’ if ’direction’ is ’ltr’, ’right’ if
  3160. ’direction’ is ’rtl’
  3161. Applies to: block containers
  3162. Inherited: yes
  3163. Percentages: N/A
  3164. Computed value: the initial value or as spec
  3165. text-decoration
  3166. Value: none | [ underline || overline || line-through || blink ] | inherit
  3167. Initial: none
  3168. Applies to: all elements
  3169. Inherited: no
  3170. Percentages: N/A
  3171. Computed value: as spec
  3172. letter-spacing
  3173. Value: normal | <length> | inherit
  3174. Initial: normal
  3175. Applies to: all elements
  3176. Inherited: yes
  3177. Percentages: N/A
  3178. Computed value: ’normal’ or absolute length
  3179. word-spacing
  3180. Value: normal | <length> | inherit
  3181. Initial: normal
  3182. Applies to: all elements
  3183. Inherited: yes
  3184. Percentages: N/A
  3185. Computed value: for ’normal’ the value 0; otherwise the absolute length
  3186. text-transform
  3187. Value: capitalize | uppercase | lowercase | none | inherit
  3188. Initial: none
  3189. Applies to: all elements
  3190. Inherited: yes
  3191. Percentages: N/A
  3192. Computed value: as spec
  3193. white-space
  3194. Value: normal | pre | nowrap | pre-wrap | pre-line | inherit
  3195. Initial: normal
  3196. Applies to: all elements
  3197. Inherited: yes
  3198. Percentages: N/A
  3199. Computed value: as spec
  3200. caption-side
  3201. Value: top | bottom | inherit
  3202. Initial: top
  3203. Applies to: 'table-caption' elements
  3204. Inherited: yes
  3205. Percentages: N/A
  3206. Computed value: as spec
  3207. table-layout
  3208. Value: auto | fixed | inherit
  3209. Initial: auto
  3210. Applies to: ’table’ and ’inline-table’ elements
  3211. Inherited: no
  3212. Percentages: N/A
  3213. Computed value: as spec
  3214. border-collapse
  3215. Value: collapse | separate | inherit
  3216. Initial: separate
  3217. Applies to: ’table’ and ’inline-table’ elements
  3218. Inherited: yes
  3219. Percentages: N/A
  3220. Computed value: as spec
  3221. border-spacing
  3222. Value: <length> <length>? | inherit
  3223. Initial: 0
  3224. Applies to: ’table’ and ’inline-table’ elements
  3225. Inherited: yes
  3226. Percentages: N/A
  3227. Computed value: two absolute lengths
  3228. empty-cells
  3229. Value: show | hide | inherit
  3230. Initial: show
  3231. Applies to: 'table-cell' elements
  3232. Inherited: yes
  3233. Percentages: N/A
  3234. Computed value: as spec
  3235. Shorthand Properties
  3236. margin
  3237. Value: <margin-width>{1,4} | inherit
  3238. Initial: see individual props
  3239. Applies to: all elements except elements with table display types other than table-caption, table, and inline-table
  3240. Inherited: no
  3241. Percentages: refer to width of containing block
  3242. Computed value: see individual props
  3243. set one - sets all four values
  3244. set two - first is top/bottom, second is right/left
  3245. set three - first is top, second is right/left, third is bottom
  3246. set four - top right bottom left
  3247. padding
  3248. Value: <padding-width>{1-4} | inherit
  3249. Initial: see individual props
  3250. Applies to: all elements except table-row-group, table-header-group,
  3251. table-footer-group, table-row, table-column-group and table-column
  3252. Inherited: no
  3253. Percentages: refer to width of containing block
  3254. Computed value: see individual props
  3255. set one - sets all four values
  3256. set two - first is top/bottom, second is right/left
  3257. set four - top right bottom left
  3258. border-width
  3259. Value: <border-width>{1-4} | inherit
  3260. Initial: see individual props
  3261. Applies to: all elements
  3262. Inherited: no
  3263. Percentages: N/A
  3264. Computed value: see individual props
  3265. set one - sets all four values
  3266. set two - first is top/bottom, second is right/left
  3267. set four - top right bottom left
  3268. border-color
  3269. Value: [<color> | transparent]{1-4} | inherit
  3270. Initial: see individual props
  3271. Applies to: all elements
  3272. Inherited: no
  3273. Percentages: N/A
  3274. Computed value: see individual props
  3275. set one - sets all four values
  3276. set two - first is top/bottom, second is right/left
  3277. set four - top right bottom left
  3278. border-style
  3279. Value: <border-style>{1-4} | inherit
  3280. Initial: see individual props
  3281. Applies to: all elements
  3282. Inherited: no
  3283. Percentages: N/A
  3284. Computed value: see individual props
  3285. set one - sets all four values
  3286. set two - first is top/bottom, second is right/left
  3287. set four - top right bottom left
  3288. border-top, border-right, border-bottom, border-left, border
  3289. Value: [<border-width> || <border-style> || <border-top-color>] | inherit
  3290. Initial: see individ
  3291. Applies to: all elements
  3292. Inherited: no
  3293. Percentages: N/A
  3294. Computed value: see individ
  3295. list-style
  3296. Value: [ <’list-style-type’> || <’list-style-position’> || <’list-style-image’>
  3297. ] | inherit
  3298. Initial: see individual props
  3299. Applies to: elements with ’display: list-item’
  3300. Inherited: yes
  3301. Percentages: N/A
  3302. Computed value: see individual props
  3303. background
  3304. Value: [<’background-color’> || <’background-image’> || <’background-
  3305. repeat’> || <’background-attachment’> || <’background-
  3306. position’>] | inherit
  3307. Initial: see individual props
  3308. Applies to: all elements
  3309. Inherited: no
  3310. Percentages: allowed on background-position
  3311. Computed value: see individual props
  3312. font
  3313. Value: [ [ <’font-style’> || <’font-variant’> || <’font-weight’> ]?
  3314. <’font-size’> [ / <’line-height’> ]? <’font-family’> ] | caption |
  3315. icon | menu | message-box | small-caption | status-bar |
  3316. inherit
  3317. Initial: see individual props
  3318. Applies to: all elements
  3319. Inherited: yes
  3320. Percentages: see individual props
  3321. Computed value: see individual props
  3322. probably not support
  3323. overflow
  3324. Value: visible | hidden | scroll | auto | inherit
  3325. Initial: visible
  3326. Applies to: block containers
  3327. Inherited: no
  3328. Percentages: N/A
  3329. Computed value: as spec
  3330. clip
  3331. Value: <shape> | auto | inherit
  3332. Initial: auto
  3333. Applies to: absolutely positioned elements
  3334. Inherited: no
  3335. Percentages: N/A
  3336. Computed value: auto if spec as 'auto', otherwise a rectangle with four values, each of which is
  3337. 'auto' if spec as 'auto' and the computed length otherwise
  3338. content
  3339. Value: normal | none | [ <string> | <uri> | <counter> | attr(<identifier>)
  3340. | open-quote | close-quote | no-open-quote | no-close-quote
  3341. ]+ | inherit
  3342. Initial: normal
  3343. Applies to: :before and :after pseudo elements
  3344. Inherited: no
  3345. Percentages: N/A
  3346. Computed value: On elements, always computes to ’normal’. On :before and
  3347. :after, if ’normal’ is specified, computes to ’none’. Otherwise,
  3348. for URI values, the absolute URI; for attr() values, the resulting
  3349. string; for other keywords, as specified.
  3350. quotes
  3351. Value: [<string> <string>]+ | none | inherit
  3352. Initial: depends on user agent
  3353. Applies to: all elements
  3354. Inherited: yes
  3355. Percentages: N/A
  3356. Computed value: as spec
  3357. counter-reset
  3358. Value: [ <identifier> <integer>? ]+ | none | inherit
  3359. Initial: none
  3360. Applies to: all elements
  3361. Inherited: no
  3362. Percentages: N/A
  3363. Computed value: as spec
  3364. counter-increment
  3365. Value: [ <identifier> <integer>? ]+ | none | inherit
  3366. Initial: none
  3367. Applies to: all elements
  3368. Inherited: no
  3369. Percentages: N/A
  3370. Computed value: as spec
  3371. background-image
  3372. Value: <uri> | none | inherit
  3373. Initial: none
  3374. Applies to: all elements
  3375. Inherited: no
  3376. Percentages: N/A
  3377. Computed value: absolute URI or none
  3378. background-repeat
  3379. Value: repeat | repeat-x | repeat-y | no-repeat | inherit
  3380. Initial: repeat
  3381. Applies to: all elements
  3382. Inherited: no
  3383. Percentages: N/A
  3384. Computed value: as spec
  3385. background-attachment
  3386. Value: scroll | fixed | inherit
  3387. Initial: scroll
  3388. Applies to: all elements
  3389. Inherited: no
  3390. Percentages: N/A
  3391. Computed value: as spec
  3392. background-position
  3393. Value: [ [ <percentage> | <length> | left | center | right ] [ <percentage>
  3394. | <length> | top | center | bottom ]? ] | [ [ left | center |
  3395. right ] || [ top | center | bottom ] ] | inherit
  3396. Initial: 0% 0%
  3397. Applies to: all elements
  3398. Inherited: no
  3399. Percentages: refer to the size of the box itself
  3400. Computed value: for <length> the absolute value, otherwise a percentage
  3401. #endif
  3402. #if false
  3403. background-color
  3404. border-bottom-color
  3405. border-bottom-style
  3406. border-bottom-width
  3407. border-collapse
  3408. border-left-color
  3409. border-left-style
  3410. border-left-width
  3411. border-right-color
  3412. border-right-style
  3413. border-right-width
  3414. border-spacing
  3415. border-top-color
  3416. border-top-style
  3417. border-top-width
  3418. bottom
  3419. caption-side
  3420. clear
  3421. color
  3422. direction
  3423. display
  3424. empty-cells
  3425. float
  3426. font-family
  3427. font-size
  3428. font-style
  3429. font-variant
  3430. font-weight
  3431. height
  3432. left
  3433. letter-spacing
  3434. line-height
  3435. list-style-image
  3436. list-style-position
  3437. list-style-type
  3438. margin-bottom
  3439. margin-left
  3440. margin-right
  3441. margin-top
  3442. max-height
  3443. max-width
  3444. min-height
  3445. min-width
  3446. padding-bottom
  3447. padding-left
  3448. padding-right
  3449. padding-top
  3450. position
  3451. right
  3452. table-layout
  3453. text-align
  3454. text-decoration
  3455. text-indent
  3456. text-transform
  3457. top
  3458. unicode-bidi
  3459. vertical-align
  3460. visibility
  3461. white-space
  3462. width
  3463. word-spacing
  3464. z-index
  3465. attributes
  3466. ==========
  3467. meta
  3468. style
  3469. _class
  3470. href
  3471. don't know
  3472. ==========
  3473. colspan
  3474. caption
  3475. title
  3476. hr
  3477. border
  3478. http_equiv
  3479. content
  3480. name
  3481. width
  3482. height
  3483. src
  3484. alt
  3485. id
  3486. descr
  3487. type
  3488. elements
  3489. ========
  3490. html
  3491. head
  3492. body
  3493. div
  3494. p
  3495. h1
  3496. h2
  3497. h3
  3498. h4
  3499. h5
  3500. h6
  3501. h7
  3502. h8
  3503. h9
  3504. a
  3505. b
  3506. table
  3507. tr
  3508. td
  3509. br
  3510. img
  3511. span
  3512. blockquote
  3513. sub
  3514. sup
  3515. ol
  3516. ul
  3517. li
  3518. strong
  3519. em
  3520. tbody
  3521. #endif