org-e-odt.el 155 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445
  1. ;;; org-e-odt.el --- OpenDocument Text exporter for Org-mode
  2. ;; Copyright (C) 2010-2012 Free Software Foundation, Inc.
  3. ;; Author: Jambunathan K <kjambunathan at gmail dot com>
  4. ;; Keywords: outlines, hypermedia, calendar, wp
  5. ;; Homepage: http://orgmode.org
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;; Code:
  19. (eval-when-compile
  20. (require 'cl))
  21. (defgroup org-export-e-odt nil
  22. "Options specific for ODT export of Org-mode files."
  23. :tag "Org Export ODT"
  24. :group 'org-export
  25. :version "24.1")
  26. ;; FIXMES
  27. ;; org-export-preprocess-after-blockquote-hook
  28. ;; org-e-odt-preprocess-latex-fragments
  29. ;; org-export-as-e-odt-and-open
  30. ;; org-export-as-e-odt-batch
  31. ;; org-export-as-e-odt
  32. (defun org-e-odt-get-style-name-for-entity (category &optional entity)
  33. (let ((entity (or entity 'default)))
  34. (or
  35. (cdr (assoc entity (cdr (assoc category
  36. org-e-odt-org-styles-alist))))
  37. (cdr (assoc entity (cdr (assoc category
  38. org-e-odt-default-org-styles-alist))))
  39. (error "Cannot determine style name for entity %s of type %s"
  40. entity category))))
  41. ;; Following variable is let bound when `org-do-lparse' is in
  42. ;; progress. See org-html.el.
  43. (defun org-e-odt-format-preamble (info)
  44. (let* ((title (org-export-secondary-string
  45. (plist-get info :title) 'e-odt info))
  46. (author (and (plist-get info :with-author)
  47. (let ((auth (plist-get info :author)))
  48. (and auth (org-export-secondary-string
  49. auth 'e-odt info)))))
  50. (date (plist-get info :date))
  51. (iso-date (org-e-odt-format-date date))
  52. (date (org-e-odt-format-date date "%d %b %Y"))
  53. (email (plist-get info :email))
  54. ;; switch on or off above vars based on user settings
  55. (author (and (plist-get info :with-author) (or author email)))
  56. ;; (date (and (plist-get info :time-stamp-file) date))
  57. (email (and (plist-get info :with-email) email)))
  58. (concat
  59. ;; title
  60. (when title
  61. (concat
  62. (org-e-odt-format-stylized-paragraph
  63. 'title (format "\n<text:title>%s</text:title>" title))
  64. ;; separator
  65. "\n<text:p text:style-name=\"OrgTitle\"/>"))
  66. (cond
  67. ((and author (not email))
  68. ;; author only
  69. (concat
  70. (org-e-odt-format-stylized-paragraph
  71. 'subtitle
  72. (format "<text:initial-creator>%s</text:initial-creator>" author))
  73. ;; separator
  74. "\n<text:p text:style-name=\"OrgSubtitle\"/>"))
  75. ((and author email)
  76. ;; author and email
  77. (concat
  78. (org-e-odt-format-stylized-paragraph
  79. 'subtitle
  80. (org-e-odt-format-link
  81. (format "<text:initial-creator>%s</text:initial-creator>" author)
  82. (concat "mailto:" email)))
  83. ;; separator
  84. "\n<text:p text:style-name=\"OrgSubtitle\"/>")))
  85. ;; date
  86. (when date
  87. (concat
  88. (org-e-odt-format-stylized-paragraph
  89. 'subtitle
  90. (org-odt-format-tags
  91. '("<text:date style:data-style-name=\"%s\" text:date-value=\"%s\">"
  92. . "</text:date>")
  93. date "N75" iso-date))
  94. ;; separator
  95. "<text:p text:style-name=\"OrgSubtitle\"/>")))))
  96. (defun org-e-odt-begin-section (style &optional name)
  97. (let ((default-name (car (org-e-odt-add-automatic-style "Section"))))
  98. (format "<text:section text:style-name=\"%s\" text:name=\"%s\">"
  99. style (or name default-name))))
  100. (defun org-e-odt-end-section ()
  101. "</text:section>")
  102. (defun org-e-odt-begin-paragraph (&optional style)
  103. (format "<text:p%s>" (org-e-odt-get-extra-attrs-for-paragraph-style style)))
  104. (defun org-e-odt-end-paragraph ()
  105. "</text:p>")
  106. (defun org-e-odt-get-extra-attrs-for-paragraph-style (style)
  107. (let (style-name)
  108. (setq style-name
  109. (cond
  110. ((stringp style) style)
  111. ((symbolp style) (org-e-odt-get-style-name-for-entity
  112. 'paragraph style))))
  113. (unless style-name
  114. (error "Don't know how to handle paragraph style %s" style))
  115. (format " text:style-name=\"%s\"" style-name)))
  116. (defun org-e-odt-format-stylized-paragraph (style text)
  117. (format "\n<text:p%s>%s</text:p>"
  118. (org-e-odt-get-extra-attrs-for-paragraph-style style)
  119. text))
  120. (defun org-e-odt-format-author (&optional author )
  121. (when (setq author (or author (plist-get org-lparse-opt-plist :author)))
  122. (format "<dc:creator>%s</dc:creator>" author)))
  123. (defun org-e-odt-format-date (&optional org-ts fmt)
  124. (save-match-data
  125. (let* ((time
  126. (and (stringp org-ts)
  127. (string-match org-ts-regexp0 org-ts)
  128. (apply 'encode-time
  129. (org-fix-decoded-time
  130. (org-parse-time-string (match-string 0 org-ts) t)))))
  131. date)
  132. (cond
  133. (fmt (format-time-string fmt time))
  134. (t (setq date (format-time-string "%Y-%m-%dT%H:%M:%S%z" time))
  135. (format "%s:%s" (substring date 0 -2) (substring date -2)))))))
  136. (defun org-e-odt-begin-annotation (&optional author date)
  137. (concat
  138. "<office:annotation>\n"
  139. (and author (org-e-odt-format-author author))
  140. (org-e-odt-format-tags
  141. '("<dc:date>" . "</dc:date>")
  142. (org-e-odt-format-date
  143. (or date (plist-get org-lparse-opt-plist :date))))
  144. (org-e-odt-begin-paragraph)))
  145. (defun org-e-odt-end-annotation ()
  146. "</office:annotation>")
  147. (defun org-e-odt-begin-plain-list (ltype)
  148. (let* ((style-name (org-e-odt-get-style-name-for-entity 'list ltype))
  149. (extra (concat
  150. ;; (if (or org-lparse-list-table-p
  151. ;; (and (= 1 (length org-lparse-list-stack))
  152. ;; (null org-e-odt-list-stack-stashed)))
  153. ;; " text:continue-numbering=\"false\""
  154. ;; " text:continue-numbering=\"true\"")
  155. " text:continue-numbering=\"true\""
  156. (when style-name
  157. (format " text:style-name=\"%s\"" style-name)))))
  158. (case ltype
  159. ((ordered unordered descriptive)
  160. (concat
  161. ;; (org-e-odt-end-paragraph)
  162. (format "<text:list%s>" extra)))
  163. (t (error "Unknown list type: %s" ltype)))))
  164. (defun org-e-odt-end-plain-list (ltype)
  165. (if ltype "</text:list>"
  166. (error "Unknown list type: %s" ltype)))
  167. (defun org-e-odt-begin-list-item (ltype &optional arg headline)
  168. (case ltype
  169. (ordered
  170. (assert (not headline) t)
  171. (let* ((counter arg) (extra ""))
  172. (concat "<text:list-item>" ;; (org-e-odt-begin-paragraph)
  173. )
  174. ;; (if (= (length org-lparse-list-stack)
  175. ;; (length org-e-odt-list-stack-stashed))
  176. ;; "<text:list-header>" "<text:list-item>")
  177. ))
  178. (unordered
  179. (let* ((id arg) (extra ""))
  180. (concat
  181. "<text:list-item>"
  182. ;; (org-e-odt-begin-paragraph)
  183. (if headline (org-e-odt-format-target headline id)
  184. (org-e-odt-format-bookmark "" id)))
  185. ;; (if (= (length org-lparse-list-stack)
  186. ;; (length org-e-odt-list-stack-stashed))
  187. ;; "<text:list-header>" "<text:list-item>")
  188. ))
  189. (descriptive
  190. (assert (not headline) t)
  191. (let ((term (or arg "(no term)")))
  192. (concat
  193. (org-e-odt-format-tags
  194. '("<text:list-item>" . "</text:list-item>")
  195. (org-e-odt-format-stylized-paragraph 'definition-term term))
  196. (org-e-odt-begin-list-item 'unordered)
  197. (org-e-odt-begin-plain-list 'descriptive)
  198. (org-e-odt-begin-list-item 'unordered))))
  199. (t (error "Unknown list type"))))
  200. (defun org-e-odt-end-list-item (ltype)
  201. (case ltype
  202. ((ordered unordered)
  203. ;; (org-lparse-insert-tag
  204. ;; (if (= (length org-lparse-list-stack)
  205. ;; (length org-e-odt-list-stack-stashed))
  206. ;; (prog1 "</text:list-header>"
  207. ;; (setq org-e-odt-list-stack-stashed nil))
  208. ;; "</text:list-item>")
  209. "</text:list-item>"
  210. ;; )
  211. )
  212. (descriptive
  213. (concat
  214. (org-e-odt-end-list-item 'unordered)
  215. (org-e-odt-end-plain-list 'descriptive)
  216. (org-e-odt-end-list-item 'unordered)
  217. ))
  218. (t (error "Unknown list type"))))
  219. (defun org-e-odt-discontinue-list ()
  220. (let ((stashed-stack org-lparse-list-stack))
  221. (loop for list-type in stashed-stack
  222. do (org-lparse-end-list-item-1 list-type)
  223. (org-lparse-end-list list-type))
  224. (setq org-e-odt-list-stack-stashed stashed-stack)))
  225. (defun org-e-odt-continue-list ()
  226. (setq org-e-odt-list-stack-stashed (nreverse org-e-odt-list-stack-stashed))
  227. (loop for list-type in org-e-odt-list-stack-stashed
  228. do (org-lparse-begin-list list-type)
  229. (org-lparse-begin-list-item list-type)))
  230. (defun org-e-odt-write-automatic-styles ()
  231. "Write automatic styles to \"content.xml\"."
  232. (with-current-buffer
  233. (find-file-noselect (expand-file-name "content.xml") t)
  234. ;; position the cursor
  235. (goto-char (point-min))
  236. (re-search-forward " </office:automatic-styles>" nil t)
  237. (goto-char (match-beginning 0))
  238. ;; write automatic table styles
  239. (loop for (style-name props) in
  240. (plist-get org-e-odt-automatic-styles 'Table) do
  241. (when (setq props (or (plist-get props :rel-width) 96))
  242. (insert (format org-e-odt-table-style-format style-name props))))))
  243. (defun org-e-odt-add-automatic-style (object-type &optional object-props)
  244. "Create an automatic style of type OBJECT-TYPE with param OBJECT-PROPS.
  245. OBJECT-PROPS is (typically) a plist created by passing
  246. \"#+ATTR_ODT: \" option of the object in question to
  247. `org-e-odt-parse-block-attributes'.
  248. Use `org-e-odt-object-counters' to generate an automatic
  249. OBJECT-NAME and STYLE-NAME. If OBJECT-PROPS is non-nil, add a
  250. new entry in `org-e-odt-automatic-styles'. Return (OBJECT-NAME
  251. . STYLE-NAME)."
  252. (assert (stringp object-type))
  253. (let* ((object (intern object-type))
  254. (seqvar object)
  255. (seqno (1+ (or (plist-get org-e-odt-object-counters seqvar) 0)))
  256. (object-name (format "%s%d" object-type seqno)) style-name)
  257. (setq org-e-odt-object-counters
  258. (plist-put org-e-odt-object-counters seqvar seqno))
  259. (when object-props
  260. (setq style-name (format "Org%s" object-name))
  261. (setq org-e-odt-automatic-styles
  262. (plist-put org-e-odt-automatic-styles object
  263. (append (list (list style-name object-props))
  264. (plist-get org-e-odt-automatic-styles object)))))
  265. (cons object-name style-name)))
  266. (defun org-e-odt-format-table-columns ()
  267. (let* ((num-cols (length (plist-get table-info :alignment)))
  268. (col-nos (loop for i from 0 below num-cols collect i))
  269. (levels )
  270. (col-widths (plist-get table-info :width))
  271. (style (or (nth 1 org-e-odt-table-style-spec) "OrgTable")))
  272. (mapconcat
  273. (lambda (c)
  274. (let* ((width (or (and org-lparse-table-is-styled (aref col-widths c))
  275. 0)))
  276. (org-e-odt-make-string
  277. (1+ width)
  278. (org-e-odt-format-tags
  279. "<table:table-column table:style-name=\"%sColumn\"/>" "" style))))
  280. col-nos "\n")))
  281. (defun org-e-odt-begin-table (caption label attributes)
  282. ;; (setq org-e-odt-table-indentedp (not (null org-lparse-list-stack)))
  283. (setq org-e-odt-table-indentedp nil) ; FIXME
  284. (when org-e-odt-table-indentedp
  285. ;; Within the Org file, the table is appearing within a list item.
  286. ;; OpenDocument doesn't allow table to appear within list items.
  287. ;; Temporarily terminate the list, emit the table and then
  288. ;; re-continue the list.
  289. (org-e-odt-discontinue-list)
  290. ;; Put the Table in an indented section.
  291. (let ((level (length org-e-odt-list-stack-stashed)))
  292. (org-e-odt-begin-section (format "OrgIndentedSection-Level-%d" level))))
  293. (setq attributes (org-e-odt-parse-block-attributes attributes))
  294. (setq org-e-odt-table-style (plist-get attributes :style))
  295. (setq org-e-odt-table-style-spec
  296. (assoc org-e-odt-table-style org-e-odt-table-styles))
  297. (concat
  298. (org-e-odt-format-stylized-paragraph
  299. 'table (org-e-odt-format-entity-caption label caption "__Table__"))
  300. (let ((name-and-style (org-e-odt-add-automatic-style "Table" attributes)))
  301. (format
  302. "\n<table:table table:name=\"%s\" table:style-name=\"%s\">\n"
  303. (car name-and-style) (or (nth 1 org-e-odt-table-style-spec)
  304. (cdr name-and-style) "OrgTable")))
  305. (org-e-odt-format-table-columns) "\n")
  306. ;; (org-e-html-pp table-info)
  307. )
  308. (defun org-e-odt-end-table ()
  309. (concat
  310. "</table:table>"
  311. ;; (when org-e-odt-table-indentedp
  312. ;; (org-e-odt-end-section)
  313. ;; (org-e-odt-continue-list))
  314. ))
  315. (defun org-e-odt-begin-table-rowgroup (&optional is-header-row)
  316. (prog1
  317. (concat (when org-e-odt-table-rowgrp-open
  318. (org-e-odt-end-table-rowgroup))
  319. (if is-header-row "<table:table-header-rows>"
  320. "<table:table-rows>"))
  321. (setq org-e-odt-table-rowgrp-open t)
  322. (setq org-e-odt-table-cur-rowgrp-is-hdr is-header-row)))
  323. (defun org-e-odt-end-table-rowgroup ()
  324. (when org-e-odt-table-rowgrp-open
  325. (setq org-e-odt-table-rowgrp-open nil)
  326. (if org-e-odt-table-cur-rowgrp-is-hdr
  327. "</table:table-header-rows>" "</table:table-rows>")))
  328. (defun org-e-odt-format-table-row (row)
  329. (org-e-odt-format-tags
  330. '("<table:table-row>" . "</table:table-row>") row))
  331. (defun org-e-odt-get-column-alignment (c)
  332. (let ((colalign-vector (plist-get table-info :alignment)))
  333. ;; FIXME
  334. (assoc-default (aref colalign-vector c)
  335. '(("l" . "left")
  336. ("r" . "right")
  337. ("c" . "center")))))
  338. (defun org-e-odt-get-table-cell-styles (r c &optional style-spec)
  339. "Retrieve styles applicable to a table cell.
  340. R and C are (zero-based) row and column numbers of the table
  341. cell. STYLE-SPEC is an entry in `org-e-odt-table-styles'
  342. applicable to the current table. It is `nil' if the table is not
  343. associated with any style attributes.
  344. Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME).
  345. When STYLE-SPEC is nil, style the table cell the conventional way
  346. - choose cell borders based on row and column groupings and
  347. choose paragraph alignment based on `org-col-cookies' text
  348. property. See also
  349. `org-e-odt-get-paragraph-style-cookie-for-table-cell'.
  350. When STYLE-SPEC is non-nil, ignore the above cookie and return
  351. styles congruent with the ODF-1.2 specification."
  352. (cond
  353. (style-spec
  354. ;; LibreOffice - particularly the Writer - honors neither table
  355. ;; templates nor custom table-cell styles. Inorder to retain
  356. ;; inter-operability with LibreOffice, only automatic styles are
  357. ;; used for styling of table-cells. The current implementation is
  358. ;; congruent with ODF-1.2 specification and hence is
  359. ;; future-compatible.
  360. ;; Additional Note: LibreOffice's AutoFormat facility for tables -
  361. ;; which recognizes as many as 16 different cell types - is much
  362. ;; richer. Unfortunately it is NOT amenable to easy configuration
  363. ;; by hand.
  364. (let* ((template-name (nth 1 style-spec))
  365. (cell-style-selectors (nth 2 style-spec))
  366. (cell-type
  367. (cond
  368. ((and (cdr (assoc 'use-first-column-styles cell-style-selectors))
  369. (= c 0)) "FirstColumn")
  370. ((and (cdr (assoc 'use-last-column-styles cell-style-selectors))
  371. (= c (1- org-lparse-table-ncols))) "LastColumn")
  372. ((and (cdr (assoc 'use-first-row-styles cell-style-selectors))
  373. (= r 0)) "FirstRow")
  374. ((and (cdr (assoc 'use-last-row-styles cell-style-selectors))
  375. (= r org-e-odt-table-rownum))
  376. "LastRow")
  377. ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors))
  378. (= (% r 2) 1)) "EvenRow")
  379. ((and (cdr (assoc 'use-banding-rows-styles cell-style-selectors))
  380. (= (% r 2) 0)) "OddRow")
  381. ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors))
  382. (= (% c 2) 1)) "EvenColumn")
  383. ((and (cdr (assoc 'use-banding-columns-styles cell-style-selectors))
  384. (= (% c 2) 0)) "OddColumn")
  385. (t ""))))
  386. (cons
  387. (concat template-name cell-type "TableCell")
  388. (concat template-name cell-type "TableParagraph"))))
  389. (t
  390. (cons
  391. (concat
  392. "OrgTblCell"
  393. (cond
  394. ((= r 0) "T")
  395. ((eq (cdr (assoc r nil ;; org-lparse-table-rowgrp-info FIXME
  396. )) :start) "T")
  397. (t ""))
  398. (when (= r org-e-odt-table-rownum) "B")
  399. (cond
  400. ((= c 0) "")
  401. ((or (memq (nth c org-table-colgroup-info) '(:start :startend))
  402. (memq (nth (1- c) org-table-colgroup-info) '(:end :startend))) "L")
  403. (t "")))
  404. (capitalize (org-e-odt-get-column-alignment c))))))
  405. (defun org-e-odt-get-paragraph-style-cookie-for-table-cell (r c)
  406. (concat
  407. (and (not org-e-odt-table-style-spec)
  408. (cond
  409. (org-e-odt-table-cur-rowgrp-is-hdr "OrgTableHeading")
  410. ((and (= c 0) nil
  411. ;; (org-lparse-get 'TABLE-FIRST-COLUMN-AS-LABELS)
  412. )
  413. "OrgTableHeading")
  414. (t "OrgTableContents")))
  415. (and org-lparse-table-is-styled
  416. (cdr (org-e-odt-get-table-cell-styles
  417. r c org-e-odt-table-style-spec)))))
  418. (defun org-e-odt-get-style-name-cookie-for-table-cell (r c)
  419. (when org-lparse-table-is-styled
  420. (let* ((cell-styles (org-e-odt-get-table-cell-styles
  421. r c org-e-odt-table-style-spec))
  422. (table-cell-style (car cell-styles)))
  423. table-cell-style)))
  424. (defun org-e-odt-format-table-cell (data r c horiz-span)
  425. (concat
  426. (let* ((paragraph-style-cookie
  427. (org-e-odt-get-paragraph-style-cookie-for-table-cell r c))
  428. (style-name-cookie
  429. (org-e-odt-get-style-name-cookie-for-table-cell r c))
  430. (extra (and style-name-cookie
  431. (format " table:style-name=\"%s\"" style-name-cookie)))
  432. (extra (concat extra
  433. (and (> horiz-span 0)
  434. (format " table:number-columns-spanned=\"%d\""
  435. (1+ horiz-span))))))
  436. (org-e-odt-format-tags
  437. '("<table:table-cell%s>" . "</table:table-cell>")
  438. (if org-lparse-list-table-p data
  439. (org-e-odt-format-stylized-paragraph paragraph-style-cookie data)) extra))
  440. (let (s)
  441. (dotimes (i horiz-span)
  442. (setq s (concat s "\n<table:covered-table-cell/>"))) s)
  443. "\n"))
  444. (defun org-e-odt-begin-toc (lang-specific-heading max-level)
  445. (concat
  446. (format "
  447. <text:table-of-content text:style-name=\"Sect2\" text:protected=\"true\" text:name=\"Table of Contents1\">
  448. <text:table-of-content-source text:outline-level=\"%d\">
  449. <text:index-title-template text:style-name=\"Contents_20_Heading\">%s</text:index-title-template>
  450. " max-level lang-specific-heading)
  451. (let ((entry-templates ""))
  452. (loop for level from 1 upto 10
  453. do (setq entry-templates
  454. (concat entry-templates
  455. (format
  456. "
  457. <text:table-of-content-entry-template text:outline-level=\"%d\" text:style-name=\"Contents_20_%d\">
  458. <text:index-entry-link-start text:style-name=\"Internet_20_link\"/>
  459. <text:index-entry-chapter/>
  460. <text:index-entry-text/>
  461. <text:index-entry-link-end/>
  462. </text:table-of-content-entry-template>
  463. " level level))))
  464. entry-templates)
  465. (format "
  466. </text:table-of-content-source>
  467. <text:index-body>
  468. <text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">
  469. <text:p text:style-name=\"Contents_20_Heading\">%s</text:p>
  470. </text:index-title>
  471. " lang-specific-heading)))
  472. (defun org-e-odt-end-toc ()
  473. (format "
  474. </text:index-body>
  475. </text:table-of-content>
  476. "))
  477. (defun org-e-odt-format-toc-entry (snumber todo headline tags href)
  478. ;; FIXME
  479. (setq headline (concat
  480. (and org-export-with-section-numbers
  481. (concat snumber ". "))
  482. headline
  483. (and tags
  484. (concat
  485. (org-e-odt-format-spaces 3)
  486. (org-e-odt-format-fontify tags "tag")))))
  487. (when todo
  488. (setq headline (org-e-odt-format-fontify headline "todo")))
  489. (let ((org-e-odt-suppress-xref t))
  490. (org-e-odt-format-link headline (concat "#" href))))
  491. (defun org-e-odt-format-toc-item (toc-entry level org-last-level)
  492. (let ((style (format "Contents_20_%d"
  493. (+ level (or ;; (org-lparse-get 'TOPLEVEL-HLEVEL)
  494. 1
  495. 1) -1))))
  496. (concat "\n" (org-e-odt-format-stylized-paragraph style toc-entry) "\n")))
  497. ;; Following variable is let bound during 'ORG-LINK callback. See
  498. ;; org-html.el
  499. (defun org-e-odt-format-link (desc href &optional attr)
  500. (cond
  501. ((and (= (string-to-char href) ?#) (not org-e-odt-suppress-xref))
  502. (setq href (substring href 1))
  503. (let ((xref-format "text"))
  504. (when (numberp desc)
  505. (setq desc (format "%d" desc) xref-format "number"))
  506. (when (listp desc)
  507. (setq desc (mapconcat 'identity desc ".") xref-format "chapter"))
  508. (setq href (concat org-e-odt-bookmark-prefix href))
  509. (org-e-odt-format-tags-simple
  510. '("<text:bookmark-ref text:reference-format=\"%s\" text:ref-name=\"%s\">" .
  511. "</text:bookmark-ref>")
  512. desc xref-format href)))
  513. (org-lparse-link-description-is-image
  514. (org-e-odt-format-tags
  515. '("<draw:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" . "</draw:a>")
  516. desc href (or attr "")))
  517. (t
  518. (org-e-odt-format-tags-simple
  519. '("<text:a xlink:type=\"simple\" xlink:href=\"%s\" %s>" . "</text:a>")
  520. desc href (or attr "")))))
  521. (defun org-e-odt-format-spaces (n)
  522. (cond
  523. ((= n 1) " ")
  524. ((> n 1) (concat
  525. " " (org-e-odt-format-tags "<text:s text:c=\"%d\"/>" "" (1- n))))
  526. (t "")))
  527. (defun org-e-odt-format-tabs (&optional n)
  528. (let ((tab "<text:tab/>")
  529. (n (or n 1)))
  530. (insert tab)))
  531. (defun org-e-odt-format-line-break ()
  532. (org-e-odt-format-tags "<text:line-break/>" ""))
  533. (defun org-e-odt-format-horizontal-line ()
  534. (org-e-odt-format-stylized-paragraph 'horizontal-line ""))
  535. (defun org-e-odt-encode-plain-text (line &optional no-whitespace-filling)
  536. (setq line (org-e-html-encode-plain-text line))
  537. (if no-whitespace-filling line
  538. (org-e-odt-fill-tabs-and-spaces line)))
  539. (defun org-e-odt-format-line (line)
  540. (case org-lparse-dyn-current-environment
  541. (fixedwidth (concat
  542. (org-e-odt-format-stylized-paragraph
  543. 'fixedwidth (org-e-odt-encode-plain-text line)) "\n"))
  544. (t (concat line "\n"))))
  545. (defun org-e-odt-format-comment (fmt &rest args)
  546. (let ((comment (apply 'format fmt args)))
  547. (format "\n<!-- %s -->\n" comment)))
  548. (defun org-e-odt-format-org-entity (wd)
  549. (org-entity-get-representation wd 'utf8))
  550. (defun org-e-odt-fill-tabs-and-spaces (line)
  551. (replace-regexp-in-string
  552. "\\([\t]\\|\\([ ]+\\)\\)" (lambda (s)
  553. (cond
  554. ((string= s "\t") (org-e-odt-format-tabs))
  555. (t (org-e-odt-format-spaces (length s))))) line))
  556. (defun org-e-odt-hfy-face-to-css (fn)
  557. "Create custom style for face FN.
  558. When FN is the default face, use it's foreground and background
  559. properties to create \"OrgSrcBlock\" paragraph style. Otherwise
  560. use it's color attribute to create a character style whose name
  561. is obtained from FN. Currently all attributes of FN other than
  562. color are ignored.
  563. The style name for a face FN is derived using the following
  564. operations on the face name in that order - de-dash, CamelCase
  565. and prefix with \"OrgSrc\". For example,
  566. `font-lock-function-name-face' is associated with
  567. \"OrgSrcFontLockFunctionNameFace\"."
  568. (let* ((css-list (hfy-face-to-style fn))
  569. (style-name ((lambda (fn)
  570. (concat "OrgSrc"
  571. (mapconcat
  572. 'capitalize (split-string
  573. (hfy-face-or-def-to-name fn) "-")
  574. ""))) fn))
  575. (color-val (cdr (assoc "color" css-list)))
  576. (background-color-val (cdr (assoc "background" css-list)))
  577. (style (and org-e-odt-create-custom-styles-for-srcblocks
  578. (cond
  579. ((eq fn 'default)
  580. (format org-src-block-paragraph-format
  581. background-color-val color-val))
  582. (t
  583. (format
  584. "
  585. <style:style style:name=\"%s\" style:family=\"text\">
  586. <style:text-properties fo:color=\"%s\"/>
  587. </style:style>" style-name color-val))))))
  588. (cons style-name style)))
  589. (defun org-e-odt-insert-custom-styles-for-srcblocks (styles)
  590. "Save STYLES used for colorizing of source blocks.
  591. Update styles.xml with styles that were collected as part of
  592. `org-e-odt-hfy-face-to-css' callbacks."
  593. (when styles
  594. (with-current-buffer
  595. (find-file-noselect (expand-file-name "styles.xml") t)
  596. (goto-char (point-min))
  597. (when (re-search-forward "</office:styles>" nil t)
  598. (goto-char (match-beginning 0))
  599. (insert "\n<!-- Org Htmlfontify Styles -->\n" styles "\n")))))
  600. (defun org-e-odt-remap-stylenames (style-name)
  601. (or
  602. (cdr (assoc style-name '(("timestamp-wrapper" . "OrgTimestampWrapper")
  603. ("timestamp" . "OrgTimestamp")
  604. ("timestamp-kwd" . "OrgTimestampKeyword")
  605. ("tag" . "OrgTag")
  606. ("todo" . "OrgTodo")
  607. ("done" . "OrgDone")
  608. ("target" . "OrgTarget"))))
  609. style-name))
  610. (defun org-e-odt-format-fontify (text style &optional id)
  611. (let* ((style-name
  612. (cond
  613. ((stringp style)
  614. (org-e-odt-remap-stylenames style))
  615. ((symbolp style)
  616. (org-e-odt-get-style-name-for-entity 'character style))
  617. ((listp style)
  618. (assert (< 1 (length style)))
  619. (let ((parent-style (pop style)))
  620. (mapconcat (lambda (s)
  621. ;; (assert (stringp s) t)
  622. (org-e-odt-remap-stylenames s)) style "")
  623. (org-e-odt-remap-stylenames parent-style)))
  624. (t (error "Don't how to handle style %s" style)))))
  625. (org-e-odt-format-tags
  626. '("<text:span text:style-name=\"%s\">" . "</text:span>")
  627. text style-name)))
  628. (defun org-e-odt-relocate-relative-path (path dir)
  629. (if (file-name-absolute-p path) path
  630. (file-relative-name (expand-file-name path dir)
  631. (expand-file-name "eyecandy" dir))))
  632. (defun org-e-odt-format-formula (src href)
  633. (save-match-data
  634. (let* ((caption (org-find-text-property-in-string 'org-caption src))
  635. (caption (and caption (org-xml-format-desc caption)))
  636. (label (org-find-text-property-in-string 'org-label src))
  637. (latex-frag (org-find-text-property-in-string 'org-latex-src src))
  638. (embed-as (or (and latex-frag
  639. (org-find-text-property-in-string
  640. 'org-latex-src-embed-type src))
  641. (if (or caption label) 'paragraph 'character)))
  642. width height)
  643. (when latex-frag
  644. (setq href (org-propertize href :title "LaTeX Fragment"
  645. :description latex-frag)))
  646. (cond
  647. ((eq embed-as 'character)
  648. (org-e-odt-format-entity "InlineFormula" href width height))
  649. (t
  650. (org-lparse-end-paragraph)
  651. (org-lparse-insert-list-table
  652. `((,(org-e-odt-format-entity
  653. (if caption "CaptionedDisplayFormula" "DisplayFormula")
  654. href width height :caption caption :label nil)
  655. ,(if (not label) ""
  656. (org-e-odt-format-entity-caption label nil "__MathFormula__"))))
  657. nil nil nil ":style \"OrgEquation\"" nil '((1 "c" 8) (2 "c" 1)))
  658. (throw 'nextline nil))))))
  659. (defun org-e-odt-copy-formula-file (path)
  660. "Returns the internal name of the file"
  661. (let* ((src-file (expand-file-name
  662. path (file-name-directory org-current-export-file)))
  663. (target-dir (format "Formula-%04d/"
  664. (incf org-e-odt-embedded-formulas-count)))
  665. (target-file (concat target-dir "content.xml")))
  666. (message "Embedding %s as %s ..."
  667. (substring-no-properties path) target-file)
  668. (make-directory target-dir)
  669. (org-e-odt-create-manifest-file-entry
  670. "application/vnd.oasis.opendocument.formula" target-dir "1.2")
  671. (case (org-e-odt-is-formula-link-p src-file)
  672. (mathml
  673. (copy-file src-file target-file 'overwrite))
  674. (odf
  675. (org-e-odt-zip-extract-one src-file "content.xml" target-dir))
  676. (t
  677. (error "%s is not a formula file" src-file)))
  678. (org-e-odt-create-manifest-file-entry "text/xml" target-file)
  679. target-file))
  680. (defun org-e-odt-format-inline-formula (thefile)
  681. (let* ((thelink (if (file-name-absolute-p thefile) thefile
  682. (org-xml-format-href
  683. (org-e-odt-relocate-relative-path
  684. thefile org-current-export-file))))
  685. (href
  686. (org-e-odt-format-tags
  687. "<draw:object xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
  688. (file-name-directory (org-e-odt-copy-formula-file thefile)))))
  689. (org-e-odt-format-formula thefile href)))
  690. (defun org-e-odt-is-formula-link-p (file)
  691. (let ((case-fold-search nil))
  692. (cond
  693. ((string-match "\\.\\(mathml\\|mml\\)\\'" file)
  694. 'mathml)
  695. ((string-match "\\.odf\\'" file)
  696. 'odf))))
  697. (defun org-e-odt-format-org-link (opt-plist type-1 path fragment desc attr
  698. descp)
  699. "Make a OpenDocument link.
  700. OPT-PLIST is an options list.
  701. TYPE-1 is the device-type of the link (THIS://foo.html).
  702. PATH is the path of the link (http://THIS#location).
  703. FRAGMENT is the fragment part of the link, if any (foo.html#THIS).
  704. DESC is the link description, if any.
  705. ATTR is a string of other attributes of the a element."
  706. (declare (special org-lparse-par-open))
  707. (save-match-data
  708. (let* ((may-inline-p
  709. (and (member type-1 '("http" "https" "file"))
  710. (org-lparse-should-inline-p path descp)
  711. (not fragment)))
  712. (type (if (equal type-1 "id") "file" type-1))
  713. (filename path)
  714. (thefile path))
  715. (cond
  716. ;; check for inlined images
  717. ((and (member type '("file"))
  718. (not fragment)
  719. (org-file-image-p
  720. filename org-e-odt-inline-image-extensions)
  721. (not descp))
  722. (org-e-odt-format-inline-image thefile))
  723. ;; check for embedded formulas
  724. ((and (member type '("file"))
  725. (not fragment)
  726. (org-e-odt-is-formula-link-p filename)
  727. (or (not descp)))
  728. (org-e-odt-format-inline-formula thefile))
  729. ((string= type "coderef")
  730. (let* ((ref fragment)
  731. (lineno-or-ref (cdr (assoc ref org-export-code-refs)))
  732. (desc (and descp desc))
  733. (org-e-odt-suppress-xref nil)
  734. (href (org-xml-format-href (concat "#coderef-" ref))))
  735. (cond
  736. ((and (numberp lineno-or-ref) (not desc))
  737. (org-e-odt-format-link lineno-or-ref href))
  738. ((and (numberp lineno-or-ref) desc
  739. (string-match (regexp-quote (concat "(" ref ")")) desc))
  740. (format (replace-match "%s" t t desc)
  741. (org-e-odt-format-link lineno-or-ref href)))
  742. (t
  743. (setq desc (format
  744. (if (and desc (string-match
  745. (regexp-quote (concat "(" ref ")"))
  746. desc))
  747. (replace-match "%s" t t desc)
  748. (or desc "%s"))
  749. lineno-or-ref))
  750. (org-e-odt-format-link (org-xml-format-desc desc) href)))))
  751. (t
  752. (when (string= type "file")
  753. (setq thefile
  754. (cond
  755. ((file-name-absolute-p path)
  756. (concat "file://" (expand-file-name path)))
  757. (t (org-e-odt-relocate-relative-path
  758. thefile org-current-export-file)))))
  759. (when (and (member type '("" "http" "https" "file")) fragment)
  760. (setq thefile (concat thefile "#" fragment)))
  761. (setq thefile (org-xml-format-href thefile))
  762. (when (not (member type '("" "file")))
  763. (setq thefile (concat type ":" thefile)))
  764. (let ((org-e-odt-suppress-xref nil))
  765. (org-e-odt-format-link
  766. (org-xml-format-desc desc) thefile attr)))))))
  767. (defun org-e-odt-format-anchor (text name &optional class)
  768. (org-e-odt-format-target text name))
  769. (defun org-e-odt-format-bookmark (text id)
  770. (if id
  771. (org-e-odt-format-tags "<text:bookmark text:name=\"%s\"/>" text id)
  772. text))
  773. (defun org-e-odt-format-target (text id)
  774. (let ((name (concat org-e-odt-bookmark-prefix id)))
  775. (concat
  776. (and id (org-e-odt-format-tags
  777. "<text:bookmark-start text:name=\"%s\"/>" "" name))
  778. (org-e-odt-format-bookmark text id)
  779. (and id (org-e-odt-format-tags
  780. "<text:bookmark-end text:name=\"%s\"/>" "" name)))))
  781. (defun org-e-odt-format-footnote (n def)
  782. (setq n (format "%d" n))
  783. (let ((id (concat "fn" n))
  784. (note-class "footnote")
  785. (par-style "Footnote"))
  786. (org-e-odt-format-tags
  787. '("<text:note text:id=\"%s\" text:note-class=\"%s\">" . "</text:note>")
  788. (concat
  789. (org-e-odt-format-tags-simple
  790. '("<text:note-citation>" . "</text:note-citation>") n)
  791. (org-e-odt-format-tags
  792. '("<text:note-body>" . "</text:note-body>") def))
  793. id note-class)))
  794. (defun org-e-odt-format-footnote-reference (n def refcnt)
  795. (if (= refcnt 1)
  796. (org-e-odt-format-footnote n def)
  797. (org-e-odt-format-footnote-ref n)))
  798. (defun org-e-odt-format-footnote-ref (n)
  799. (setq n (format "%d" n))
  800. (let ((note-class "footnote")
  801. (ref-format "text")
  802. (ref-name (concat "fn" n)))
  803. (org-e-odt-format-tags
  804. '("<text:span text:style-name=\"%s\">" . "</text:span>")
  805. (org-e-odt-format-tags-simple
  806. '("<text:note-ref text:note-class=\"%s\" text:reference-format=\"%s\" text:ref-name=\"%s\">" . "</text:note-ref>")
  807. n note-class ref-format ref-name)
  808. "OrgSuperscript")))
  809. (defun org-e-odt-parse-block-attributes (params)
  810. (save-match-data
  811. (when params
  812. (setq params (org-trim params))
  813. (unless (string-match "\\`(.*)\\'" params)
  814. (setq params (format "(%s)" params)))
  815. (ignore-errors (read params)))))
  816. (defun org-e-odt-format-image (src &optional
  817. caption label attr
  818. embed-as ; FIXME
  819. category ; FIXME
  820. )
  821. "Create image tag with source and attributes."
  822. (let* ((href (org-e-odt-format-tags
  823. "<draw:image xlink:href=\"%s\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\"/>" ""
  824. (org-e-odt-copy-image-file src)))
  825. ;; (caption (org-find-text-property-in-string 'org-caption src))
  826. ;; (caption (and caption (org-xml-format-desc caption)))
  827. ;; (attr (org-find-text-property-in-string 'org-attributes src))
  828. ;; (label (org-find-text-property-in-string 'org-label src))
  829. ;; (latex-frag (org-find-text-property-in-string
  830. ;; 'org-latex-src src))
  831. ;; (category (and latex-frag "__DvipngImage__")) ; FIXME
  832. (attr-plist (org-e-odt-parse-block-attributes attr))
  833. (user-frame-anchor
  834. (car (assoc-string (plist-get attr-plist :anchor)
  835. '(("as-char") ("paragraph") ("page")) t)))
  836. (user-frame-style
  837. (and user-frame-anchor (plist-get attr-plist :style)))
  838. (user-frame-attrs
  839. (and user-frame-anchor (plist-get attr-plist :attributes)))
  840. (user-frame-params
  841. (list user-frame-style user-frame-attrs user-frame-anchor))
  842. (embed-as (or embed-as user-frame-anchor "paragraph"))
  843. ;; (embed-as (cond
  844. ;; (latex-frag
  845. ;; (symbol-name
  846. ;; (case (org-find-text-property-in-string ; FIXME
  847. ;; 'org-latex-src-embed-type src)
  848. ;; (paragraph 'paragraph)
  849. ;; (t 'as-char))))
  850. ;; (user-frame-anchor)
  851. ;; (t "paragraph")))
  852. (size (org-e-odt-image-size-from-file
  853. src (plist-get attr-plist :width)
  854. (plist-get attr-plist :height)
  855. (plist-get attr-plist :scale) nil embed-as))
  856. (width (car size)) (height (cdr size)))
  857. ;; (when latex-frag ; FIXME
  858. ;; (setq href (org-propertize href :title "LaTeX Fragment"
  859. ;; :description latex-frag)))
  860. (let ((frame-style-handle (concat (and (or caption label) "Captioned")
  861. embed-as "Image")))
  862. (org-e-odt-format-entity
  863. frame-style-handle href width height
  864. :caption caption :label label :category category
  865. :user-frame-params user-frame-params))))
  866. (defun org-e-odt-format-object-description (title description)
  867. (concat (and title (org-e-odt-format-tags
  868. '("<svg:title>" . "</svg:title>")
  869. (org-e-odt-encode-plain-text title t)))
  870. (and description (org-e-odt-format-tags
  871. '("<svg:desc>" . "</svg:desc>")
  872. (org-e-odt-encode-plain-text description t)))))
  873. (defun org-e-odt-format-frame (text width height style &optional
  874. extra anchor-type)
  875. (let ((frame-attrs
  876. (concat
  877. (if width (format " svg:width=\"%0.2fcm\"" width) "")
  878. (if height (format " svg:height=\"%0.2fcm\"" height) "")
  879. extra
  880. (format " text:anchor-type=\"%s\"" (or anchor-type "paragraph")))))
  881. (org-e-odt-format-tags
  882. '("<draw:frame draw:style-name=\"%s\"%s>" . "</draw:frame>")
  883. (concat text (org-e-odt-format-object-description
  884. (get-text-property 0 :title text)
  885. (get-text-property 0 :description text)))
  886. style frame-attrs)))
  887. (defun org-e-odt-format-textbox (text width height style &optional
  888. extra anchor-type)
  889. (org-e-odt-format-frame
  890. (org-e-odt-format-tags
  891. '("<draw:text-box %s>" . "</draw:text-box>")
  892. text (concat (format " fo:min-height=\"%0.2fcm\"" (or height .2))
  893. (unless width
  894. (format " fo:min-width=\"%0.2fcm\"" (or width .2)))))
  895. width nil style extra anchor-type))
  896. (defun org-e-odt-merge-frame-params(default-frame-params user-frame-params)
  897. (if (not user-frame-params) default-frame-params
  898. (assert (= (length default-frame-params) 3))
  899. (assert (= (length user-frame-params) 3))
  900. (loop for user-frame-param in user-frame-params
  901. for default-frame-param in default-frame-params
  902. collect (or user-frame-param default-frame-param))))
  903. (defun* org-e-odt-format-entity (entity href width height
  904. &key caption label category
  905. user-frame-params)
  906. (let* ((entity-style (assoc-string entity org-e-odt-entity-frame-styles t))
  907. default-frame-params frame-params)
  908. (cond
  909. ((not (or caption label))
  910. (setq default-frame-params (nth 2 entity-style))
  911. (setq frame-params (org-e-odt-merge-frame-params
  912. default-frame-params user-frame-params))
  913. (apply 'org-e-odt-format-frame href width height frame-params))
  914. (t
  915. (setq default-frame-params (nth 3 entity-style))
  916. (setq frame-params (org-e-odt-merge-frame-params
  917. default-frame-params user-frame-params))
  918. (apply 'org-e-odt-format-textbox
  919. (org-e-odt-format-stylized-paragraph
  920. 'illustration
  921. (concat
  922. (apply 'org-e-odt-format-frame href width height
  923. (nth 2 entity-style))
  924. (org-e-odt-format-entity-caption
  925. label caption (or category (nth 1 entity-style)))))
  926. width height frame-params)))))
  927. (defun org-e-odt-copy-image-file (path)
  928. "Returns the internal name of the file"
  929. (let* ((image-type (file-name-extension path))
  930. (media-type (format "image/%s" image-type))
  931. (src-file (expand-file-name
  932. path (file-name-directory org-current-export-file)))
  933. (target-dir "Images/")
  934. (target-file
  935. (format "%s%04d.%s" target-dir
  936. (incf org-e-odt-embedded-images-count) image-type)))
  937. (message "Embedding %s as %s ..."
  938. (substring-no-properties path) target-file)
  939. (when (= 1 org-e-odt-embedded-images-count)
  940. (make-directory target-dir)
  941. (org-e-odt-create-manifest-file-entry "" target-dir))
  942. (copy-file src-file target-file 'overwrite)
  943. (org-e-odt-create-manifest-file-entry media-type target-file)
  944. target-file))
  945. (defun org-e-odt-do-image-size (probe-method file &optional dpi anchor-type)
  946. (setq dpi (or dpi org-e-odt-pixels-per-inch))
  947. (setq anchor-type (or anchor-type "paragraph"))
  948. (flet ((size-in-cms (size-in-pixels)
  949. (flet ((pixels-to-cms (pixels)
  950. (let* ((cms-per-inch 2.54)
  951. (inches (/ pixels dpi)))
  952. (* cms-per-inch inches))))
  953. (and size-in-pixels
  954. (cons (pixels-to-cms (car size-in-pixels))
  955. (pixels-to-cms (cdr size-in-pixels)))))))
  956. (case probe-method
  957. (emacs
  958. (size-in-cms (ignore-errors ; Emacs could be in batch mode
  959. (clear-image-cache)
  960. (image-size (create-image file) 'pixels))))
  961. (imagemagick
  962. (size-in-cms
  963. (let ((dim (shell-command-to-string
  964. (format "identify -format \"%%w:%%h\" \"%s\"" file))))
  965. (when (string-match "\\([0-9]+\\):\\([0-9]+\\)" dim)
  966. (cons (string-to-number (match-string 1 dim))
  967. (string-to-number (match-string 2 dim)))))))
  968. (t
  969. (cdr (assoc-string anchor-type
  970. org-e-odt-default-image-sizes-alist))))))
  971. (defun org-e-odt-image-size-from-file (file &optional user-width
  972. user-height scale dpi embed-as)
  973. (unless (file-name-absolute-p file)
  974. (setq file (expand-file-name
  975. file (file-name-directory org-current-export-file))))
  976. (let* (size width height)
  977. (unless (and user-height user-width)
  978. (loop for probe-method in org-e-odt-image-size-probe-method
  979. until size
  980. do (setq size (org-e-odt-do-image-size
  981. probe-method file dpi embed-as)))
  982. (or size (error "Cannot determine Image size. Aborting ..."))
  983. (setq width (car size) height (cdr size)))
  984. (cond
  985. (scale
  986. (setq width (* width scale) height (* height scale)))
  987. ((and user-height user-width)
  988. (setq width user-width height user-height))
  989. (user-height
  990. (setq width (* user-height (/ width height)) height user-height))
  991. (user-width
  992. (setq height (* user-width (/ height width)) width user-width))
  993. (t (ignore)))
  994. ;; ensure that an embedded image fits comfortably within a page
  995. (let ((max-width (car org-e-odt-max-image-size))
  996. (max-height (cdr org-e-odt-max-image-size)))
  997. (when (or (> width max-width) (> height max-height))
  998. (let* ((scale1 (/ max-width width))
  999. (scale2 (/ max-height height))
  1000. (scale (min scale1 scale2)))
  1001. (setq width (* scale width) height (* scale height)))))
  1002. (cons width height)))
  1003. (defun org-e-odt-add-label-definition (label default-category)
  1004. "Create an entry in `org-e-odt-entity-labels-alist' and return it."
  1005. (setq label (substring-no-properties label))
  1006. (let* ((label-props (assoc default-category org-e-odt-category-map-alist))
  1007. (category (nth 1 label-props))
  1008. (counter category)
  1009. (label-style (nth 2 label-props))
  1010. (sequence-var (intern (mapconcat
  1011. 'downcase
  1012. (org-split-string counter) "-")))
  1013. (seqno (1+ (or (plist-get org-e-odt-entity-counts-plist sequence-var)
  1014. 0)))
  1015. (label-props (list label category seqno label-style)))
  1016. (setq org-e-odt-entity-counts-plist
  1017. (plist-put org-e-odt-entity-counts-plist sequence-var seqno))
  1018. (push label-props org-e-odt-entity-labels-alist)
  1019. label-props))
  1020. (defun org-e-odt-format-label-reference (label default-category
  1021. seqno) ; FIXME
  1022. (let* ((label-props (assoc default-category org-e-odt-category-map-alist))
  1023. (category (nth 1 label-props))
  1024. (counter category) ; FIXME
  1025. (label-style (nth 2 label-props)))
  1026. (unless label-props
  1027. (error "Unknown category: %S" default-category))
  1028. (org-e-odt-do-format-label-reference label category seqno label-style)))
  1029. (defun org-e-odt-format-label-definition (caption label category seqno label-style)
  1030. (assert label)
  1031. (setq label (org-solidify-link-text label))
  1032. (format-spec
  1033. (cadr (assoc-string label-style org-e-odt-label-styles t))
  1034. `((?e . ,category)
  1035. (?n . ,(org-e-odt-format-tags-simple
  1036. '("<text:sequence text:ref-name=\"%s\" text:name=\"%s\" text:formula=\"ooow:%s+1\" style:num-format=\"1\">" . "</text:sequence>")
  1037. (format "%d" seqno) label category category))
  1038. (?c . ,(or (and caption (concat ": " caption)) "")))))
  1039. (defun org-e-odt-do-format-label-reference (label category seqno label-style)
  1040. (assert label)
  1041. (save-match-data
  1042. (let* ((fmt (cddr (assoc-string label-style org-e-odt-label-styles t)))
  1043. (fmt1 (car fmt))
  1044. (fmt2 (cadr fmt)))
  1045. (org-e-odt-format-tags-simple
  1046. '("<text:sequence-ref text:reference-format=\"%s\" text:ref-name=\"%s\">"
  1047. . "</text:sequence-ref>")
  1048. (format-spec fmt2 `((?e . ,category)
  1049. (?n . ,(format "%d" seqno)))) fmt1 label))))
  1050. (defun org-e-odt-format-entity-caption (label caption category)
  1051. (or (and label
  1052. (apply 'org-e-odt-format-label-definition
  1053. caption (org-e-odt-add-label-definition label category)))
  1054. caption ""))
  1055. (defun org-e-odt-format-tags-1 (tag text prefix suffix &rest args)
  1056. (cond
  1057. ((consp tag)
  1058. (concat prefix (apply 'format (car tag) args) text suffix
  1059. (format (cdr tag))))
  1060. ((stringp tag) ; singleton tag
  1061. (concat prefix (apply 'format tag args) text))))
  1062. (defun org-e-odt-format-tags (tag text &rest args)
  1063. (apply 'org-e-odt-format-tags-1 tag text "\n" "\n" args))
  1064. (defun org-e-odt-format-tags-simple (tag text &rest args)
  1065. (apply 'org-e-odt-format-tags-1 tag text nil nil args))
  1066. (defun org-e-odt-init-outfile ()
  1067. (unless (executable-find "zip")
  1068. ;; Not at all OSes ship with zip by default
  1069. (error "Executable \"zip\" needed for creating OpenDocument files"))
  1070. (let* ((outdir (make-temp-file
  1071. (format org-e-odt-tmpdir-prefix 'odt) t)) ; FIXME
  1072. (content-file (expand-file-name "content.xml" outdir)))
  1073. ;; reset variables
  1074. (setq org-e-odt-manifest-file-entries nil
  1075. org-e-odt-embedded-images-count 0
  1076. org-e-odt-embedded-formulas-count 0
  1077. org-e-odt-section-count 0
  1078. org-e-odt-entity-labels-alist nil
  1079. org-e-odt-list-stack-stashed nil
  1080. org-e-odt-automatic-styles nil
  1081. org-e-odt-object-counters nil
  1082. org-e-odt-entity-counts-plist nil)
  1083. ;; let `htmlfontify' know that we are interested in collecting
  1084. ;; styles - FIXME
  1085. (setq hfy-user-sheet-assoc nil)
  1086. ;; init conten.xml
  1087. (with-current-buffer
  1088. (find-file-noselect content-file t)
  1089. (current-buffer))))
  1090. (defun org-e-odt-save-as-outfile (target opt-plist)
  1091. ;; write automatic styles
  1092. (org-e-odt-write-automatic-styles)
  1093. ;; write styles file
  1094. ;; (when (equal org-lparse-backend 'odt) FIXME
  1095. ;; )
  1096. (org-e-odt-update-styles-file opt-plist)
  1097. ;; create mimetype file
  1098. (let ((mimetype (org-e-odt-write-mimetype-file ;; org-lparse-backend FIXME
  1099. 'odt)))
  1100. (org-e-odt-create-manifest-file-entry mimetype "/" "1.2"))
  1101. ;; create a manifest entry for content.xml
  1102. (org-e-odt-create-manifest-file-entry "text/xml" "content.xml")
  1103. ;; write out the manifest entries before zipping
  1104. (org-e-odt-write-manifest-file)
  1105. (let ((xml-files '("mimetype" "META-INF/manifest.xml" "content.xml"
  1106. "meta.xml"))
  1107. (zipdir default-directory))
  1108. (when (or t (equal org-lparse-backend 'odt)) ; FIXME
  1109. (push "styles.xml" xml-files))
  1110. (message "Switching to directory %s" (expand-file-name zipdir))
  1111. ;; save all xml files
  1112. (mapc (lambda (file)
  1113. (with-current-buffer
  1114. (find-file-noselect (expand-file-name file) t)
  1115. ;; prettify output if needed
  1116. (when org-e-odt-prettify-xml
  1117. (indent-region (point-min) (point-max)))
  1118. (save-buffer 0)))
  1119. xml-files)
  1120. (let* ((target-name (file-name-nondirectory target))
  1121. (target-dir (file-name-directory target))
  1122. (cmds `(("zip" "-mX0" ,target-name "mimetype")
  1123. ("zip" "-rmTq" ,target-name "."))))
  1124. (when (file-exists-p target)
  1125. ;; FIXME: If the file is locked this throws a cryptic error
  1126. (delete-file target))
  1127. (let ((coding-system-for-write 'no-conversion) exitcode err-string)
  1128. (message "Creating odt file...")
  1129. (mapc
  1130. (lambda (cmd)
  1131. (message "Running %s" (mapconcat 'identity cmd " "))
  1132. (setq err-string
  1133. (with-output-to-string
  1134. (setq exitcode
  1135. (apply 'call-process (car cmd)
  1136. nil standard-output nil (cdr cmd)))))
  1137. (or (zerop exitcode)
  1138. (ignore (message "%s" err-string))
  1139. (error "Unable to create odt file (%S)" exitcode)))
  1140. cmds))
  1141. ;; move the file from outdir to target-dir
  1142. (rename-file target-name target-dir)
  1143. ;; kill all xml buffers
  1144. (mapc (lambda (file)
  1145. (kill-buffer
  1146. (find-file-noselect (expand-file-name file zipdir) t)))
  1147. xml-files)
  1148. (delete-directory zipdir)))
  1149. (message "Created %s" target)
  1150. (set-buffer (find-file-noselect target t)))
  1151. (defun org-e-odt-create-manifest-file-entry (&rest args)
  1152. (push args org-e-odt-manifest-file-entries))
  1153. (defun org-e-odt-write-manifest-file ()
  1154. (make-directory "META-INF")
  1155. (let ((manifest-file (expand-file-name "META-INF/manifest.xml")))
  1156. (with-current-buffer
  1157. (find-file-noselect manifest-file t)
  1158. (insert
  1159. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
  1160. <manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\" manifest:version=\"1.2\">\n")
  1161. (mapc
  1162. (lambda (file-entry)
  1163. (let* ((version (nth 2 file-entry))
  1164. (extra (if version
  1165. (format " manifest:version=\"%s\"" version)
  1166. "")))
  1167. (insert
  1168. (format org-e-odt-manifest-file-entry-tag
  1169. (nth 0 file-entry) (nth 1 file-entry) extra))))
  1170. org-e-odt-manifest-file-entries)
  1171. (insert "\n</manifest:manifest>"))))
  1172. (defun org-e-odt-update-meta-file (info) ; FIXME opt-plist
  1173. (let ((title (org-export-secondary-string
  1174. (plist-get info :title) 'e-odt info))
  1175. (author (or (let ((auth (plist-get info :author)))
  1176. (and auth (org-export-secondary-string
  1177. auth 'e-odt info))) ""))
  1178. (date (org-e-odt-format-date (plist-get info :date)))
  1179. (email (plist-get info :email))
  1180. (keywords (plist-get info :keywords))
  1181. (description (plist-get info :description)))
  1182. (write-region
  1183. (concat
  1184. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
  1185. <office:document-meta
  1186. xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"
  1187. xmlns:xlink=\"http://www.w3.org/1999/xlink\"
  1188. xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
  1189. xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"
  1190. xmlns:ooo=\"http://openoffice.org/2004/office\"
  1191. office:version=\"1.2\">
  1192. <office:meta>\n"
  1193. (org-e-odt-format-author author) "\n"
  1194. (format "<meta:initial-creator>%s</meta:initial-creator>\n" author)
  1195. (format "<dc:date>%s</dc:date>\n" date)
  1196. (format "<meta:creation-date>%s</meta:creation-date>\n" date)
  1197. (format "<meta:generator>%s</meta:generator>\n"
  1198. (when org-export-creator-info
  1199. (format "Org-%s/Emacs-%s"
  1200. org-version emacs-version)))
  1201. (format "<meta:keyword>%s</meta:keyword>\n" keywords)
  1202. (format "<dc:subject>%s</dc:subject>\n" description)
  1203. (format "<dc:title>%s</dc:title>\n" title)
  1204. "\n"
  1205. " </office:meta>\n" "</office:document-meta>")
  1206. nil (expand-file-name "meta.xml")))
  1207. ;; create a manifest entry for meta.xml
  1208. (org-e-odt-create-manifest-file-entry "text/xml" "meta.xml"))
  1209. (defun org-e-odt-update-styles-file (opt-plist)
  1210. ;; write styles file
  1211. (let ((styles-file (plist-get opt-plist :odt-styles-file)))
  1212. (org-e-odt-copy-styles-file (and styles-file
  1213. (read (org-trim styles-file))))
  1214. ;; FIXME: Who is opening an empty styles.xml before this point?
  1215. (with-current-buffer
  1216. (find-file-noselect (expand-file-name "styles.xml") t)
  1217. (revert-buffer t t)))
  1218. ;; Write custom styles for source blocks
  1219. (org-e-odt-insert-custom-styles-for-srcblocks
  1220. (mapconcat
  1221. (lambda (style)
  1222. (format " %s\n" (cddr style)))
  1223. hfy-user-sheet-assoc "")))
  1224. (defun org-e-odt-write-mimetype-file (format)
  1225. ;; create mimetype file
  1226. (let ((mimetype
  1227. (case format
  1228. (odt "application/vnd.oasis.opendocument.text")
  1229. (odf "application/vnd.oasis.opendocument.formula")
  1230. (t (error "Unknown OpenDocument backend %S" org-lparse-backend)))))
  1231. (write-region mimetype nil (expand-file-name "mimetype"))
  1232. mimetype))
  1233. (defun org-e-odt-finalize-outfile ()
  1234. (org-e-odt-delete-empty-paragraphs))
  1235. (defun org-e-odt-delete-empty-paragraphs ()
  1236. (goto-char (point-min))
  1237. (let ((open "<text:p[^>]*>")
  1238. (close "</text:p>"))
  1239. (while (re-search-forward (format "%s[ \r\n\t]*%s" open close) nil t)
  1240. (replace-match ""))))
  1241. (declare-function org-create-math-formula "org"
  1242. (latex-frag &optional mathml-file))
  1243. ;;;###autoload
  1244. (defun org-e-odt-convert (&optional in-file out-fmt prefix-arg)
  1245. "Convert IN-FILE to format OUT-FMT using a command line converter.
  1246. IN-FILE is the file to be converted. If unspecified, it defaults
  1247. to variable `buffer-file-name'. OUT-FMT is the desired output
  1248. format. Use `org-e-odt-convert-process' as the converter.
  1249. If PREFIX-ARG is non-nil then the newly converted file is opened
  1250. using `org-open-file'."
  1251. (interactive
  1252. (append (org-lparse-convert-read-params) current-prefix-arg))
  1253. (org-lparse-do-convert in-file out-fmt prefix-arg))
  1254. (defun org-e-odt-get (what &optional opt-plist)
  1255. (case what
  1256. (BACKEND 'odt)
  1257. (EXPORT-DIR (org-export-directory :html opt-plist))
  1258. (FILE-NAME-EXTENSION "odt")
  1259. (EXPORT-BUFFER-NAME "*Org ODT Export*")
  1260. (ENTITY-CONTROL org-e-odt-entity-control-callbacks-alist)
  1261. (ENTITY-FORMAT org-e-odt-entity-format-callbacks-alist)
  1262. (INIT-METHOD 'org-e-odt-init-outfile)
  1263. (FINAL-METHOD 'org-e-odt-finalize-outfile)
  1264. (SAVE-METHOD 'org-e-odt-save-as-outfile)
  1265. (CONVERT-METHOD
  1266. (and org-e-odt-convert-process
  1267. (cadr (assoc-string org-e-odt-convert-process
  1268. org-e-odt-convert-processes t))))
  1269. (CONVERT-CAPABILITIES
  1270. (and org-e-odt-convert-process
  1271. (cadr (assoc-string org-e-odt-convert-process
  1272. org-e-odt-convert-processes t))
  1273. org-e-odt-convert-capabilities))
  1274. (TOPLEVEL-HLEVEL 1)
  1275. (SPECIAL-STRING-REGEXPS org-e-odt-special-string-regexps)
  1276. (INLINE-IMAGES 'maybe)
  1277. (INLINE-IMAGE-EXTENSIONS '("png" "jpeg" "jpg" "gif" "svg"))
  1278. (PLAIN-TEXT-MAP '(("&" . "&amp;") ("<" . "&lt;") (">" . "&gt;")))
  1279. (TABLE-FIRST-COLUMN-AS-LABELS nil)
  1280. (FOOTNOTE-SEPARATOR )
  1281. (CODING-SYSTEM-FOR-WRITE 'utf-8)
  1282. (CODING-SYSTEM-FOR-SAVE 'utf-8)
  1283. (t (error "Unknown property: %s" what))))
  1284. (defun org-e-odt-do-preprocess-latex-fragments ()
  1285. "Convert LaTeX fragments to images."
  1286. (let* ((latex-frag-opt (plist-get org-lparse-opt-plist :LaTeX-fragments))
  1287. (latex-frag-opt ; massage the options
  1288. (or (and (member latex-frag-opt '(mathjax t))
  1289. (not (and (fboundp 'org-format-latex-mathml-available-p)
  1290. (org-format-latex-mathml-available-p)))
  1291. (prog1 org-lparse-latex-fragment-fallback
  1292. (org-lparse-warn
  1293. (concat
  1294. "LaTeX to MathML converter not available. "
  1295. (format "Using %S instead."
  1296. org-lparse-latex-fragment-fallback)))))
  1297. latex-frag-opt))
  1298. cache-dir display-msg)
  1299. (cond
  1300. ((eq latex-frag-opt 'dvipng)
  1301. (setq cache-dir "ltxpng/")
  1302. (setq display-msg "Creating LaTeX image %s"))
  1303. ((member latex-frag-opt '(mathjax t))
  1304. (setq latex-frag-opt 'mathml)
  1305. (setq cache-dir "ltxmathml/")
  1306. (setq display-msg "Creating MathML formula %s")))
  1307. (when (and org-current-export-file)
  1308. (org-format-latex
  1309. (concat cache-dir (file-name-sans-extension
  1310. (file-name-nondirectory org-current-export-file)))
  1311. org-current-export-dir nil display-msg
  1312. nil nil latex-frag-opt))))
  1313. (defadvice org-format-latex-as-mathml
  1314. (after org-e-odt-protect-latex-fragment activate)
  1315. "Encode LaTeX fragment as XML.
  1316. Do this when translation to MathML fails."
  1317. (when (or (not (> (length ad-return-value) 0))
  1318. (get-text-property 0 'org-protected ad-return-value))
  1319. (setq ad-return-value
  1320. (org-propertize (org-e-odt-encode-plain-text (ad-get-arg 0))
  1321. 'org-protected t))))
  1322. (defun org-e-odt-preprocess-latex-fragments ()
  1323. (when (equal org-export-current-backend 'odt)
  1324. (org-e-odt-do-preprocess-latex-fragments)))
  1325. ;; process latex fragments as part of
  1326. ;; `org-export-preprocess-after-blockquote-hook'. Note that this hook
  1327. ;; is the one that is closest and well before the call to
  1328. ;; `org-export-attach-captions-and-attributes' in
  1329. ;; `org-export-preprocess-string'. The above arrangement permits
  1330. ;; captions, labels and attributes to be attached to png images
  1331. ;; generated out of latex equations.
  1332. (add-hook 'org-export-preprocess-after-blockquote-hook
  1333. 'org-e-odt-preprocess-latex-fragments)
  1334. (defun org-e-odt-zip-extract-one (archive member &optional target)
  1335. (require 'arc-mode)
  1336. (let* ((target (or target default-directory))
  1337. (archive (expand-file-name archive))
  1338. (archive-zip-extract
  1339. (list "unzip" "-qq" "-o" "-d" target))
  1340. exit-code command-output)
  1341. (setq command-output
  1342. (with-temp-buffer
  1343. (setq exit-code (archive-zip-extract archive member))
  1344. (buffer-string)))
  1345. (unless (zerop exit-code)
  1346. (message command-output)
  1347. (error "Extraction failed"))))
  1348. (defun org-e-odt-zip-extract (archive members &optional target)
  1349. (when (atom members) (setq members (list members)))
  1350. (mapc (lambda (member)
  1351. (org-e-odt-zip-extract-one archive member target))
  1352. members))
  1353. (defun org-e-odt-copy-styles-file (&optional styles-file)
  1354. ;; Non-availability of styles.xml is not a critical error. For now
  1355. ;; throw an error purely for aesthetic reasons.
  1356. (setq styles-file (or styles-file
  1357. org-e-odt-styles-file
  1358. (expand-file-name "OrgOdtStyles.xml"
  1359. org-e-odt-styles-dir)
  1360. (error "org-e-odt: Missing styles file?")))
  1361. (cond
  1362. ((listp styles-file)
  1363. (let ((archive (nth 0 styles-file))
  1364. (members (nth 1 styles-file)))
  1365. (org-e-odt-zip-extract archive members)
  1366. (mapc
  1367. (lambda (member)
  1368. (when (org-file-image-p member)
  1369. (let* ((image-type (file-name-extension member))
  1370. (media-type (format "image/%s" image-type)))
  1371. (org-e-odt-create-manifest-file-entry media-type member))))
  1372. members)))
  1373. ((and (stringp styles-file) (file-exists-p styles-file))
  1374. (let ((styles-file-type (file-name-extension styles-file)))
  1375. (cond
  1376. ((string= styles-file-type "xml")
  1377. (copy-file styles-file (expand-file-name "styles.xml") t))
  1378. ((member styles-file-type '("odt" "ott"))
  1379. (org-e-odt-zip-extract styles-file "styles.xml")))))
  1380. (t
  1381. (error (format "Invalid specification of styles.xml file: %S"
  1382. org-e-odt-styles-file))))
  1383. ;; create a manifest entry for styles.xml
  1384. (org-e-odt-create-manifest-file-entry "text/xml" "styles.xml"))
  1385. (defun org-e-odt-configure-outline-numbering ()
  1386. "Outline numbering is retained only upto LEVEL.
  1387. To disable outline numbering pass a LEVEL of 0."
  1388. (goto-char (point-min))
  1389. (let ((regex
  1390. "<text:outline-level-style\\([^>]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>")
  1391. (replacement
  1392. "<text:outline-level-style\\1text:level=\"\\2\" style:num-format=\"\">"))
  1393. (while (re-search-forward regex nil t)
  1394. (unless (let ((sec-num (plist-get info :section-numbers))
  1395. (level (string-to-number (match-string 2))))
  1396. (if (wholenump sec-num) (<= level sec-num) sec-num))
  1397. (replace-match replacement t nil))))
  1398. (save-buffer 0))
  1399. ;;;###autoload
  1400. (defun org-export-as-odf (latex-frag &optional odf-file)
  1401. "Export LATEX-FRAG as OpenDocument formula file ODF-FILE.
  1402. Use `org-create-math-formula' to convert LATEX-FRAG first to
  1403. MathML. When invoked as an interactive command, use
  1404. `org-latex-regexps' to infer LATEX-FRAG from currently active
  1405. region. If no LaTeX fragments are found, prompt for it. Push
  1406. MathML source to kill ring, if `org-export-copy-to-kill-ring' is
  1407. non-nil."
  1408. (interactive
  1409. `(,(let (frag)
  1410. (setq frag (and (setq frag (and (region-active-p)
  1411. (buffer-substring (region-beginning)
  1412. (region-end))))
  1413. (loop for e in org-latex-regexps
  1414. thereis (when (string-match (nth 1 e) frag)
  1415. (match-string (nth 2 e) frag)))))
  1416. (read-string "LaTeX Fragment: " frag nil frag))
  1417. ,(let ((odf-filename (expand-file-name
  1418. (concat
  1419. (file-name-sans-extension
  1420. (or (file-name-nondirectory buffer-file-name)))
  1421. "." "odf")
  1422. (file-name-directory buffer-file-name))))
  1423. (read-file-name "ODF filename: " nil odf-filename nil
  1424. (file-name-nondirectory odf-filename)))))
  1425. (let* ((org-lparse-backend 'odf)
  1426. org-lparse-opt-plist
  1427. (filename (or odf-file
  1428. (expand-file-name
  1429. (concat
  1430. (file-name-sans-extension
  1431. (or (file-name-nondirectory buffer-file-name)))
  1432. "." "odf")
  1433. (file-name-directory buffer-file-name))))
  1434. (buffer (find-file-noselect (org-e-odt-init-outfile filename)))
  1435. (coding-system-for-write 'utf-8)
  1436. (save-buffer-coding-system 'utf-8))
  1437. (set-buffer buffer)
  1438. (set-buffer-file-coding-system coding-system-for-write)
  1439. (let ((mathml (org-create-math-formula latex-frag)))
  1440. (unless mathml (error "No Math formula created"))
  1441. (insert mathml)
  1442. (or (org-export-push-to-kill-ring
  1443. (upcase (symbol-name org-lparse-backend)))
  1444. (message "Exporting... done")))
  1445. (org-e-odt-save-as-outfile filename nil ; FIXME
  1446. )))
  1447. ;;;###autoload
  1448. (defun org-export-as-odf-and-open ()
  1449. "Export LaTeX fragment as OpenDocument formula and immediately open it.
  1450. Use `org-export-as-odf' to read LaTeX fragment and OpenDocument
  1451. formula file."
  1452. (interactive)
  1453. (org-lparse-and-open
  1454. nil nil nil (call-interactively 'org-export-as-odf)))
  1455. ;;; Driver Starts here
  1456. ;;; Dependencies
  1457. (require 'format-spec)
  1458. (eval-when-compile (require 'cl) (require 'table))
  1459. ;;; Hooks
  1460. (defvar org-e-odt-after-blockquotes-hook nil
  1461. "Hook run during HTML export, after blockquote, verse, center are done.")
  1462. (defvar org-e-odt-final-hook nil
  1463. "Hook run at the end of HTML export, in the new buffer.")
  1464. ;; FIXME: it already exists in org-e-odt.el
  1465. ;;; Function Declarations
  1466. (declare-function org-element-property "org-element" (property element))
  1467. (declare-function org-element-normalize-string "org-element" (s))
  1468. (declare-function org-element-parse-secondary-string
  1469. "org-element" (string restriction &optional buffer))
  1470. (defvar org-element-string-restrictions)
  1471. (defvar org-element-object-restrictions)
  1472. (declare-function org-export-clean-table "org-export" (table specialp))
  1473. (declare-function org-export-data "org-export" (data backend info))
  1474. (declare-function org-export-directory "org-export" (type plist))
  1475. (declare-function org-export-expand-macro "org-export" (macro info))
  1476. (declare-function org-export-first-sibling-p "org-export" (headline info))
  1477. (declare-function org-export-footnote-first-reference-p "org-export"
  1478. (footnote-reference info))
  1479. (declare-function org-export-get-coderef-format "org-export" (path desc))
  1480. (declare-function org-export-get-footnote-definition "org-export"
  1481. (footnote-reference info))
  1482. (declare-function org-export-get-footnote-number "org-export" (footnote info))
  1483. (declare-function org-export-get-previous-element "org-export" (blob info))
  1484. (declare-function org-export-get-relative-level "org-export" (headline info))
  1485. (declare-function org-export-handle-code
  1486. "org-export" (element info &optional num-fmt ref-fmt delayed))
  1487. (declare-function org-export-included-file "org-export" (keyword backend info))
  1488. (declare-function org-export-inline-image-p "org-export"
  1489. (link &optional extensions))
  1490. (declare-function org-export-last-sibling-p "org-export" (headline info))
  1491. (declare-function org-export-low-level-p "org-export" (headline info))
  1492. (declare-function org-export-output-file-name
  1493. "org-export" (extension &optional subtreep pub-dir))
  1494. (declare-function org-export-resolve-coderef "org-export" (ref info))
  1495. (declare-function org-export-resolve-fuzzy-link "org-export" (link info))
  1496. (declare-function org-export-secondary-string "org-export"
  1497. (secondary backend info))
  1498. (declare-function org-export-solidify-link-text "org-export" (s))
  1499. (declare-function org-export-table-format-info "org-export" (table))
  1500. (declare-function
  1501. org-export-to-buffer "org-export"
  1502. (backend buffer &optional subtreep visible-only body-only ext-plist))
  1503. (declare-function
  1504. org-export-to-file "org-export"
  1505. (backend file &optional subtreep visible-only body-only ext-plist))
  1506. (declare-function org-id-find-id-file "org-id" (id))
  1507. (declare-function htmlize-region "ext:htmlize" (beg end))
  1508. (declare-function org-pop-to-buffer-same-window
  1509. "org-compat" (&optional buffer-or-name norecord label))
  1510. (declare-function hfy-face-to-style "htmlfontify" (fn))
  1511. (declare-function hfy-face-or-def-to-name "htmlfontify" (fn))
  1512. (declare-function archive-zip-extract "arc-mode.el" (archive name))
  1513. ;;; Internal Variables
  1514. ;;;; ODT Internal Variables
  1515. (defconst org-e-odt-lib-dir
  1516. (file-name-directory load-file-name)
  1517. "Location of ODT exporter.
  1518. Use this to infer values of `org-e-odt-styles-dir' and
  1519. `org-e-odt-schema-dir'.")
  1520. (defvar org-e-odt-data-dir
  1521. (expand-file-name "../etc/" org-e-odt-lib-dir)
  1522. "Data directory for ODT exporter.
  1523. Use this to infer values of `org-e-odt-styles-dir' and
  1524. `org-e-odt-schema-dir'.")
  1525. (defconst org-e-odt-special-string-regexps
  1526. '(("\\\\-" . "&#x00ad;\\1") ; shy
  1527. ("---\\([^-]\\)" . "&#x2014;\\1") ; mdash
  1528. ("--\\([^-]\\)" . "&#x2013;\\1") ; ndash
  1529. ("\\.\\.\\." . "&#x2026;")) ; hellip
  1530. "Regular expressions for special string conversion.")
  1531. (defconst org-e-odt-schema-dir-list
  1532. (list
  1533. (and org-e-odt-data-dir
  1534. (expand-file-name "./schema/" org-e-odt-data-dir)) ; bail out
  1535. (eval-when-compile
  1536. (and (boundp 'org-e-odt-data-dir) org-e-odt-data-dir ; see make install
  1537. (expand-file-name "./schema/" org-e-odt-data-dir)))
  1538. (expand-file-name "../contrib/odt/etc/schema/" org-e-odt-lib-dir) ; git
  1539. )
  1540. "List of directories to search for OpenDocument schema files.
  1541. Use this list to set the default value of
  1542. `org-e-odt-schema-dir'. The entries in this list are
  1543. populated heuristically based on the values of `org-e-odt-lib-dir'
  1544. and `org-e-odt-data-dir'.")
  1545. (defconst org-e-odt-styles-dir-list
  1546. (list
  1547. (and org-e-odt-data-dir
  1548. (expand-file-name "./styles/" org-e-odt-data-dir)) ; bail out
  1549. (eval-when-compile
  1550. (and (boundp 'org-e-odt-data-dir) org-e-odt-data-dir ; see make install
  1551. (expand-file-name "./styles/" org-e-odt-data-dir)))
  1552. (expand-file-name "../etc/styles/" org-e-odt-lib-dir) ; git
  1553. (expand-file-name "./etc/styles/" org-e-odt-lib-dir) ; elpa
  1554. (expand-file-name "./org/" data-directory) ; system
  1555. )
  1556. "List of directories to search for OpenDocument styles files.
  1557. See `org-e-odt-styles-dir'. The entries in this list are populated
  1558. heuristically based on the values of `org-e-odt-lib-dir' and
  1559. `org-e-odt-data-dir'.")
  1560. (defconst org-e-odt-styles-dir
  1561. (let* ((styles-dir
  1562. (catch 'styles-dir
  1563. (message "Debug (org-e-odt): Searching for OpenDocument styles files...")
  1564. (mapc (lambda (styles-dir)
  1565. (when styles-dir
  1566. (message "Debug (org-e-odt): Trying %s..." styles-dir)
  1567. (when (and (file-readable-p
  1568. (expand-file-name
  1569. "OrgOdtContentTemplate.xml" styles-dir))
  1570. (file-readable-p
  1571. (expand-file-name
  1572. "OrgOdtStyles.xml" styles-dir)))
  1573. (message "Debug (org-e-odt): Using styles under %s"
  1574. styles-dir)
  1575. (throw 'styles-dir styles-dir))))
  1576. org-e-odt-styles-dir-list)
  1577. nil)))
  1578. (unless styles-dir
  1579. (error "Error (org-e-odt): Cannot find factory styles files. Aborting."))
  1580. styles-dir)
  1581. "Directory that holds auxiliary XML files used by the ODT exporter.
  1582. This directory contains the following XML files -
  1583. \"OrgOdtStyles.xml\" and \"OrgOdtContentTemplate.xml\". These
  1584. XML files are used as the default values of
  1585. `org-e-odt-styles-file' and
  1586. `org-e-odt-content-template-file'.
  1587. The default value of this variable varies depending on the
  1588. version of org in use and is initialized from
  1589. `org-e-odt-styles-dir-list'. Note that the user could be using org
  1590. from one of: org's own private git repository, GNU ELPA tar or
  1591. standard Emacs.")
  1592. (defconst org-e-odt-tmpdir-prefix "%s-")
  1593. (defconst org-e-odt-bookmark-prefix "OrgXref.")
  1594. (defconst org-e-odt-manifest-file-entry-tag
  1595. "
  1596. <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s\"%s/>")
  1597. (defvar org-lparse-dyn-first-heading-pos) ; let bound during org-do-lparse
  1598. (defvar org-e-odt-suppress-xref nil)
  1599. (defvar org-e-odt-file-extensions
  1600. '(("odt" . "OpenDocument Text")
  1601. ("ott" . "OpenDocument Text Template")
  1602. ("odm" . "OpenDocument Master Document")
  1603. ("ods" . "OpenDocument Spreadsheet")
  1604. ("ots" . "OpenDocument Spreadsheet Template")
  1605. ("odg" . "OpenDocument Drawing (Graphics)")
  1606. ("otg" . "OpenDocument Drawing Template")
  1607. ("odp" . "OpenDocument Presentation")
  1608. ("otp" . "OpenDocument Presentation Template")
  1609. ("odi" . "OpenDocument Image")
  1610. ("odf" . "OpenDocument Formula")
  1611. ("odc" . "OpenDocument Chart")))
  1612. (defvar org-e-odt-default-org-styles-alist
  1613. '((paragraph . ((default . "Text_20_body")
  1614. (fixedwidth . "OrgFixedWidthBlock")
  1615. (verse . "OrgVerse")
  1616. (quote . "Quotations")
  1617. (blockquote . "Quotations")
  1618. (center . "OrgCenter")
  1619. (left . "OrgLeft")
  1620. (right . "OrgRight")
  1621. (title . "OrgTitle")
  1622. (subtitle . "OrgSubtitle")
  1623. (footnote . "Footnote")
  1624. (src . "OrgSrcBlock")
  1625. (illustration . "Illustration")
  1626. (table . "Table")
  1627. (definition-term . "Text_20_body_20_bold")
  1628. (horizontal-line . "Horizontal_20_Line")))
  1629. (character . ((bold . "Bold")
  1630. (emphasis . "Emphasis")
  1631. (code . "OrgCode")
  1632. (verbatim . "OrgCode")
  1633. (strike . "Strikethrough")
  1634. (underline . "Underline")
  1635. (subscript . "OrgSubscript")
  1636. (superscript . "OrgSuperscript")))
  1637. (list . ((ordered . "OrgNumberedList")
  1638. (unordered . "OrgBulletedList")
  1639. (descriptive . "OrgDescriptionList"))))
  1640. "Default styles for various entities.")
  1641. (defvar org-e-odt-org-styles-alist org-e-odt-default-org-styles-alist)
  1642. ;;;_. callbacks
  1643. ;;;_. control callbacks
  1644. ;;;_ , document body
  1645. (defvar org-lparse-body-only) ; let bound during org-do-lparse
  1646. (defvar org-lparse-opt-plist) ; bound during org-do-lparse
  1647. (defvar org-lparse-list-stack) ; dynamically bound in org-do-lparse
  1648. (defvar org-e-odt-list-stack-stashed)
  1649. (defvar org-lparse-table-ncols)
  1650. (defvar org-e-odt-table-rowgrp-open)
  1651. (defvar org-e-odt-table-rownum)
  1652. (defvar org-e-odt-table-cur-rowgrp-is-hdr)
  1653. (defvar org-lparse-table-is-styled)
  1654. (defvar org-lparse-table-rowgrp-info)
  1655. (defvar org-lparse-table-colalign-vector)
  1656. (defvar org-e-odt-table-style nil
  1657. "Table style specified by \"#+ATTR_ODT: <style-name>\" line.
  1658. This is set during `org-e-odt-begin-table'.")
  1659. (defvar org-e-odt-table-style-spec nil
  1660. "Entry for `org-e-odt-table-style' in `org-e-odt-table-styles'.")
  1661. (defvar org-e-odt-table-style-format
  1662. "
  1663. <style:style style:name=\"%s\" style:family=\"table\">
  1664. <style:table-properties style:rel-width=\"%d%%\" fo:margin-top=\"0cm\" fo:margin-bottom=\"0.20cm\" table:align=\"center\"/>
  1665. </style:style>
  1666. "
  1667. "Template for auto-generated Table styles.")
  1668. (defvar org-e-odt-automatic-styles '()
  1669. "Registry of automatic styles for various OBJECT-TYPEs.
  1670. The variable has the following form:
  1671. \(\(OBJECT-TYPE-A
  1672. \(\(OBJECT-NAME-A.1 OBJECT-PROPS-A.1\)
  1673. \(OBJECT-NAME-A.2 OBJECT-PROPS-A.2\) ...\)\)
  1674. \(OBJECT-TYPE-B
  1675. \(\(OBJECT-NAME-B.1 OBJECT-PROPS-B.1\)
  1676. \(OBJECT-NAME-B.2 OBJECT-PROPS-B.2\) ...\)\)
  1677. ...\).
  1678. OBJECT-TYPEs could be \"Section\", \"Table\", \"Figure\" etc.
  1679. OBJECT-PROPS is (typically) a plist created by passing
  1680. \"#+ATTR_ODT: \" option to `org-e-odt-parse-block-attributes'.
  1681. Use `org-e-odt-add-automatic-style' to add update this variable.'")
  1682. (defvar org-e-odt-object-counters nil
  1683. "Running counters for various OBJECT-TYPEs.
  1684. Use this to generate automatic names and style-names. See
  1685. `org-e-odt-add-automatic-style'.")
  1686. (defvar org-e-odt-table-indentedp nil)
  1687. (defvar org-lparse-table-colalign-info)
  1688. (defvar org-lparse-link-description-is-image nil)
  1689. (defvar org-src-block-paragraph-format
  1690. "<style:style style:name=\"OrgSrcBlock\" style:family=\"paragraph\" style:parent-style-name=\"Preformatted_20_Text\">
  1691. <style:paragraph-properties fo:background-color=\"%s\" fo:padding=\"0.049cm\" fo:border=\"0.51pt solid #000000\" style:shadow=\"none\">
  1692. <style:background-image/>
  1693. </style:paragraph-properties>
  1694. <style:text-properties fo:color=\"%s\"/>
  1695. </style:style>"
  1696. "Custom paragraph style for colorized source and example blocks.
  1697. This style is much the same as that of \"OrgFixedWidthBlock\"
  1698. except that the foreground and background colors are set
  1699. according to the default face identified by the `htmlfontify'.")
  1700. (defvar hfy-optimisations)
  1701. (defvar org-e-odt-embedded-formulas-count 0)
  1702. (defvar org-e-odt-entity-frame-styles
  1703. '(("As-CharImage" "__Figure__" ("OrgInlineImage" nil "as-char"))
  1704. ("ParagraphImage" "__Figure__" ("OrgDisplayImage" nil "paragraph"))
  1705. ("PageImage" "__Figure__" ("OrgPageImage" nil "page"))
  1706. ("CaptionedAs-CharImage" "__Figure__"
  1707. ("OrgCaptionedImage"
  1708. " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
  1709. ("OrgInlineImage" nil "as-char"))
  1710. ("CaptionedParagraphImage" "__Figure__"
  1711. ("OrgCaptionedImage"
  1712. " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
  1713. ("OrgImageCaptionFrame" nil "paragraph"))
  1714. ("CaptionedPageImage" "__Figure__"
  1715. ("OrgCaptionedImage"
  1716. " style:rel-width=\"100%\" style:rel-height=\"scale\"" "paragraph")
  1717. ("OrgPageImageCaptionFrame" nil "page"))
  1718. ("InlineFormula" "__MathFormula__" ("OrgInlineFormula" nil "as-char"))
  1719. ("DisplayFormula" "__MathFormula__" ("OrgDisplayFormula" nil "as-char"))
  1720. ("CaptionedDisplayFormula" "__MathFormula__"
  1721. ("OrgCaptionedFormula" nil "paragraph")
  1722. ("OrgFormulaCaptionFrame" nil "as-char"))))
  1723. (defvar org-e-odt-embedded-images-count 0)
  1724. (defvar org-e-odt-image-size-probe-method
  1725. (append (and (executable-find "identify") '(imagemagick)) ; See Bug#10675
  1726. '(emacs fixed))
  1727. "Ordered list of methods for determining image sizes.")
  1728. (defvar org-e-odt-default-image-sizes-alist
  1729. '(("as-char" . (5 . 0.4))
  1730. ("paragraph" . (5 . 5)))
  1731. "Hardcoded image dimensions one for each of the anchor
  1732. methods.")
  1733. ;; A4 page size is 21.0 by 29.7 cms
  1734. ;; The default page settings has 2cm margin on each of the sides. So
  1735. ;; the effective text area is 17.0 by 25.7 cm
  1736. (defvar org-e-odt-max-image-size '(17.0 . 20.0)
  1737. "Limiting dimensions for an embedded image.")
  1738. (defvar org-e-odt-entity-labels-alist nil
  1739. "Associate Labels with the Labeled entities.
  1740. Each element of the alist is of the form (LABEL-NAME
  1741. CATEGORY-NAME SEQNO LABEL-STYLE-NAME). LABEL-NAME is same as
  1742. that specified by \"#+LABEL: ...\" line. CATEGORY-NAME is the
  1743. type of the entity that LABEL-NAME is attached to. CATEGORY-NAME
  1744. can be one of \"Table\", \"Figure\" or \"Equation\". SEQNO is
  1745. the unique number assigned to the referenced entity on a
  1746. per-CATEGORY basis. It is generated sequentially and is 1-based.
  1747. LABEL-STYLE-NAME is a key `org-e-odt-label-styles'.
  1748. See `org-e-odt-add-label-definition' and
  1749. `org-e-odt-fixup-label-references'.")
  1750. (defvar org-e-odt-entity-counts-plist nil
  1751. "Plist of running counters of SEQNOs for each of the CATEGORY-NAMEs.
  1752. See `org-e-odt-entity-labels-alist' for known CATEGORY-NAMEs.")
  1753. (defvar org-e-odt-label-styles
  1754. '(("text" "(%n)" "text" "(%n)")
  1755. ("category-and-value" "%e %n%c" "category-and-value" "%e %n")
  1756. ("value" "%e %n%c" "value" "%n"))
  1757. "Specify how labels are applied and referenced.
  1758. This is an alist where each element is of the
  1759. form (LABEL-STYLE-NAME LABEL-ATTACH-FMT LABEL-REF-MODE
  1760. LABEL-REF-FMT).
  1761. LABEL-ATTACH-FMT controls how labels and captions are attached to
  1762. an entity. It may contain following specifiers - %e, %n and %c.
  1763. %e is replaced with the CATEGORY-NAME. %n is replaced with
  1764. \"<text:sequence ...> SEQNO </text:sequence>\". %c is replaced
  1765. with CAPTION. See `org-e-odt-format-label-definition'.
  1766. LABEL-REF-MODE and LABEL-REF-FMT controls how label references
  1767. are generated. The following XML is generated for a label
  1768. reference - \"<text:sequence-ref
  1769. text:reference-format=\"LABEL-REF-MODE\" ...> LABEL-REF-FMT
  1770. </text:sequence-ref>\". LABEL-REF-FMT may contain following
  1771. specifiers - %e and %n. %e is replaced with the CATEGORY-NAME.
  1772. %n is replaced with SEQNO. See
  1773. `org-e-odt-format-label-reference'.")
  1774. (defvar org-e-odt-category-map-alist
  1775. '(("__Table__" "Table" "value")
  1776. ("__Figure__" "Figure" "value")
  1777. ("__MathFormula__" "Equation" "text")
  1778. ("__DvipngImage__" "Equation" "value")
  1779. ;; ("__Table__" "Table" "category-and-value")
  1780. ;; ("__Figure__" "Figure" "category-and-value")
  1781. ;; ("__DvipngImage__" "Equation" "category-and-value")
  1782. )
  1783. "Map a CATEGORY-HANDLE to CATEGORY-NAME and LABEL-STYLE.
  1784. This is an alist where each element is of the form
  1785. \\(CATEGORY-HANDLE CATEGORY-NAME LABEL-STYLE\\). CATEGORY_HANDLE
  1786. could either be one of the internal handles (as seen above) or be
  1787. derived from the \"#+LABEL:<label-name>\" specification. See
  1788. `org-e-odt-get-category-from-label'. CATEGORY-NAME and
  1789. LABEL-STYLE are used for generating ODT labels. See
  1790. `org-e-odt-label-styles'.")
  1791. (defvar org-e-odt-manifest-file-entries nil)
  1792. (defvar hfy-user-sheet-assoc) ; bound during org-do-lparse
  1793. (defvar org-lparse-latex-fragment-fallback) ; set by org-do-lparse
  1794. ;;;; HTML Internal Variables
  1795. (defvar org-e-odt-option-alist
  1796. '(
  1797. ;; (:agenda-style nil nil org-agenda-export-html-style)
  1798. ;; (:convert-org-links nil nil org-e-odt-link-org-files-as-html)
  1799. ;; ;; FIXME Use (org-xml-encode-org-text-skip-links s) ??
  1800. ;; ;; (:expand-quoted-html nil "@" org-e-odt-expand)
  1801. ;; (:inline-images nil nil org-e-odt-inline-images)
  1802. ;; ;; (:link-home nil nil org-e-odt-link-home) FIXME
  1803. ;; ;; (:link-up nil nil org-e-odt-link-up) FIXME
  1804. ;; (:style nil nil org-e-odt-style)
  1805. ;; (:style-extra nil nil org-e-odt-style-extra)
  1806. ;; (:style-include-default nil nil org-e-odt-style-include-default)
  1807. ;; (:style-include-scripts nil nil org-e-odt-style-include-scripts)
  1808. ;; ;; (:timestamp nil nil org-e-odt-with-timestamp)
  1809. ;; (:html-extension nil nil org-e-odt-extension)
  1810. ;; (:html-postamble nil nil org-e-odt-postamble)
  1811. ;; (:html-preamble nil nil org-e-odt-preamble)
  1812. ;; (:html-table-tag nil nil org-e-odt-table-tag)
  1813. ;; (:xml-declaration nil nil org-e-odt-xml-declaration)
  1814. (:LaTeX-fragments nil "LaTeX" org-export-with-LaTeX-fragments))
  1815. "Alist between export properties and ways to set them.
  1816. The car of the alist is the property name, and the cdr is a list
  1817. like \(KEYWORD OPTION DEFAULT BEHAVIOUR\) where:
  1818. KEYWORD is a string representing a buffer keyword, or nil.
  1819. OPTION is a string that could be found in an #+OPTIONS: line.
  1820. DEFAULT is the default value for the property.
  1821. BEHAVIOUR determine how Org should handle multiple keywords for
  1822. the same property. It is a symbol among:
  1823. nil Keep old value and discard the new one.
  1824. t Replace old value with the new one.
  1825. `space' Concatenate the values, separating them with a space.
  1826. `newline' Concatenate the values, separating them with
  1827. a newline.
  1828. `split' Split values at white spaces, and cons them to the
  1829. previous list.
  1830. KEYWORD and OPTION have precedence over DEFAULT.
  1831. All these properties should be back-end agnostic. For back-end
  1832. specific properties, define a similar variable named
  1833. `org-BACKEND-option-alist', replacing BACKEND with the name of
  1834. the appropriate back-end. You can also redefine properties
  1835. there, as they have precedence over these.")
  1836. (defvar html-table-tag nil) ; dynamically scoped into this.
  1837. ;; FIXME: it already exists in org-e-odt.el
  1838. (defconst org-e-odt-cvt-link-fn
  1839. nil
  1840. "Function to convert link URLs to exportable URLs.
  1841. Takes two arguments, TYPE and PATH.
  1842. Returns exportable url as (TYPE PATH), or nil to signal that it
  1843. didn't handle this case.
  1844. Intended to be locally bound around a call to `org-export-as-html'." )
  1845. (defvar org-e-odt-format-table-no-css)
  1846. (defvar htmlize-buffer-places) ; from htmlize.el
  1847. (defvar body-only) ; dynamically scoped into this.
  1848. (defvar org-e-odt-table-rowgrp-open)
  1849. (defvar org-e-odt-table-rownum)
  1850. (defvar org-e-odt-table-cur-rowgrp-is-hdr)
  1851. (defvar org-lparse-table-is-styled)
  1852. (defvar org-e-odt-headline-formatter
  1853. (lambda (level snumber todo todo-type priority
  1854. title tags target extra-targets extra-class)
  1855. (concat snumber " " title)))
  1856. ;;; User Configuration Variables
  1857. (defgroup org-export-e-odt nil
  1858. "Options for exporting Org mode files to HTML."
  1859. :tag "Org Export HTML"
  1860. :group 'org-export)
  1861. (defcustom org-e-odt-protect-char-alist
  1862. '(("&" . "&amp;")
  1863. ("<" . "&lt;")
  1864. (">" . "&gt;"))
  1865. "Alist of characters to be converted by `org-e-html-protect'."
  1866. :group 'org-export-e-html
  1867. :type '(repeat (cons (string :tag "Character")
  1868. (string :tag "ODT equivalent"))))
  1869. (defcustom org-e-odt-schema-dir
  1870. (let* ((schema-dir
  1871. (catch 'schema-dir
  1872. (message "Debug (org-e-odt): Searching for OpenDocument schema files...")
  1873. (mapc
  1874. (lambda (schema-dir)
  1875. (when schema-dir
  1876. (message "Debug (org-e-odt): Trying %s..." schema-dir)
  1877. (when (and (file-readable-p
  1878. (expand-file-name "od-manifest-schema-v1.2-cs01.rnc"
  1879. schema-dir))
  1880. (file-readable-p
  1881. (expand-file-name "od-schema-v1.2-cs01.rnc"
  1882. schema-dir))
  1883. (file-readable-p
  1884. (expand-file-name "schemas.xml" schema-dir)))
  1885. (message "Debug (org-e-odt): Using schema files under %s"
  1886. schema-dir)
  1887. (throw 'schema-dir schema-dir))))
  1888. org-e-odt-schema-dir-list)
  1889. (message "Debug (org-e-odt): No OpenDocument schema files installed")
  1890. nil)))
  1891. schema-dir)
  1892. "Directory that contains OpenDocument schema files.
  1893. This directory contains:
  1894. 1. rnc files for OpenDocument schema
  1895. 2. a \"schemas.xml\" file that specifies locating rules needed
  1896. for auto validation of OpenDocument XML files.
  1897. Use the customize interface to set this variable. This ensures
  1898. that `rng-schema-locating-files' is updated and auto-validation
  1899. of OpenDocument XML takes place based on the value
  1900. `rng-nxml-auto-validate-flag'.
  1901. The default value of this variable varies depending on the
  1902. version of org in use and is initialized from
  1903. `org-e-odt-schema-dir-list'. The OASIS schema files are available
  1904. only in the org's private git repository. It is *not* bundled
  1905. with GNU ELPA tar or standard Emacs distribution."
  1906. :type '(choice
  1907. (const :tag "Not set" nil)
  1908. (directory :tag "Schema directory"))
  1909. :group 'org-export-e-odt
  1910. :version "24.1"
  1911. :set
  1912. (lambda (var value)
  1913. "Set `org-e-odt-schema-dir'.
  1914. Also add it to `rng-schema-locating-files'."
  1915. (let ((schema-dir value))
  1916. (set var
  1917. (if (and
  1918. (file-readable-p
  1919. (expand-file-name "od-manifest-schema-v1.2-cs01.rnc" schema-dir))
  1920. (file-readable-p
  1921. (expand-file-name "od-schema-v1.2-cs01.rnc" schema-dir))
  1922. (file-readable-p
  1923. (expand-file-name "schemas.xml" schema-dir)))
  1924. schema-dir
  1925. (when value
  1926. (message "Error (org-e-odt): %s has no OpenDocument schema files"
  1927. value))
  1928. nil)))
  1929. (when org-e-odt-schema-dir
  1930. (eval-after-load 'rng-loc
  1931. '(add-to-list 'rng-schema-locating-files
  1932. (expand-file-name "schemas.xml"
  1933. org-e-odt-schema-dir))))))
  1934. (defcustom org-e-odt-content-template-file nil
  1935. "Template file for \"content.xml\".
  1936. The exporter embeds the exported content just before
  1937. \"</office:text>\" element.
  1938. If unspecified, the file named \"OrgOdtContentTemplate.xml\"
  1939. under `org-e-odt-styles-dir' is used."
  1940. :type 'file
  1941. :group 'org-export-e-odt
  1942. :version "24.1")
  1943. (defcustom org-e-odt-styles-file nil
  1944. "Default styles file for use with ODT export.
  1945. Valid values are one of:
  1946. 1. nil
  1947. 2. path to a styles.xml file
  1948. 3. path to a *.odt or a *.ott file
  1949. 4. list of the form (ODT-OR-OTT-FILE (FILE-MEMBER-1 FILE-MEMBER-2
  1950. ...))
  1951. In case of option 1, an in-built styles.xml is used. See
  1952. `org-e-odt-styles-dir' for more information.
  1953. In case of option 3, the specified file is unzipped and the
  1954. styles.xml embedded therein is used.
  1955. In case of option 4, the specified ODT-OR-OTT-FILE is unzipped
  1956. and FILE-MEMBER-1, FILE-MEMBER-2 etc are copied in to the
  1957. generated odt file. Use relative path for specifying the
  1958. FILE-MEMBERS. styles.xml must be specified as one of the
  1959. FILE-MEMBERS.
  1960. Use options 1, 2 or 3 only if styles.xml alone suffices for
  1961. achieving the desired formatting. Use option 4, if the styles.xml
  1962. references additional files like header and footer images for
  1963. achieving the desired formatting.
  1964. Use \"#+ODT_STYLES_FILE: ...\" directive to set this variable on
  1965. a per-file basis. For example,
  1966. #+ODT_STYLES_FILE: \"/path/to/styles.xml\" or
  1967. #+ODT_STYLES_FILE: (\"/path/to/file.ott\" (\"styles.xml\" \"image/hdr.png\"))."
  1968. :group 'org-export-e-odt
  1969. :version "24.1"
  1970. :type
  1971. '(choice
  1972. (const :tag "Factory settings" nil)
  1973. (file :must-match t :tag "styles.xml")
  1974. (file :must-match t :tag "ODT or OTT file")
  1975. (list :tag "ODT or OTT file + Members"
  1976. (file :must-match t :tag "ODF Text or Text Template file")
  1977. (cons :tag "Members"
  1978. (file :tag " Member" "styles.xml")
  1979. (repeat (file :tag "Member"))))))
  1980. (defcustom org-e-odt-inline-image-extensions
  1981. '("png" "jpeg" "jpg" "gif")
  1982. "Extensions of image files that can be inlined into HTML."
  1983. :type '(repeat (string :tag "Extension"))
  1984. :group 'org-export-e-odt
  1985. :version "24.1")
  1986. (defcustom org-e-odt-pixels-per-inch display-pixels-per-inch
  1987. "Scaling factor for converting images pixels to inches.
  1988. Use this for sizing of embedded images. See Info node `(org)
  1989. Images in ODT export' for more information."
  1990. :type 'float
  1991. :group 'org-export-e-odt
  1992. :version "24.1")
  1993. (defcustom org-e-odt-create-custom-styles-for-srcblocks t
  1994. "Whether custom styles for colorized source blocks be automatically created.
  1995. When this option is turned on, the exporter creates custom styles
  1996. for source blocks based on the advice of `htmlfontify'. Creation
  1997. of custom styles happen as part of `org-e-odt-hfy-face-to-css'.
  1998. When this option is turned off exporter does not create such
  1999. styles.
  2000. Use the latter option if you do not want the custom styles to be
  2001. based on your current display settings. It is necessary that the
  2002. styles.xml already contains needed styles for colorizing to work.
  2003. This variable is effective only if
  2004. `org-e-odt-fontify-srcblocks' is turned on."
  2005. :group 'org-export-e-odt
  2006. :version "24.1"
  2007. :type 'boolean)
  2008. (defcustom org-e-odt-preferred-output-format nil
  2009. "Automatically post-process to this format after exporting to \"odt\".
  2010. Interactive commands `org-export-as-e-odt' and
  2011. `org-export-as-e-odt-and-open' export first to \"odt\" format and
  2012. then use `org-e-odt-convert-process' to convert the
  2013. resulting document to this format. During customization of this
  2014. variable, the list of valid values are populated based on
  2015. `org-e-odt-convert-capabilities'."
  2016. :group 'org-export-e-odt
  2017. :version "24.1"
  2018. :type '(choice :convert-widget
  2019. (lambda (w)
  2020. (apply 'widget-convert (widget-type w)
  2021. (eval (car (widget-get w :args)))))
  2022. `((const :tag "None" nil)
  2023. ,@(mapcar (lambda (c)
  2024. `(const :tag ,c ,c))
  2025. (org-lparse-reachable-formats "odt")))))
  2026. (defcustom org-e-odt-table-styles
  2027. '(("OrgEquation" "OrgEquation"
  2028. ((use-first-column-styles . t)
  2029. (use-last-column-styles . t))))
  2030. "Specify how Table Styles should be derived from a Table Template.
  2031. This is a list where each element is of the
  2032. form (TABLE-STYLE-NAME TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS).
  2033. TABLE-STYLE-NAME is the style associated with the table through
  2034. `org-e-odt-table-style'.
  2035. TABLE-TEMPLATE-NAME is a set of - upto 9 - automatic
  2036. TABLE-CELL-STYLE-NAMEs and PARAGRAPH-STYLE-NAMEs (as defined
  2037. below) that is included in
  2038. `org-e-odt-content-template-file'.
  2039. TABLE-CELL-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
  2040. \"TableCell\"
  2041. PARAGRAPH-STYLE-NAME := TABLE-TEMPLATE-NAME + TABLE-CELL-TYPE +
  2042. \"TableParagraph\"
  2043. TABLE-CELL-TYPE := \"FirstRow\" | \"LastColumn\" |
  2044. \"FirstRow\" | \"LastRow\" |
  2045. \"EvenRow\" | \"OddRow\" |
  2046. \"EvenColumn\" | \"OddColumn\" | \"\"
  2047. where \"+\" above denotes string concatenation.
  2048. TABLE-CELL-OPTIONS is an alist where each element is of the
  2049. form (TABLE-CELL-STYLE-SELECTOR . ON-OR-OFF).
  2050. TABLE-CELL-STYLE-SELECTOR := `use-first-row-styles' |
  2051. `use-last-row-styles' |
  2052. `use-first-column-styles' |
  2053. `use-last-column-styles' |
  2054. `use-banding-rows-styles' |
  2055. `use-banding-columns-styles' |
  2056. `use-first-row-styles'
  2057. ON-OR-OFF := `t' | `nil'
  2058. For example, with the following configuration
  2059. \(setq org-e-odt-table-styles
  2060. '\(\(\"TableWithHeaderRowsAndColumns\" \"Custom\"
  2061. \(\(use-first-row-styles . t\)
  2062. \(use-first-column-styles . t\)\)\)
  2063. \(\"TableWithHeaderColumns\" \"Custom\"
  2064. \(\(use-first-column-styles . t\)\)\)\)\)
  2065. 1. A table associated with \"TableWithHeaderRowsAndColumns\"
  2066. style will use the following table-cell styles -
  2067. \"CustomFirstRowTableCell\", \"CustomFirstColumnTableCell\",
  2068. \"CustomTableCell\" and the following paragraph styles
  2069. \"CustomFirstRowTableParagraph\",
  2070. \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
  2071. as appropriate.
  2072. 2. A table associated with \"TableWithHeaderColumns\" style will
  2073. use the following table-cell styles -
  2074. \"CustomFirstColumnTableCell\", \"CustomTableCell\" and the
  2075. following paragraph styles
  2076. \"CustomFirstColumnTableParagraph\", \"CustomTableParagraph\"
  2077. as appropriate..
  2078. Note that TABLE-TEMPLATE-NAME corresponds to the
  2079. \"<table:table-template>\" elements contained within
  2080. \"<office:styles>\". The entries (TABLE-STYLE-NAME
  2081. TABLE-TEMPLATE-NAME TABLE-CELL-OPTIONS) correspond to
  2082. \"table:template-name\" and \"table:use-first-row-styles\" etc
  2083. attributes of \"<table:table>\" element. Refer ODF-1.2
  2084. specification for more information. Also consult the
  2085. implementation filed under `org-e-odt-get-table-cell-styles'.
  2086. The TABLE-STYLE-NAME \"OrgEquation\" is used internally for
  2087. formatting of numbered display equations. Do not delete this
  2088. style from the list."
  2089. :group 'org-export-e-odt
  2090. :version "24.1"
  2091. :type '(choice
  2092. (const :tag "None" nil)
  2093. (repeat :tag "Table Styles"
  2094. (list :tag "Table Style Specification"
  2095. (string :tag "Table Style Name")
  2096. (string :tag "Table Template Name")
  2097. (alist :options (use-first-row-styles
  2098. use-last-row-styles
  2099. use-first-column-styles
  2100. use-last-column-styles
  2101. use-banding-rows-styles
  2102. use-banding-columns-styles)
  2103. :key-type symbol
  2104. :value-type (const :tag "True" t))))))
  2105. (defcustom org-e-odt-fontify-srcblocks t
  2106. "Specify whether or not source blocks need to be fontified.
  2107. Turn this option on if you want to colorize the source code
  2108. blocks in the exported file. For colorization to work, you need
  2109. to make available an enhanced version of `htmlfontify' library."
  2110. :type 'boolean
  2111. :group 'org-export-e-odt
  2112. :version "24.1")
  2113. (defcustom org-e-odt-prettify-xml t ; FIXME
  2114. "Specify whether or not the xml output should be prettified.
  2115. When this option is turned on, `indent-region' is run on all
  2116. component xml buffers before they are saved. Turn this off for
  2117. regular use. Turn this on if you need to examine the xml
  2118. visually."
  2119. :group 'org-export-e-odt
  2120. :version "24.1"
  2121. :type 'boolean)
  2122. (defcustom org-e-odt-convert-processes
  2123. '(("LibreOffice"
  2124. "soffice --headless --convert-to %f%x --outdir %d %i")
  2125. ("unoconv"
  2126. "unoconv -f %f -o %d %i"))
  2127. "Specify a list of document converters and their usage.
  2128. The converters in this list are offered as choices while
  2129. customizing `org-e-odt-convert-process'.
  2130. This variable is a list where each element is of the
  2131. form (CONVERTER-NAME CONVERTER-CMD). CONVERTER-NAME is the name
  2132. of the converter. CONVERTER-CMD is the shell command for the
  2133. converter and can contain format specifiers. These format
  2134. specifiers are interpreted as below:
  2135. %i input file name in full
  2136. %I input file name as a URL
  2137. %f format of the output file
  2138. %o output file name in full
  2139. %O output file name as a URL
  2140. %d output dir in full
  2141. %D output dir as a URL.
  2142. %x extra options as set in `org-e-odt-convert-capabilities'."
  2143. :group 'org-export-e-odt
  2144. :version "24.1"
  2145. :type
  2146. '(choice
  2147. (const :tag "None" nil)
  2148. (alist :tag "Converters"
  2149. :key-type (string :tag "Converter Name")
  2150. :value-type (group (string :tag "Command line")))))
  2151. (defcustom org-e-odt-convert-process "LibreOffice"
  2152. "Use this converter to convert from \"odt\" format to other formats.
  2153. During customization, the list of converter names are populated
  2154. from `org-e-odt-convert-processes'."
  2155. :group 'org-export-e-odt
  2156. :version "24.1"
  2157. :type '(choice :convert-widget
  2158. (lambda (w)
  2159. (apply 'widget-convert (widget-type w)
  2160. (eval (car (widget-get w :args)))))
  2161. `((const :tag "None" nil)
  2162. ,@(mapcar (lambda (c)
  2163. `(const :tag ,(car c) ,(car c)))
  2164. org-e-odt-convert-processes))))
  2165. (defcustom org-e-odt-convert-capabilities
  2166. '(("Text"
  2167. ("odt" "ott" "doc" "rtf" "docx")
  2168. (("pdf" "pdf") ("odt" "odt") ("rtf" "rtf") ("ott" "ott")
  2169. ("doc" "doc" ":\"MS Word 97\"") ("docx" "docx") ("html" "html")))
  2170. ("Web"
  2171. ("html")
  2172. (("pdf" "pdf") ("odt" "odt") ("html" "html")))
  2173. ("Spreadsheet"
  2174. ("ods" "ots" "xls" "csv" "xlsx")
  2175. (("pdf" "pdf") ("ots" "ots") ("html" "html") ("csv" "csv") ("ods" "ods")
  2176. ("xls" "xls") ("xlsx" "xlsx")))
  2177. ("Presentation"
  2178. ("odp" "otp" "ppt" "pptx")
  2179. (("pdf" "pdf") ("swf" "swf") ("odp" "odp") ("otp" "otp") ("ppt" "ppt")
  2180. ("pptx" "pptx") ("odg" "odg"))))
  2181. "Specify input and output formats of `org-e-odt-convert-process'.
  2182. More correctly, specify the set of input and output formats that
  2183. the user is actually interested in.
  2184. This variable is an alist where each element is of the
  2185. form (DOCUMENT-CLASS INPUT-FMT-LIST OUTPUT-FMT-ALIST).
  2186. INPUT-FMT-LIST is a list of INPUT-FMTs. OUTPUT-FMT-ALIST is an
  2187. alist where each element is of the form (OUTPUT-FMT
  2188. OUTPUT-FILE-EXTENSION EXTRA-OPTIONS).
  2189. The variable is interpreted as follows:
  2190. `org-e-odt-convert-process' can take any document that is in
  2191. INPUT-FMT-LIST and produce any document that is in the
  2192. OUTPUT-FMT-LIST. A document converted to OUTPUT-FMT will have
  2193. OUTPUT-FILE-EXTENSION as the file name extension. OUTPUT-FMT
  2194. serves dual purposes:
  2195. - It is used for populating completion candidates during
  2196. `org-e-odt-convert' commands.
  2197. - It is used as the value of \"%f\" specifier in
  2198. `org-e-odt-convert-process'.
  2199. EXTRA-OPTIONS is used as the value of \"%x\" specifier in
  2200. `org-e-odt-convert-process'.
  2201. DOCUMENT-CLASS is used to group a set of file formats in
  2202. INPUT-FMT-LIST in to a single class.
  2203. Note that this variable inherently captures how LibreOffice based
  2204. converters work. LibreOffice maps documents of various formats
  2205. to classes like Text, Web, Spreadsheet, Presentation etc and
  2206. allow document of a given class (irrespective of it's source
  2207. format) to be converted to any of the export formats associated
  2208. with that class.
  2209. See default setting of this variable for an typical
  2210. configuration."
  2211. :group 'org-export-e-odt
  2212. :version "24.1"
  2213. :type
  2214. '(choice
  2215. (const :tag "None" nil)
  2216. (alist :tag "Capabilities"
  2217. :key-type (string :tag "Document Class")
  2218. :value-type
  2219. (group (repeat :tag "Input formats" (string :tag "Input format"))
  2220. (alist :tag "Output formats"
  2221. :key-type (string :tag "Output format")
  2222. :value-type
  2223. (group (string :tag "Output file extension")
  2224. (choice
  2225. (const :tag "None" nil)
  2226. (string :tag "Extra options"))))))))
  2227. ;;;; Debugging
  2228. ;;;; Document
  2229. ;;;; Document Header (Styles)
  2230. ;;;; Document Header (Scripts)
  2231. ;;;; Document Header (Mathjax)
  2232. ;;;; Preamble
  2233. ;;;; Postamble
  2234. ;;;; Emphasis
  2235. ;;;; Todos
  2236. ;;;; Tags
  2237. ;;;; Time-stamps
  2238. ;;;; Statistics Cookie
  2239. ;;;; Subscript
  2240. ;;;; Superscript
  2241. ;;;; Inline images
  2242. ;;;; Block
  2243. ;;;; Comment
  2244. ;;;; Comment Block
  2245. ;;;; Drawer
  2246. ;;;; Dynamic Block
  2247. ;;;; Emphasis
  2248. ;;;; Entity
  2249. ;;;; Example Block
  2250. ;;;; Export Snippet
  2251. ;;;; Export Block
  2252. ;;;; Fixed Width
  2253. ;;;; Footnotes
  2254. ;;;; Headline
  2255. ;;;; Horizontal Rule
  2256. ;;;; Inline Babel Call
  2257. ;;;; Inline Src Block
  2258. ;;;; Inlinetask
  2259. ;;;; Item
  2260. ;;;; Keyword
  2261. ;;;; Latex Environment
  2262. ;;;; Latex Fragment
  2263. ;;;; Line Break
  2264. ;;;; Link
  2265. ;;;; Babel Call
  2266. ;;;; Macro
  2267. ;;;; Paragraph
  2268. ;;;; Plain List
  2269. ;;;; Plain Text
  2270. ;;;; Property Drawer
  2271. ;;;; Quote Block
  2272. ;;;; Quote Section
  2273. ;;;; Section
  2274. ;;;; Radio Target
  2275. ;;;; Special Block
  2276. ;;;; Src Block
  2277. ;;;; Table
  2278. ;;;; Target
  2279. ;;;; Time-stamp
  2280. ;;;; Verbatim
  2281. ;;;; Verse Block
  2282. ;;;; Headline
  2283. ;;;; Links
  2284. ;;;; Drawers
  2285. ;;;; Inlinetasks
  2286. ;;;; Publishing
  2287. ;;;; Compilation
  2288. ;;; User Configurable Variables (MAYBE)
  2289. ;;;; Preamble
  2290. ;;;; Headline
  2291. ;;;; Emphasis
  2292. (defcustom org-e-odt-format-headline-function nil
  2293. "Function to format headline text.
  2294. This function will be called with 5 arguments:
  2295. TODO the todo keyword \(string or nil\).
  2296. TODO-TYPE the type of todo \(symbol: `todo', `done', nil\)
  2297. PRIORITY the priority of the headline \(integer or nil\)
  2298. TEXT the main headline text \(string\).
  2299. TAGS the tags string, separated with colons \(string or nil\).
  2300. The function result will be used in the section format string.
  2301. As an example, one could set the variable to the following, in
  2302. order to reproduce the default set-up:
  2303. \(defun org-e-odt-format-headline \(todo todo-type priority text tags\)
  2304. \"Default format function for an headline.\"
  2305. \(concat \(when todo
  2306. \(format \"\\\\textbf{\\\\textsc{\\\\textsf{%s}}} \" todo\)\)
  2307. \(when priority
  2308. \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
  2309. text
  2310. \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)"
  2311. :group 'org-export-e-odt
  2312. :type 'function)
  2313. ;;;; Footnotes
  2314. ;;;; Time-stamps
  2315. (defcustom org-e-odt-active-timestamp-format "\\textit{%s}"
  2316. "A printf format string to be applied to active time-stamps."
  2317. :group 'org-export-e-odt
  2318. :type 'string)
  2319. (defcustom org-e-odt-inactive-timestamp-format "\\textit{%s}"
  2320. "A printf format string to be applied to inactive time-stamps."
  2321. :group 'org-export-e-odt
  2322. :type 'string)
  2323. (defcustom org-e-odt-diary-timestamp-format "\\textit{%s}"
  2324. "A printf format string to be applied to diary time-stamps."
  2325. :group 'org-export-e-odt
  2326. :type 'string)
  2327. ;;;; Links
  2328. (defcustom org-e-odt-inline-image-rules
  2329. '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\)\\'"))
  2330. "Rules characterizing image files that can be inlined into HTML.
  2331. A rule consists in an association whose key is the type of link
  2332. to consider, and value is a regexp that will be matched against
  2333. link's path.
  2334. Note that, by default, the image extension *actually* allowed
  2335. depend on the way the HTML file is processed. When used with
  2336. pdflatex, pdf, jpg and png images are OK. When processing
  2337. through dvi to Postscript, only ps and eps are allowed. The
  2338. default we use here encompasses both."
  2339. :group 'org-export-e-odt
  2340. :type '(alist :key-type (string :tag "Type")
  2341. :value-type (regexp :tag "Path")))
  2342. ;;;; Tables
  2343. (defcustom org-e-odt-table-caption-above t
  2344. "When non-nil, place caption string at the beginning of the table.
  2345. Otherwise, place it near the end."
  2346. :group 'org-export-e-odt
  2347. :type 'boolean)
  2348. ;;;; Drawers
  2349. (defcustom org-e-odt-format-drawer-function nil
  2350. "Function called to format a drawer in HTML code.
  2351. The function must accept two parameters:
  2352. NAME the drawer name, like \"LOGBOOK\"
  2353. CONTENTS the contents of the drawer.
  2354. The function should return the string to be exported.
  2355. For example, the variable could be set to the following function
  2356. in order to mimic default behaviour:
  2357. \(defun org-e-odt-format-drawer-default \(name contents\)
  2358. \"Format a drawer element for HTML export.\"
  2359. contents\)"
  2360. :group 'org-export-e-odt
  2361. :type 'function)
  2362. ;;;; Inlinetasks
  2363. (defcustom org-e-odt-format-inlinetask-function nil
  2364. "Function called to format an inlinetask in HTML code.
  2365. The function must accept six parameters:
  2366. TODO the todo keyword, as a string
  2367. TODO-TYPE the todo type, a symbol among `todo', `done' and nil.
  2368. PRIORITY the inlinetask priority, as a string
  2369. NAME the inlinetask name, as a string.
  2370. TAGS the inlinetask tags, as a string.
  2371. CONTENTS the contents of the inlinetask, as a string.
  2372. The function should return the string to be exported.
  2373. For example, the variable could be set to the following function
  2374. in order to mimic default behaviour:
  2375. \(defun org-e-odt-format-inlinetask \(todo type priority name tags contents\)
  2376. \"Format an inline task element for HTML export.\"
  2377. \(let \(\(full-title
  2378. \(concat
  2379. \(when todo
  2380. \(format \"\\\\textbf{\\\\textsf{\\\\textsc{%s}}} \" todo\)\)
  2381. \(when priority \(format \"\\\\framebox{\\\\#%c} \" priority\)\)
  2382. title
  2383. \(when tags \(format \"\\\\hfill{}\\\\textsc{%s}\" tags\)\)\)\)\)
  2384. \(format \(concat \"\\\\begin{center}\\n\"
  2385. \"\\\\fbox{\\n\"
  2386. \"\\\\begin{minipage}[c]{.6\\\\textwidth}\\n\"
  2387. \"%s\\n\\n\"
  2388. \"\\\\rule[.8em]{\\\\textwidth}{2pt}\\n\\n\"
  2389. \"%s\"
  2390. \"\\\\end{minipage}}\"
  2391. \"\\\\end{center}\"\)
  2392. full-title contents\)\)"
  2393. :group 'org-export-e-odt
  2394. :type 'function)
  2395. ;; Src blocks
  2396. ;;;; Plain text
  2397. (defcustom org-e-odt-quotes
  2398. '(("fr" ("\\(\\s-\\|[[(]\\)\"" . "«~") ("\\(\\S-\\)\"" . "~»") ("\\(\\s-\\|(\\)'" . "'"))
  2399. ("en" ("\\(\\s-\\|[[(]\\)\"" . "``") ("\\(\\S-\\)\"" . "''") ("\\(\\s-\\|(\\)'" . "`")))
  2400. "Alist for quotes to use when converting english double-quotes.
  2401. The CAR of each item in this alist is the language code.
  2402. The CDR of each item in this alist is a list of three CONS:
  2403. - the first CONS defines the opening quote;
  2404. - the second CONS defines the closing quote;
  2405. - the last CONS defines single quotes.
  2406. For each item in a CONS, the first string is a regexp
  2407. for allowed characters before/after the quote, the second
  2408. string defines the replacement string for this quote."
  2409. :group 'org-export-e-odt
  2410. :type '(list
  2411. (cons :tag "Opening quote"
  2412. (string :tag "Regexp for char before")
  2413. (string :tag "Replacement quote "))
  2414. (cons :tag "Closing quote"
  2415. (string :tag "Regexp for char after ")
  2416. (string :tag "Replacement quote "))
  2417. (cons :tag "Single quote"
  2418. (string :tag "Regexp for char before")
  2419. (string :tag "Replacement quote "))))
  2420. ;;;; Compilation
  2421. ;;; Internal Functions (HTML)
  2422. ;; (defun org-e-odt-format-inline-image (path &optional caption label attr)
  2423. ;; ;; FIXME: alt text missing here?
  2424. ;; (let ((inline-image (format "<img src=\"%s\" alt=\"%s\"/>"
  2425. ;; path (file-name-nondirectory path))))
  2426. ;; (if (not label) inline-image
  2427. ;; (org-e-odt-format-section inline-image "figure" label))))
  2428. ;;;; Bibliography
  2429. (defun org-e-odt-bibliography ()
  2430. "Find bibliography, cut it out and return it."
  2431. (catch 'exit
  2432. (let (beg end (cnt 1) bib)
  2433. (save-excursion
  2434. (goto-char (point-min))
  2435. (when (re-search-forward
  2436. "^[ \t]*<div \\(id\\|class\\)=\"bibliography\"" nil t)
  2437. (setq beg (match-beginning 0))
  2438. (while (re-search-forward "</?div\\>" nil t)
  2439. (setq cnt (+ cnt (if (string= (match-string 0) "<div") +1 -1)))
  2440. (when (= cnt 0)
  2441. (and (looking-at ">") (forward-char 1))
  2442. (setq bib (buffer-substring beg (point)))
  2443. (delete-region beg (point))
  2444. (throw 'exit bib))))
  2445. nil))))
  2446. ;;;; Table
  2447. (defun org-e-odt-format-table (lines olines)
  2448. (let ((org-e-odt-format-table-no-css nil))
  2449. (org-lparse-format-table lines olines)))
  2450. (defun org-e-odt-splice-attributes (tag attributes)
  2451. "Read attributes in string ATTRIBUTES, add and replace in HTML tag TAG."
  2452. (if (not attributes)
  2453. tag
  2454. (let (oldatt newatt)
  2455. (setq oldatt (org-extract-attributes-from-string tag)
  2456. tag (pop oldatt)
  2457. newatt (cdr (org-extract-attributes-from-string attributes)))
  2458. (while newatt
  2459. (setq oldatt (plist-put oldatt (pop newatt) (pop newatt))))
  2460. (if (string-match ">" tag)
  2461. (setq tag
  2462. (replace-match (concat (org-attributes-to-string oldatt) ">")
  2463. t t tag)))
  2464. tag)))
  2465. (defun org-export-splice-style (style extra)
  2466. "Splice EXTRA into STYLE, just before \"</style>\"."
  2467. (if (and (stringp extra)
  2468. (string-match "\\S-" extra)
  2469. (string-match "</style>" style))
  2470. (concat (substring style 0 (match-beginning 0))
  2471. "\n" extra "\n"
  2472. (substring style (match-beginning 0)))
  2473. style))
  2474. (defun org-e-odt-toc-entry-formatter
  2475. (level snumber todo todo-type priority
  2476. headline tags target extra-targets extra-class)
  2477. (org-e-odt-format-toc-entry snumber todo headline tags target))
  2478. (defun org-e-odt-make-string (n string)
  2479. (let (out) (dotimes (i n out) (setq out (concat string out)))))
  2480. (defun org-e-odt-toc-text (toc-entries)
  2481. (let* ((prev-level (1- (nth 1 (car toc-entries))))
  2482. (start-level prev-level))
  2483. (mapconcat
  2484. (lambda (entry)
  2485. (let ((headline (nth 0 entry))
  2486. (level (nth 1 entry)))
  2487. (prog1 (org-e-odt-format-toc-item headline level prev-level)
  2488. (setq prev-level level))))
  2489. toc-entries "")))
  2490. (defun* org-e-odt-format-toc-headline
  2491. (todo todo-type priority text tags
  2492. &key level section-number headline-label &allow-other-keys)
  2493. ;; FIXME
  2494. (setq text (concat
  2495. (and org-export-with-section-numbers
  2496. (concat section-number ". "))
  2497. text
  2498. (and tags
  2499. (concat
  2500. (org-e-odt-format-spaces 3)
  2501. (org-e-odt-format-fontify tags "tag")))))
  2502. (when todo
  2503. (setq text (org-e-odt-format-fontify text "todo")))
  2504. (let ((org-e-odt-suppress-xref t))
  2505. (org-e-odt-format-link text (concat "#" headline-label))))
  2506. (defun org-e-odt-toc (depth info)
  2507. (assert (wholenump depth))
  2508. (let* ((headlines (org-export-collect-headlines info depth))
  2509. (toc-entries
  2510. (loop for headline in headlines collect
  2511. (list (org-e-odt-format-headline--wrap
  2512. headline info 'org-e-odt-format-toc-headline)
  2513. (org-export-get-relative-level headline info)))))
  2514. (when toc-entries
  2515. (let* ((lang-specific-heading "Table of Contents")) ; FIXME
  2516. (concat
  2517. (org-e-odt-begin-toc lang-specific-heading depth)
  2518. (org-e-odt-toc-text toc-entries)
  2519. (org-e-odt-end-toc))))))
  2520. (defun org-e-odt-begin-outline (level1 snumber title tags
  2521. target extra-targets extra-class)
  2522. (let* ((class (format "outline-%d" level1))
  2523. (class (if extra-class (concat class " " extra-class) class))
  2524. (id (format "outline-container-%s"
  2525. (org-lparse-suffix-from-snumber snumber)))
  2526. (extra (concat (when id (format " id=\"%s\"" id))
  2527. (when class (format " class=\"%s\"" class)))))
  2528. (org-lparse-insert-tag "<div%s>" extra)
  2529. (insert
  2530. (org-lparse-format 'HEADING
  2531. (org-lparse-format
  2532. 'HEADLINE title extra-targets tags snumber level1)
  2533. level1 target))))
  2534. (defun org-e-odt-end-outline ()
  2535. (org-lparse-insert-tag "</div>"))
  2536. (defun org-e-odt-suffix-from-snumber (snumber)
  2537. (let* ((snu (replace-regexp-in-string "\\." "-" snumber))
  2538. (href (cdr (assoc (concat "sec-" snu)
  2539. org-export-preferred-target-alist))))
  2540. (org-solidify-link-text (or href snu))))
  2541. (defun org-e-odt-format-outline (contents level1 snumber title
  2542. tags target extra-targets extra-class)
  2543. )
  2544. ;; (defun org-e-odt-format-line (line)
  2545. ;; (case org-lparse-dyn-current-environment
  2546. ;; ((quote fixedwidth) (concat (org-e-odt-encode-plain-text line) "\n"))
  2547. ;; (t (concat line "\n"))))
  2548. (defun org-e-odt-fix-class-name (kwd) ; audit callers of this function
  2549. "Turn todo keyword into a valid class name.
  2550. Replaces invalid characters with \"_\"."
  2551. (save-match-data
  2552. (while (string-match "[^a-zA-Z0-9_]" kwd)
  2553. (setq kwd (replace-match "_" t t kwd))))
  2554. kwd)
  2555. (defun org-e-odt-format-internal-link (text href &optional extra)
  2556. (org-e-odt-format-link text (concat "#" href) extra))
  2557. (defun org-e-odt-format-extra-targets (extra-targets)
  2558. (if (not extra-targets) ""
  2559. (mapconcat (lambda (x)
  2560. (when x
  2561. (setq x (org-solidify-link-text
  2562. (if (org-uuidgen-p x) (concat "ID-" x) x)))
  2563. (org-e-odt-format-anchor "" x))) extra-targets "")))
  2564. (defun org-e-odt-format-org-tags (tags)
  2565. (if (not tags) ""
  2566. (org-e-odt-format-fontify
  2567. (mapconcat
  2568. (lambda (x)
  2569. (org-e-odt-format-fontify
  2570. x (concat "" ;; org-e-odt-tag-class-prefix
  2571. (org-e-odt-fix-class-name x))))
  2572. (org-split-string tags ":")
  2573. (org-e-odt-format-spaces 1)) "tag")))
  2574. (defun org-e-odt-format-section-number (&optional snumber level)
  2575. ;; FIXME
  2576. (and nil org-export-with-section-numbers
  2577. ;; (not org-lparse-body-only)
  2578. snumber level
  2579. (org-e-odt-format-fontify snumber (format "section-number-%d" level))))
  2580. ;; (defun org-e-odt-format-headline (title extra-targets tags
  2581. ;; &optional snumber level)
  2582. ;; (concat
  2583. ;; (org-e-odt-format-extra-targets extra-targets)
  2584. ;; (concat (org-e-odt-format-section-number snumber level) " ")
  2585. ;; title
  2586. ;; (and tags (concat (org-e-odt-format-spaces 3)
  2587. ;; (org-e-odt-format-org-tags tags)))))
  2588. (defun org-e-odt-get-coding-system-for-write ()
  2589. (or org-e-odt-coding-system
  2590. (and (boundp 'buffer-file-coding-system) buffer-file-coding-system)))
  2591. (defun org-e-odt-get-coding-system-for-save ()
  2592. (or org-e-odt-coding-system
  2593. (and (boundp 'buffer-file-coding-system) buffer-file-coding-system)))
  2594. ;; (defun org-e-odt-format-date (info)
  2595. ;; (let ((date (plist-get info :date)))
  2596. ;; (cond
  2597. ;; ((and date (string-match "%" date))
  2598. ;; (format-time-string date))
  2599. ;; (date date)
  2600. ;; (t (format-time-string "%Y-%m-%d %T %Z")))))
  2601. ;;; Internal Functions (Ngz)
  2602. (defun org-e-odt--caption/label-string (caption label info)
  2603. "Return caption and label HTML string for floats.
  2604. CAPTION is a cons cell of secondary strings, the car being the
  2605. standard caption and the cdr its short form. LABEL is a string
  2606. representing the label. INFO is a plist holding contextual
  2607. information.
  2608. If there's no caption nor label, return the empty string.
  2609. For non-floats, see `org-e-odt--wrap-label'."
  2610. (setq label nil) ;; FIXME
  2611. (let ((label-str (if label (format "\\label{%s}" label) "")))
  2612. (cond
  2613. ((and (not caption) (not label)) "")
  2614. ((not caption) (format "\\label{%s}\n" label))
  2615. ;; Option caption format with short name.
  2616. ((cdr caption)
  2617. (format "\\caption[%s]{%s%s}\n"
  2618. (org-export-secondary-string (cdr caption) 'e-odt info)
  2619. label-str
  2620. (org-export-secondary-string (car caption) 'e-odt info)))
  2621. ;; Standard caption format.
  2622. ;; (t (format "\\caption{%s%s}\n"
  2623. ;; label-str
  2624. ;; (org-export-secondary-string (car caption) 'e-odt info)))
  2625. (t (org-export-secondary-string (car caption) 'e-odt info)))))
  2626. (defun org-e-odt--find-verb-separator (s)
  2627. "Return a character not used in string S.
  2628. This is used to choose a separator for constructs like \\verb."
  2629. (let ((ll "~,./?;':\"|!@#%^&-_=+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ<>()[]{}"))
  2630. (loop for c across ll
  2631. when (not (string-match (regexp-quote (char-to-string c)) s))
  2632. return (char-to-string c))))
  2633. (defun org-e-odt--quotation-marks (text info)
  2634. "Export quotation marks depending on language conventions.
  2635. TEXT is a string containing quotation marks to be replaced. INFO
  2636. is a plist used as a communication channel."
  2637. (mapc (lambda(l)
  2638. (let ((start 0))
  2639. (while (setq start (string-match (car l) text start))
  2640. (let ((new-quote (concat (match-string 1 text) (cdr l))))
  2641. (setq text (replace-match new-quote t t text))))))
  2642. (cdr (or (assoc (plist-get info :language) org-e-odt-quotes)
  2643. ;; Falls back on English.
  2644. (assoc "en" org-e-odt-quotes))))
  2645. text)
  2646. (defun org-e-odt--wrap-label (element output)
  2647. "Wrap label associated to ELEMENT around OUTPUT, if appropriate.
  2648. This function shouldn't be used for floats. See
  2649. `org-e-odt--caption/label-string'."
  2650. ;; (let ((label (org-element-property :name element)))
  2651. ;; (if (or (not output) (not label) (string= output "") (string= label ""))
  2652. ;; output
  2653. ;; (concat (format "\\label{%s}\n" label) output)))
  2654. output)
  2655. ;;; Transcode Helpers
  2656. (defun* org-e-odt-format-headline
  2657. (todo todo-type priority text tags
  2658. &key level section-number headline-label &allow-other-keys)
  2659. (concat (org-e-odt-todo todo) (and todo " ") text
  2660. (and tags (org-e-odt-format-spaces 3))
  2661. (and tags (org-e-odt-format-org-tags tags))))
  2662. ;;;; Src Code
  2663. (defun org-e-odt-htmlfontify-string (line)
  2664. (let* ((hfy-html-quote-regex "\\([<\"&> ]\\)")
  2665. (hfy-html-quote-map '(("\"" "&quot;")
  2666. ("<" "&lt;")
  2667. ("&" "&amp;")
  2668. (">" "&gt;")
  2669. (" " "<text:s/>")
  2670. (" " "<text:tab/>")))
  2671. (hfy-face-to-css 'org-e-odt-hfy-face-to-css)
  2672. (hfy-optimisations-1 (copy-seq hfy-optimisations))
  2673. (hfy-optimisations (add-to-list 'hfy-optimisations-1
  2674. 'body-text-only))
  2675. (hfy-begin-span-handler
  2676. (lambda (style text-block text-id text-begins-block-p)
  2677. (insert (format "<text:span text:style-name=\"%s\">" style))))
  2678. (hfy-end-span-handler (lambda nil (insert "</text:span>"))))
  2679. (htmlfontify-string line)))
  2680. (defun org-e-odt-do-format-code
  2681. (code &optional lang refs retain-labels num-start)
  2682. (let* ((lang (or (assoc-default lang org-src-lang-modes) lang))
  2683. (lang-mode (and lang (intern (format "%s-mode" lang))))
  2684. (code-lines (org-split-string code "\n"))
  2685. (code-length (length code-lines))
  2686. (use-htmlfontify-p (and (functionp lang-mode)
  2687. org-e-odt-fontify-srcblocks
  2688. (require 'htmlfontify nil t)
  2689. (fboundp 'htmlfontify-string)))
  2690. (code (if (not use-htmlfontify-p) code
  2691. (with-temp-buffer
  2692. (insert code)
  2693. (funcall lang-mode)
  2694. (font-lock-fontify-buffer)
  2695. (buffer-string))))
  2696. (fontifier (if use-htmlfontify-p 'org-e-odt-htmlfontify-string
  2697. 'org-e-odt-encode-plain-text))
  2698. (par-style (if use-htmlfontify-p "OrgSrcBlock"
  2699. "OrgFixedWidthBlock"))
  2700. (i 0))
  2701. (assert (= code-length (length (org-split-string code "\n"))))
  2702. (setq code
  2703. (org-export-format-code
  2704. code
  2705. (lambda (loc line-num ref)
  2706. (setq par-style
  2707. (concat par-style (and (= (incf i) code-length) "LastLine")))
  2708. (setq loc (concat loc (and ref retain-labels (format " (%s)" ref))))
  2709. (setq loc (funcall fontifier loc))
  2710. (when ref
  2711. (setq loc (org-e-odt-format-target loc (concat "coderef-" ref))))
  2712. (setq loc (org-e-odt-format-stylized-paragraph par-style loc))
  2713. (if (not line-num) loc
  2714. (org-e-odt-format-tags
  2715. '("<text:list-item>" . "</text:list-item>") loc)))
  2716. num-start refs))
  2717. (cond
  2718. ((not num-start) code)
  2719. ((equal num-start 0)
  2720. (org-e-odt-format-tags
  2721. '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
  2722. . "</text:list>") code " text:continue-numbering=\"false\""))
  2723. (t (org-e-odt-format-tags
  2724. '("<text:list text:style-name=\"OrgSrcBlockNumberedLine\"%s>"
  2725. . "</text:list>") code " text:continue-numbering=\"true\"")))))
  2726. (defun org-e-odt-format-code (element info)
  2727. (let* ((lang (org-element-property :language element))
  2728. ;; Extract code and references.
  2729. (code-info (org-export-unravel-code element))
  2730. (code (car code-info))
  2731. (refs (cdr code-info))
  2732. ;; Does the src block contain labels?
  2733. (retain-labels (org-element-property :retain-labels element))
  2734. ;; Does it have line numbers?
  2735. (num-start (case (org-element-property :number-lines element)
  2736. (continued (org-export-get-loc element info))
  2737. (new 0))))
  2738. (org-e-odt-do-format-code code lang refs retain-labels num-start)))
  2739. ;;; Template
  2740. (defun org-e-odt-template (contents info)
  2741. "Return complete document string after HTML conversion.
  2742. CONTENTS is the transcoded contents string. RAW-DATA is the
  2743. original parsed data. INFO is a plist holding export options."
  2744. ;; write meta file
  2745. (org-e-odt-update-meta-file info)
  2746. (with-temp-buffer
  2747. (insert-file-contents
  2748. (or org-e-odt-content-template-file
  2749. (expand-file-name "OrgOdtContentTemplate.xml"
  2750. org-e-odt-styles-dir)))
  2751. (goto-char (point-min))
  2752. (re-search-forward "</office:text>" nil nil)
  2753. (goto-char (match-beginning 0))
  2754. ;; Title
  2755. (insert (org-e-odt-format-preamble info))
  2756. ;; Table of Contents
  2757. (let ((depth (plist-get info :with-toc)))
  2758. (when (wholenump depth) (insert (org-e-odt-toc depth info))))
  2759. ;; Update styles.xml - take care of outline numbering
  2760. (with-current-buffer
  2761. (find-file-noselect (expand-file-name "styles.xml") t)
  2762. ;; Don't make automatic backup of styles.xml file. This setting
  2763. ;; prevents the backed-up styles.xml file from being zipped in to
  2764. ;; odt file. This is more of a hackish fix. Better alternative
  2765. ;; would be to fix the zip command so that the output odt file
  2766. ;; includes only the needed files and excludes any auto-generated
  2767. ;; extra files like backups and auto-saves etc etc. Note that
  2768. ;; currently the zip command zips up the entire temp directory so
  2769. ;; that any auto-generated files created under the hood ends up in
  2770. ;; the resulting odt file.
  2771. (set (make-local-variable 'backup-inhibited) t)
  2772. (org-e-odt-configure-outline-numbering))
  2773. ;; Contents
  2774. (insert contents)
  2775. (buffer-substring-no-properties (point-min) (point-max))))
  2776. ;;; Transcode Functions
  2777. ;;;; Block
  2778. (defun org-e-odt-center-block (center-block contents info)
  2779. "Transcode a CENTER-BLOCK element from Org to HTML.
  2780. CONTENTS holds the contents of the block. INFO is a plist
  2781. holding contextual information."
  2782. (org-e-odt--wrap-label center-block contents))
  2783. ;;;; Comment
  2784. ;; Comments are ignored.
  2785. ;;;; Comment Block
  2786. ;; Comment Blocks are ignored.
  2787. ;;;; Drawer
  2788. (defun org-e-odt-drawer (drawer contents info)
  2789. "Transcode a DRAWER element from Org to HTML.
  2790. CONTENTS holds the contents of the block. INFO is a plist
  2791. holding contextual information."
  2792. (let* ((name (org-element-property :drawer-name drawer))
  2793. (output (if (functionp org-e-odt-format-drawer-function)
  2794. (funcall org-e-odt-format-drawer-function
  2795. name contents)
  2796. ;; If there's no user defined function: simply
  2797. ;; display contents of the drawer.
  2798. contents)))
  2799. (org-e-odt--wrap-label drawer output)))
  2800. ;;;; Dynamic Block
  2801. (defun org-e-odt-dynamic-block (dynamic-block contents info)
  2802. "Transcode a DYNAMIC-BLOCK element from Org to HTML.
  2803. CONTENTS holds the contents of the block. INFO is a plist
  2804. holding contextual information. See
  2805. `org-export-data'."
  2806. (org-e-odt--wrap-label dynamic-block contents))
  2807. ;;;; Emphasis
  2808. (defun org-e-odt-emphasis (emphasis contents info)
  2809. "Transcode EMPHASIS from Org to HTML.
  2810. CONTENTS is the contents of the emphasized text. INFO is a plist
  2811. holding contextual information.."
  2812. ;; (format (cdr (assoc (org-element-property :marker emphasis)
  2813. ;; org-e-odt-emphasis-alist))
  2814. ;; contents)
  2815. (org-e-odt-format-fontify
  2816. contents (cadr (assoc
  2817. (org-element-property :marker emphasis)
  2818. '(("*" bold)
  2819. ("/" emphasis)
  2820. ("_" underline)
  2821. ("=" code)
  2822. ("~" verbatim)
  2823. ("+" strike))))))
  2824. ;;;; Entity
  2825. (defun org-e-odt-entity (entity contents info)
  2826. "Transcode an ENTITY object from Org to HTML.
  2827. CONTENTS are the definition itself. INFO is a plist holding
  2828. contextual information."
  2829. ;; (let ((ent (org-element-property :latex entity)))
  2830. ;; (if (org-element-property :latex-math-p entity)
  2831. ;; (format "$%s$" ent)
  2832. ;; ent))
  2833. (org-element-property :utf-8 entity))
  2834. ;;;; Example Block
  2835. (defun org-e-odt-example-block (example-block contents info)
  2836. "Transcode a EXAMPLE-BLOCK element from Org to HTML.
  2837. CONTENTS is nil. INFO is a plist holding contextual information."
  2838. (let* ((options (or (org-element-property :options example-block) ""))
  2839. (value (org-export-handle-code example-block info nil nil t)))
  2840. (org-e-odt--wrap-label
  2841. example-block (org-e-odt-format-source-code-or-example value nil))))
  2842. ;;;; Export Snippet
  2843. (defun org-e-odt-export-snippet (export-snippet contents info)
  2844. "Transcode a EXPORT-SNIPPET object from Org to HTML.
  2845. CONTENTS is nil. INFO is a plist holding contextual information."
  2846. (when (eq (org-export-snippet-backend export-snippet) 'e-odt)
  2847. (org-element-property :value export-snippet)))
  2848. ;;;; Export Block
  2849. (defun org-e-odt-export-block (export-block contents info)
  2850. "Transcode a EXPORT-BLOCK element from Org to HTML.
  2851. CONTENTS is nil. INFO is a plist holding contextual information."
  2852. (when (string= (org-element-property :type export-block) "latex")
  2853. (org-remove-indentation (org-element-property :value export-block))))
  2854. ;;;; Fixed Width
  2855. (defun org-e-odt-fixed-width (fixed-width contents info)
  2856. "Transcode a FIXED-WIDTH element from Org to HTML.
  2857. CONTENTS is nil. INFO is a plist holding contextual information."
  2858. (let* ((value (org-element-normalize-string
  2859. (replace-regexp-in-string
  2860. "^[ \t]*: ?" ""
  2861. (org-element-property :value fixed-width)))))
  2862. (org-e-odt--wrap-label
  2863. fixed-width (org-e-odt-format-source-code-or-example value nil))))
  2864. ;;;; Footnote Definition
  2865. ;; Footnote Definitions are ignored.
  2866. ;;;; Footnote Reference
  2867. (defun org-e-odt-footnote-def (raw info) ; FIXME
  2868. (if (equal (org-element-type raw) 'org-data)
  2869. (org-trim (org-export-data raw 'e-odt info)) ; fix paragraph
  2870. ; style
  2871. (org-odt-format-stylized-paragraph
  2872. 'footnote (org-trim (org-export-secondary-string raw 'e-odt info)))))
  2873. (defvar org-e-odt-footnote-separator
  2874. (org-e-odt-format-fontify "," 'superscript))
  2875. (defun org-e-odt-footnote-reference (footnote-reference contents info)
  2876. "Transcode a FOOTNOTE-REFERENCE element from Org to HTML.
  2877. CONTENTS is nil. INFO is a plist holding contextual information."
  2878. (concat
  2879. ;; Insert separator between two footnotes in a row.
  2880. (let ((prev (org-export-get-previous-element footnote-reference info)))
  2881. (when (eq (org-element-type prev) 'footnote-reference)
  2882. org-e-odt-footnote-separator))
  2883. (cond
  2884. ((not (org-export-footnote-first-reference-p footnote-reference info))
  2885. (let* ((n (org-export-get-footnote-number footnote-reference info)))
  2886. (org-e-odt-format-footnote-reference n "IGNORED" 100)))
  2887. ;; Inline definitions are secondary strings.
  2888. ((eq (org-element-property :type footnote-reference) 'inline)
  2889. (let* ((raw (org-export-get-footnote-definition footnote-reference info))
  2890. (n (org-export-get-footnote-number footnote-reference info))
  2891. (def (org-e-odt-footnote-def raw info)))
  2892. (org-e-odt-format-footnote-reference n def 1)))
  2893. ;; Non-inline footnotes definitions are full Org data.
  2894. (t
  2895. (let* ((raw (org-export-get-footnote-definition footnote-reference info))
  2896. (n (org-export-get-footnote-number footnote-reference info))
  2897. (def (org-e-odt-footnote-def raw info)))
  2898. (org-e-odt-format-footnote-reference n def 1))))))
  2899. ;;;; Headline
  2900. (defun org-e-odt-todo (todo)
  2901. (when todo
  2902. (org-e-odt-format-fontify
  2903. (concat
  2904. "" ; org-e-odt-todo-kwd-class-prefix
  2905. (org-e-odt-fix-class-name todo))
  2906. (list (if (member todo org-done-keywords) "done" "todo")
  2907. todo))))
  2908. (defun org-e-odt-format-headline--wrap (headline info
  2909. &optional format-function
  2910. &rest extra-keys)
  2911. "Transcode an HEADLINE element from Org to ODT.
  2912. CONTENTS holds the contents of the headline. INFO is a plist
  2913. holding contextual information."
  2914. (let* ((level (+ (org-export-get-relative-level headline info)))
  2915. (headline-number (org-export-get-headline-number headline info))
  2916. (section-number (and (org-export-numbered-headline-p headline info)
  2917. (mapconcat 'number-to-string
  2918. headline-number ".")))
  2919. (todo (and (plist-get info :with-todo-keywords)
  2920. (let ((todo (org-element-property
  2921. :todo-keyword headline)))
  2922. (and todo
  2923. (org-export-secondary-string todo 'e-odt info)))))
  2924. (todo-type (and todo (org-element-property :todo-type headline)))
  2925. (priority (and (plist-get info :with-priority)
  2926. (org-element-property :priority headline)))
  2927. (text (org-export-secondary-string
  2928. (org-element-property :title headline) 'e-odt info))
  2929. (tags (and (plist-get info :with-tags)
  2930. (org-element-property :tags headline)))
  2931. (headline-label (concat "sec-" (mapconcat 'number-to-string
  2932. headline-number "-")))
  2933. (format-function (cond
  2934. ((functionp format-function) format-function)
  2935. ((functionp org-e-odt-format-headline-function)
  2936. (function*
  2937. (lambda (todo todo-type priority text tags
  2938. &allow-other-keys)
  2939. (funcall org-e-odt-format-headline-function
  2940. todo todo-type priority text tags))))
  2941. (t 'org-e-odt-format-headline))))
  2942. (apply format-function
  2943. todo todo-type priority text tags
  2944. :headline-label headline-label :level level
  2945. :section-number section-number extra-keys)))
  2946. (defun org-e-odt-headline (headline contents info)
  2947. "Transcode an HEADLINE element from Org to HTML.
  2948. CONTENTS holds the contents of the headline. INFO is a plist
  2949. holding contextual information."
  2950. (let* ((numberedp (org-export-numbered-headline-p headline info))
  2951. ;; Get level relative to current parsed data.
  2952. (level (org-export-get-relative-level headline info))
  2953. (text (org-export-secondary-string
  2954. (org-element-property :title headline) 'e-odt info))
  2955. ;; Create the headline text.
  2956. (full-text (org-e-odt-format-headline--wrap headline info)))
  2957. (cond
  2958. ;; Case 1: This is a footnote section: ignore it.
  2959. ((org-element-property :footnote-section-p headline) nil)
  2960. ;; Case 2. This is a deep sub-tree: export it as a list item.
  2961. ;; Also export as items headlines for which no section
  2962. ;; format has been found.
  2963. ((org-export-low-level-p headline info) ; FIXME (or (not section-fmt))
  2964. ;; Build the real contents of the sub-tree.
  2965. (let* ((type (if numberedp 'unordered 'unordered)) ; FIXME
  2966. (itemized-body (org-e-odt-format-list-item
  2967. contents type nil nil full-text)))
  2968. (concat
  2969. (and (org-export-first-sibling-p headline info)
  2970. (org-e-odt-begin-plain-list type))
  2971. itemized-body
  2972. (and (org-export-last-sibling-p headline info)
  2973. (org-e-odt-end-plain-list type)))))
  2974. ;; Case 3. Standard headline. Export it as a section.
  2975. (t
  2976. (let* ((extra-ids (list (org-element-property :custom-id headline)
  2977. (org-element-property :id headline)))
  2978. (extra-ids nil) ; FIXME
  2979. (id (concat "sec-" (mapconcat 'number-to-string
  2980. (org-export-get-headline-number
  2981. headline info) "-"))))
  2982. (concat
  2983. (org-e-odt-format-tags
  2984. '("<text:h text:style-name=\"Heading_20_%s\" text:outline-level=\"%s\">" .
  2985. "</text:h>")
  2986. (concat (org-e-odt-format-extra-targets extra-ids)
  2987. (if (not id) full-text (org-e-odt-format-target full-text id) ))
  2988. level level)
  2989. contents))))))
  2990. ;;;; Horizontal Rule
  2991. (defun org-e-odt-horizontal-rule (horizontal-rule contents info)
  2992. "Transcode an HORIZONTAL-RULE object from Org to HTML.
  2993. CONTENTS is nil. INFO is a plist holding contextual information."
  2994. (let ((attr (mapconcat #'identity
  2995. (org-element-property :attr_odt horizontal-rule)
  2996. " ")))
  2997. (org-e-odt--wrap-label horizontal-rule
  2998. (org-e-odt-format-horizontal-line))))
  2999. ;;;; Inline Babel Call
  3000. ;; Inline Babel Calls are ignored.
  3001. ;;;; Inline Src Block
  3002. (defun org-e-odt-inline-src-block (inline-src-block contents info)
  3003. "Transcode an INLINE-SRC-BLOCK element from Org to HTML.
  3004. CONTENTS holds the contents of the item. INFO is a plist holding
  3005. contextual information."
  3006. (let* ((org-lang (org-element-property :language inline-src-block))
  3007. (code (org-element-property :value inline-src-block))
  3008. (separator (org-e-odt--find-verb-separator code)))
  3009. (error "FIXME")))
  3010. ;;;; Inlinetask
  3011. (defun org-e-odt-format-section (text class &optional id)
  3012. (let ((extra (concat (when id (format " id=\"%s\"" id)))))
  3013. (concat (format "<div class=\"%s\"%s>\n" class extra) text "</div>\n")))
  3014. (defun org-e-odt-inlinetask (inlinetask contents info)
  3015. "Transcode an INLINETASK element from Org to ODT.
  3016. CONTENTS holds the contents of the block. INFO is a plist
  3017. holding contextual information."
  3018. (cond
  3019. ;; If `org-e-odt-format-inlinetask-function' is provided, call it
  3020. ;; with appropriate arguments.
  3021. ((functionp org-e-odt-format-inlinetask-function)
  3022. (let ((format-function
  3023. (function*
  3024. (lambda (todo todo-type priority text tags
  3025. &key contents &allow-other-keys)
  3026. (funcall org-e-odt-format-inlinetask-function
  3027. todo todo-type priority text tags contents)))))
  3028. (org-e-odt-format-headline--wrap
  3029. inlinetask info format-function :contents contents)))
  3030. ;; Otherwise, use a default template.
  3031. (t (org-e-odt--wrap-label
  3032. inlinetask
  3033. (org-e-odt-format-stylized-paragraph
  3034. nil (org-e-odt-format-textbox
  3035. (concat (org-e-odt-format-stylized-paragraph
  3036. "OrgInlineTaskHeading" (org-e-odt-format-headline--wrap
  3037. inlinetask info))
  3038. contents)
  3039. nil nil "OrgInlineTaskFrame" " style:rel-width=\"100%\""))))))
  3040. ;;;; Item
  3041. (defun org-e-odt-format-list-item (contents type checkbox
  3042. &optional term-counter-id
  3043. headline)
  3044. (when checkbox
  3045. (setq checkbox
  3046. (org-e-odt-format-fontify (case checkbox
  3047. (on "[X]")
  3048. (off "[&nbsp;]")
  3049. (trans "[-]")) 'code)))
  3050. (concat
  3051. (org-e-odt-begin-list-item type term-counter-id headline)
  3052. ;; FIXME checkbox (and checkbox " ")
  3053. contents
  3054. (org-e-odt-end-list-item type)))
  3055. (defun org-e-odt-item (item contents info)
  3056. "Transcode an ITEM element from Org to HTML.
  3057. CONTENTS holds the contents of the item. INFO is a plist holding
  3058. contextual information."
  3059. ;; Grab `:level' from plain-list properties, which is always the
  3060. ;; first element above current item.
  3061. (let* ((plain-list (org-export-get-parent item info))
  3062. (type (org-element-property :type plain-list))
  3063. (level (org-element-property :level plain-list))
  3064. (counter (org-element-property :counter item))
  3065. (checkbox (org-element-property :checkbox item))
  3066. (tag (let ((tag (org-element-property :tag item)))
  3067. (and tag (org-export-secondary-string tag 'e-odt info)))))
  3068. (org-e-odt-format-list-item
  3069. contents type checkbox (or tag counter))))
  3070. ;;;; Keyword
  3071. (defun org-e-odt-keyword (keyword contents info)
  3072. "Transcode a KEYWORD element from Org to HTML.
  3073. CONTENTS is nil. INFO is a plist holding contextual information."
  3074. (let ((key (org-element-property :key keyword))
  3075. (value (org-element-property :value keyword)))
  3076. (cond
  3077. ((string= key "LATEX") value)
  3078. ((string= key "INDEX") (format "\\index{%s}" value))
  3079. ((string= key "TARGET") nil ; FIXME
  3080. ;; (format "\\label{%s}" (org-export-solidify-link-text value))
  3081. )
  3082. ((string= key "toc")
  3083. (let ((value (downcase value)))
  3084. (cond
  3085. ((string-match "\\<headlines\\>" value)
  3086. (let ((depth (or (and (string-match "[0-9]+" value)
  3087. (string-to-number (match-string 0 value)))
  3088. (plist-get info :with-toc))))
  3089. (when (wholenump depth) (org-e-odt-toc depth info))))
  3090. ((string= "tables" value) "FIXME")
  3091. ((string= "figures" value) "FIXME")
  3092. ((string= "listings" value)
  3093. (cond
  3094. ;; At the moment, src blocks with a caption are wrapped
  3095. ;; into a figure environment.
  3096. (t "FIXME")))))))))
  3097. ;;;; Latex Environment
  3098. (defun org-e-odt-format-latex (latex-frag processing-type)
  3099. (let* ((prefix (case processing-type
  3100. (dvipng "ltxpng/")
  3101. (mathml "ltxmathml/")))
  3102. (cache-relpath
  3103. (concat prefix (file-name-sans-extension
  3104. (file-name-nondirectory (buffer-file-name)))))
  3105. (cache-dir (file-name-directory (buffer-file-name )))
  3106. (display-msg (case processing-type
  3107. (dvipng "Creating LaTeX Image...")
  3108. (mathml "Creating MathML snippet..."))))
  3109. (with-temp-buffer
  3110. (insert latex-frag)
  3111. (org-format-latex cache-relpath cache-dir nil display-msg
  3112. nil nil processing-type)
  3113. (buffer-string))))
  3114. (defun org-e-odt-latex-environment (latex-environment contents info)
  3115. "Transcode a LATEX-ENVIRONMENT element from Org to HTML.
  3116. CONTENTS is nil. INFO is a plist holding contextual information."
  3117. (org-e-odt--wrap-label
  3118. latex-environment
  3119. (let* ((latex-frag
  3120. (org-remove-indentation
  3121. (org-element-property :value latex-environment)))
  3122. (processing-type (plist-get info :LaTeX-fragments))
  3123. (caption (org-element-property :caption latex-environment))
  3124. (short-caption (and (cdr caption) (org-export-secondary-string
  3125. (cdr caption) 'e-odt info)))
  3126. (caption (and (car caption) (org-export-secondary-string
  3127. (car caption) 'e-odt info)))
  3128. (label (org-element-property :name latex-environment))
  3129. (attr nil) ; FIXME
  3130. (label (org-element-property :name latex-environment)))
  3131. (cond
  3132. ((member processing-type '(t mathjax))
  3133. (org-e-odt-format-latex latex-frag 'mathml))
  3134. ((equal processing-type 'dvipng)
  3135. (let* ((formula-link (org-e-odt-format-latex
  3136. latex-frag processing-type)))
  3137. (when (and formula-link
  3138. (string-match "file:\\([^]]*\\)" formula-link))
  3139. (org-e-odt-format-image
  3140. (match-string 1 formula-link) caption label attr "paragraph"
  3141. "__DvipngImage__"))))
  3142. (t latex-frag)))))
  3143. ;;;; Latex Fragment
  3144. (defun org-e-odt-latex-fragment (latex-fragment contents info)
  3145. "Transcode a LATEX-FRAGMENT object from Org to HTML.
  3146. CONTENTS is nil. INFO is a plist holding contextual information."
  3147. (let* ((latex-frag (org-element-property :value latex-fragment))
  3148. (processing-type (plist-get info :LaTeX-fragments)))
  3149. (cond
  3150. ((member processing-type '(t mathjax))
  3151. (org-e-odt-format-latex latex-frag 'mathml))
  3152. ((equal processing-type 'dvipng)
  3153. (let* ((formula-link (org-e-odt-format-latex latex-frag processing-type))
  3154. (src (and formula-link
  3155. (string-match "file:\\([^]]*\\)" formula-link)
  3156. (match-string 1 formula-link))))
  3157. (assert src)
  3158. (org-e-odt-format-image src)))
  3159. (t latex-frag))))
  3160. ;;;; Line Break
  3161. (defun org-e-odt-line-break (line-break contents info)
  3162. "Transcode a LINE-BREAK object from Org to HTML.
  3163. CONTENTS is nil. INFO is a plist holding contextual information."
  3164. "<text:line-break/>\n")
  3165. ;;;; Link
  3166. (defun org-e-odt-link--inline-image (link desc info)
  3167. "Return HTML code for an inline image.
  3168. LINK is the link pointing to the inline image. INFO is a plist
  3169. used as a communication channel."
  3170. (let* ((type (org-element-property :type link))
  3171. (raw-path (org-element-property :path link))
  3172. (path (cond ((member type '("http" "https"))
  3173. (concat type ":" raw-path))
  3174. ((file-name-absolute-p raw-path)
  3175. (expand-file-name raw-path))
  3176. (t raw-path)))
  3177. (parent (org-export-get-parent-paragraph link info))
  3178. (caption (org-element-property :caption parent))
  3179. (short-caption (and (cdr caption) (org-export-secondary-string
  3180. (cdr caption) 'e-odt info)))
  3181. (caption (and (car caption) (org-export-secondary-string
  3182. (car caption) 'e-odt info)))
  3183. (label (org-element-property :name parent))
  3184. ;; Retrieve latex attributes from the element around.
  3185. (attr (let ((raw-attr
  3186. (mapconcat #'identity
  3187. (org-element-property :attr_odt parent)
  3188. " ")))
  3189. (unless (string= raw-attr "") raw-attr))))
  3190. ;; Now clear ATTR from any special keyword and set a default
  3191. ;; value if nothing is left.
  3192. (setq attr (if (not attr) "" (org-trim attr)))
  3193. ;; Return proper string, depending on DISPOSITION.
  3194. (org-e-odt-format-image
  3195. path caption label attr (if (org-e-html-standalone-image-p link info)
  3196. "paragraph" "as-char"))))
  3197. (defvar org-e-odt-standalone-image-predicate
  3198. (function (lambda (paragraph)
  3199. (or (org-element-property :caption paragraph)
  3200. (org-element-property :name paragraph)))))
  3201. (defun org-e-odt-standalone-image-p (element info &optional predicate)
  3202. "Test if ELEMENT is a standalone image for the purpose ODT export.
  3203. INFO is a plist holding contextual information.
  3204. Return non-nil, if ELEMENT is of type paragraph and it's sole
  3205. content, save for whitespaces, is a link that qualifies as an
  3206. inline image.
  3207. Return non-nil, if ELEMENT is of type link and it's containing
  3208. paragraph has no other content save for leading and trailing
  3209. whitespaces.
  3210. Return nil, otherwise.
  3211. Bind `org-e-odt-standalone-image-predicate' to constrain
  3212. paragraph further. For example, to check for only captioned
  3213. standalone images, do the following.
  3214. \(setq org-e-odt-standalone-image-predicate
  3215. \(lambda \(paragraph\)
  3216. \(org-element-property :caption paragraph\)\)\)
  3217. "
  3218. (let ((paragraph (case (org-element-type element)
  3219. (paragraph element)
  3220. (link (and (org-export-inline-image-p
  3221. element org-e-odt-inline-image-rules)
  3222. (org-export-get-parent element info)))
  3223. (t nil))))
  3224. (when paragraph
  3225. (assert (eq (org-element-type paragraph) 'paragraph))
  3226. (when (or (not (and (boundp 'org-e-odt-standalone-image-predicate)
  3227. (functionp org-e-odt-standalone-image-predicate)))
  3228. (funcall org-e-odt-standalone-image-predicate paragraph))
  3229. (let ((contents (org-element-contents paragraph)))
  3230. (loop for x in contents
  3231. with inline-image-count = 0
  3232. always (cond
  3233. ((eq (org-element-type x) 'plain-text)
  3234. (not (org-string-nw-p x)))
  3235. ((eq (org-element-type x) 'link)
  3236. (when (org-export-inline-image-p
  3237. x org-e-odt-inline-image-rules)
  3238. (= (incf inline-image-count) 1)))
  3239. (t nil))))))))
  3240. (defun org-e-odt-link (link desc info)
  3241. "Transcode a LINK object from Org to HTML.
  3242. DESC is the description part of the link, or the empty string.
  3243. INFO is a plist holding contextual information. See
  3244. `org-export-data'."
  3245. (let* ((type (org-element-property :type link))
  3246. (raw-path (org-element-property :path link))
  3247. ;; Ensure DESC really exists, or set it to nil.
  3248. (desc (and (not (string= desc "")) desc))
  3249. (imagep (org-export-inline-image-p
  3250. link org-e-odt-inline-image-rules))
  3251. (path (cond
  3252. ((member type '("http" "https" "ftp" "mailto"))
  3253. (concat type ":" raw-path))
  3254. ((string= type "file")
  3255. (when (string-match "\\(.+\\)::.+" raw-path)
  3256. (setq raw-path (match-string 1 raw-path)))
  3257. (if (file-name-absolute-p raw-path)
  3258. (concat "file://" (expand-file-name raw-path))
  3259. ;; TODO: Not implemented yet. Concat also:
  3260. ;; (org-export-directory :HTML info)
  3261. (concat "file://" raw-path)))
  3262. (t raw-path)))
  3263. protocol)
  3264. (cond
  3265. ;; Image file.
  3266. ((and (not desc) (org-export-inline-image-p
  3267. link org-e-odt-inline-image-rules))
  3268. (org-e-odt-link--inline-image link desc info))
  3269. ;; Radioed target: Target's name is obtained from original raw
  3270. ;; link. Path is parsed and transcoded in order to have a proper
  3271. ;; display of the contents.
  3272. ((string= type "radio")
  3273. (org-e-odt-format-internal-link
  3274. (org-export-secondary-string
  3275. (org-element-parse-secondary-string
  3276. path (cdr (assq 'radio-target org-element-object-restrictions)))
  3277. 'e-odt info)
  3278. (org-export-solidify-link-text path)))
  3279. ;; Links pointing to an headline: Find destination and build
  3280. ;; appropriate referencing command.
  3281. ((member type '("custom-id" "fuzzy" "id"))
  3282. (let ((destination (if (string= type "fuzzy")
  3283. (org-export-resolve-fuzzy-link link info)
  3284. (org-export-resolve-id-link link info))))
  3285. (case (org-element-type destination)
  3286. ;; Fuzzy link points nowhere.
  3287. ('nil
  3288. (org-e-odt-format-fontify
  3289. (or desc (org-export-secondary-string
  3290. (org-element-property :raw-link link)
  3291. 'e-odt info)) 'emphasis))
  3292. ;; Fuzzy link points to an invisible target.
  3293. (keyword nil)
  3294. ;; LINK points to an headline. If headlines are numbered
  3295. ;; and the link has no description, display headline's
  3296. ;; number. Otherwise, display description or headline's
  3297. ;; title.
  3298. (headline
  3299. (let* ((headline-no (org-export-get-headline-number destination info))
  3300. (label (format "sec-%s" (mapconcat 'number-to-string
  3301. headline-no "-")))
  3302. (section-no (mapconcat 'number-to-string headline-no ".")))
  3303. (setq desc
  3304. (cond
  3305. (desc desc)
  3306. ((plist-get info :section-numbers) section-no)
  3307. (t (org-export-secondary-string
  3308. (org-element-property :title destination)
  3309. 'e-odt info))))
  3310. (org-e-odt-format-internal-link desc label)))
  3311. ;; Fuzzy link points to a target. Do as above.
  3312. (otherwise
  3313. ;; "__Table__"
  3314. ;; "__Figure__"
  3315. ;; "__MathFormula__"
  3316. ;; "__DvipngImage__"
  3317. (let ((path (org-export-solidify-link-text path)))
  3318. (unless desc
  3319. (setq number (cond
  3320. ((org-e-odt-standalone-image-p destination info)
  3321. (org-export-get-ordinal
  3322. (assoc 'link (org-element-contents destination))
  3323. info 'link 'org-e-odt-standalone-image-p))
  3324. (t (org-export-get-ordinal destination info))))
  3325. (setq desc (when number
  3326. (if (atom number) (number-to-string number)
  3327. (mapconcat 'number-to-string number ".")))))
  3328. (let ((label path)
  3329. (default-category
  3330. (cond
  3331. ((eq (org-element-type destination) 'table)
  3332. "__Table__")
  3333. ((org-e-odt-standalone-image-p destination info)
  3334. "__Figure__")
  3335. (t (error "Handle enumeration of %S" destination)))))
  3336. (org-e-odt-format-label-reference label default-category number)))))))
  3337. ;; Coderef: replace link with the reference name or the
  3338. ;; equivalent line number.
  3339. ((string= type "coderef")
  3340. (let* ((fmt (org-export-get-coderef-format path (or desc "%s")))
  3341. (res (org-export-resolve-coderef path info))
  3342. (org-e-odt-suppress-xref nil)
  3343. (href (org-xml-format-href (concat "#coderef-" path))))
  3344. (format fmt (org-e-odt-format-link res href))))
  3345. ;; Link type is handled by a special function.
  3346. ((functionp (setq protocol (nth 2 (assoc type org-link-protocols))))
  3347. (funcall protocol (org-link-unescape path) desc 'html))
  3348. ;; External link with a description part.
  3349. ((and path desc) (org-e-odt-format-link desc path))
  3350. ;; External link without a description part.
  3351. (path (org-e-odt-format-link path path))
  3352. ;; No path, only description. Try to do something useful.
  3353. (t (org-e-odt-format-fontify desc 'emphasis)))))
  3354. ;;;; Babel Call
  3355. ;; Babel Calls are ignored.
  3356. ;;;; Macro
  3357. (defun org-e-odt-macro (macro contents info)
  3358. "Transcode a MACRO element from Org to HTML.
  3359. CONTENTS is nil. INFO is a plist holding contextual information."
  3360. ;; Use available tools.
  3361. (org-export-expand-macro macro info))
  3362. ;;;; Paragraph
  3363. (defun org-e-odt-paragraph (paragraph contents info)
  3364. "Transcode a PARAGRAPH element from Org to HTML.
  3365. CONTENTS is the contents of the paragraph, as a string. INFO is
  3366. the plist used as a communication channel."
  3367. (let* ((style nil) ; FIXME
  3368. (class (cdr (assoc style '((footnote . "footnote")
  3369. (verse . nil)))))
  3370. (extra (if class (format " class=\"%s\"" class) ""))
  3371. (parent (org-export-get-parent paragraph info))
  3372. (parent-type (org-element-type parent))
  3373. (style (case parent-type
  3374. (quote-block 'quote)
  3375. (center-block 'center)
  3376. (footnote-definition 'footnote)
  3377. (t nil))))
  3378. (org-e-odt-format-stylized-paragraph style contents)))
  3379. ;;;; Plain List
  3380. (defun org-e-odt-plain-list (plain-list contents info)
  3381. "Transcode a PLAIN-LIST element from Org to HTML.
  3382. CONTENTS is the contents of the list. INFO is a plist holding
  3383. contextual information."
  3384. (let* (arg1 ;; FIXME
  3385. (type (org-element-property :type plain-list))
  3386. (attr (mapconcat #'identity
  3387. (org-element-property :attr_odt plain-list)
  3388. " ")))
  3389. (org-e-odt--wrap-label
  3390. plain-list (format "%s\n%s%s"
  3391. (org-e-odt-begin-plain-list type)
  3392. contents (org-e-odt-end-plain-list type)))))
  3393. ;;;; Plain Text
  3394. (defun org-e-odt-convert-special-strings (string)
  3395. "Convert special characters in STRING to ODT."
  3396. (let ((all org-e-odt-special-string-regexps)
  3397. e a re rpl start)
  3398. (while (setq a (pop all))
  3399. (setq re (car a) rpl (cdr a) start 0)
  3400. (while (string-match re string start)
  3401. (setq string (replace-match rpl t nil string))))
  3402. string))
  3403. ;; (defun org-e-odt-encode-plain-text (s)
  3404. ;; "Convert plain text characters to HTML equivalent.
  3405. ;; Possible conversions are set in `org-export-html-protect-char-alist'."
  3406. ;; (let ((cl org-e-odt-protect-char-alist) c)
  3407. ;; (while (setq c (pop cl))
  3408. ;; (let ((start 0))
  3409. ;; (while (string-match (car c) s start)
  3410. ;; (setq s (replace-match (cdr c) t t s)
  3411. ;; start (1+ (match-beginning 0))))))
  3412. ;; s))
  3413. (defun org-e-odt-plain-text (text info)
  3414. "Transcode a TEXT string from Org to HTML.
  3415. TEXT is the string to transcode. INFO is a plist holding
  3416. contextual information."
  3417. (setq text (org-e-odt-encode-plain-text text t))
  3418. ;; Protect %, #, &, $, ~, ^, _, { and }.
  3419. ;; (while (string-match "\\([^\\]\\|^\\)\\([%$#&{}~^_]\\)" text)
  3420. ;; (setq text
  3421. ;; (replace-match (format "\\%s" (match-string 2 text)) nil t text 2)))
  3422. ;; Protect \
  3423. ;; (setq text (replace-regexp-in-string
  3424. ;; "\\(?:[^\\]\\|^\\)\\(\\\\\\)\\(?:[^%$#&{}~^_\\]\\|$\\)"
  3425. ;; "$\\backslash$" text nil t 1))
  3426. ;; HTML into \HTML{} and TeX into \TeX{}.
  3427. ;; (let ((case-fold-search nil)
  3428. ;; (start 0))
  3429. ;; (while (string-match "\\<\\(\\(?:La\\)?TeX\\)\\>" text start)
  3430. ;; (setq text (replace-match
  3431. ;; (format "\\%s{}" (match-string 1 text)) nil t text)
  3432. ;; start (match-end 0))))
  3433. ;; Handle quotation marks
  3434. ;; (setq text (org-e-odt--quotation-marks text info))
  3435. ;; Convert special strings.
  3436. ;; (when (plist-get info :with-special-strings)
  3437. ;; (while (string-match (regexp-quote "...") text)
  3438. ;; (setq text (replace-match "\\ldots{}" nil t text))))
  3439. (when (plist-get info :with-special-strings)
  3440. (setq text (org-e-odt-convert-special-strings text)))
  3441. ;; Handle break preservation if required.
  3442. (when (plist-get info :preserve-breaks)
  3443. (setq text (replace-regexp-in-string "\\(\\\\\\\\\\)?[ \t]*\n" " \\\\\\\\\n"
  3444. text)))
  3445. ;; Return value.
  3446. text)
  3447. ;;;; Property Drawer
  3448. (defun org-e-odt-property-drawer (property-drawer contents info)
  3449. "Transcode a PROPERTY-DRAWER element from Org to HTML.
  3450. CONTENTS is nil. INFO is a plist holding contextual
  3451. information."
  3452. ;; The property drawer isn't exported but we want separating blank
  3453. ;; lines nonetheless.
  3454. "")
  3455. ;;;; Quote Block
  3456. (defun org-e-odt-quote-block (quote-block contents info)
  3457. "Transcode a QUOTE-BLOCK element from Org to HTML.
  3458. CONTENTS holds the contents of the block. INFO is a plist
  3459. holding contextual information."
  3460. (org-e-odt--wrap-label quote-block contents))
  3461. ;;;; Quote Section
  3462. (defun org-e-odt-quote-section (quote-section contents info)
  3463. "Transcode a QUOTE-SECTION element from Org to HTML.
  3464. CONTENTS is nil. INFO is a plist holding contextual information."
  3465. (let ((value (org-remove-indentation
  3466. (org-element-property :value quote-section))))
  3467. (when value (org-e-odt-format-source-code-or-example value nil))))
  3468. ;;;; Section
  3469. (defun org-e-odt-section (section contents info) ; FIXME
  3470. "Transcode a SECTION element from Org to HTML.
  3471. CONTENTS holds the contents of the section. INFO is a plist
  3472. holding contextual information."
  3473. contents)
  3474. ;;;; Radio Target
  3475. (defun org-e-odt-radio-target (radio-target text info)
  3476. "Transcode a RADIO-TARGET object from Org to HTML.
  3477. TEXT is the text of the target. INFO is a plist holding
  3478. contextual information."
  3479. (org-e-odt-format-anchor
  3480. text (org-export-solidify-link-text
  3481. (org-element-property :value radio-target))))
  3482. ;;;; Special Block
  3483. (defun org-e-odt-special-block (special-block contents info)
  3484. "Transcode a SPECIAL-BLOCK element from Org to HTML.
  3485. CONTENTS holds the contents of the block. INFO is a plist
  3486. holding contextual information."
  3487. (let ((type (downcase (org-element-property :type special-block))))
  3488. (org-e-odt--wrap-label
  3489. special-block
  3490. (format "\\begin{%s}\n%s\\end{%s}" type contents type))))
  3491. ;;;; Src Block
  3492. (defun org-e-odt-src-block (src-block contents info)
  3493. "Transcode a SRC-BLOCK element from Org to HTML.
  3494. CONTENTS holds the contents of the item. INFO is a plist holding
  3495. contextual information."
  3496. (let* ((lang (org-element-property :language src-block))
  3497. (caption (org-element-property :caption src-block))
  3498. (label (org-element-property :name src-block)))
  3499. ;; FIXME: Handle caption
  3500. ;; caption-str (when caption)
  3501. ;; (main (org-export-secondary-string (car caption) 'e-odt info))
  3502. ;; (secondary (org-export-secondary-string (cdr caption) 'e-odt info))
  3503. ;; (caption-str (org-e-odt--caption/label-string caption label info))
  3504. (org-e-odt-format-code src-block info)))
  3505. ;;;; Statistics Cookie
  3506. (defun org-e-odt-statistics-cookie (statistics-cookie contents info)
  3507. "Transcode a STATISTICS-COOKIE object from Org to HTML.
  3508. CONTENTS is nil. INFO is a plist holding contextual information."
  3509. (let ((cookie-value (org-element-property :value statistics-cookie)))
  3510. (org-e-odt-format-fontify cookie-value 'code)))
  3511. ;;;; Subscript
  3512. (defun org-e-odt-subscript (subscript contents info)
  3513. "Transcode a SUBSCRIPT object from Org to HTML.
  3514. CONTENTS is the contents of the object. INFO is a plist holding
  3515. contextual information."
  3516. ;; (format (if (= (length contents) 1) "$_%s$" "$_{\\mathrm{%s}}$") contents)
  3517. (org-e-odt-format-fontify contents 'subscript))
  3518. ;;;; Superscript
  3519. (defun org-e-odt-superscript (superscript contents info)
  3520. "Transcode a SUPERSCRIPT object from Org to HTML.
  3521. CONTENTS is the contents of the object. INFO is a plist holding
  3522. contextual information."
  3523. ;; (format (if (= (length contents) 1) "$^%s$" "$^{\\mathrm{%s}}$") contents)
  3524. (org-e-odt-format-fontify contents 'superscript))
  3525. ;;;; Table
  3526. (defun org-e-odt-get-colwidth (c)
  3527. (let ((col-widths (plist-get table-info :width)))
  3528. (or (and org-lparse-table-is-styled (aref col-widths c)) 0)))
  3529. (defun org-e-odt-table-row (fields &optional text-for-empty-fields)
  3530. (incf org-e-odt-table-rownum)
  3531. (let ((i -1))
  3532. (org-e-odt-format-table-row
  3533. (mapconcat
  3534. (lambda (x)
  3535. (when (and (string= x "") text-for-empty-fields)
  3536. (setq x text-for-empty-fields))
  3537. (incf i)
  3538. (let ((horiz-span (org-e-odt-get-colwidth i)))
  3539. (org-e-odt-format-table-cell
  3540. x org-e-odt-table-rownum i horiz-span)))
  3541. fields "\n"))))
  3542. (defun org-e-odt-table-preamble ()
  3543. (let ((colgroup-vector (plist-get table-info :column-groups)) ;; FIXME
  3544. c gr colgropen preamble)
  3545. (unless (aref colgroup-vector 0)
  3546. (setf (aref colgroup-vector 0) 'start))
  3547. (dotimes (c columns-number preamble)
  3548. (setq gr (aref colgroup-vector c))
  3549. (setq preamble
  3550. (concat
  3551. preamble
  3552. (when (memq gr '(start start-end))
  3553. (prog1 (if colgropen "</colgroup>\n<colgroup>" "\n<colgroup>")
  3554. (setq colgropen t)))
  3555. (let* ((colalign-vector (plist-get table-info :alignment)) ;; FIXME
  3556. (align (cdr (assoc (aref colalign-vector c)
  3557. '(("l" . "left")
  3558. ("r" . "right")
  3559. ("c" . "center")))))
  3560. (alignspec (if (and (boundp 'org-e-odt-format-table-no-css)
  3561. org-e-odt-format-table-no-css)
  3562. " align=\"%s\"" " class=\"%s\""))
  3563. (extra (format alignspec align)))
  3564. (format "<col%s />" extra))
  3565. (when (memq gr '(end start-end))
  3566. (setq colgropen nil)
  3567. "</colgroup>"))))
  3568. (concat preamble (if colgropen "</colgroup>"))))
  3569. (defun org-e-odt-list-table (lines caption label attributes)
  3570. (setq lines (org-e-odt-org-table-to-list-table lines))
  3571. (let* ((splice nil) head
  3572. (org-e-odt-table-rownum -1)
  3573. i (cnt 0)
  3574. fields line
  3575. org-e-odt-table-cur-rowgrp-is-hdr
  3576. org-e-odt-table-rowgrp-open
  3577. n
  3578. (org-lparse-table-style 'org-table)
  3579. org-lparse-table-is-styled)
  3580. (cond
  3581. (splice
  3582. (setq org-lparse-table-is-styled nil)
  3583. (mapconcat 'org-e-odt-table-row lines "\n"))
  3584. (t
  3585. (setq org-lparse-table-is-styled t)
  3586. (concat
  3587. (org-e-odt-begin-table caption label attributes)
  3588. ;; FIXME (org-e-odt-table-preamble)
  3589. (org-e-odt-begin-table-rowgroup head)
  3590. (mapconcat
  3591. (lambda (line)
  3592. (cond
  3593. ((equal line 'hline) (org-e-odt-begin-table-rowgroup))
  3594. (t (org-e-odt-table-row line))))
  3595. lines "\n")
  3596. (org-e-odt-end-table-rowgroup)
  3597. (org-e-odt-end-table))))))
  3598. (defun org-e-odt-transcode-table-row (row)
  3599. (if (string-match org-table-hline-regexp row) 'hline
  3600. (mapcar
  3601. (lambda (cell)
  3602. (org-export-secondary-string
  3603. (let ((cell (org-element-parse-secondary-string
  3604. cell
  3605. (cdr (assq 'table org-element-string-restrictions)))))
  3606. cell)
  3607. 'e-odt info))
  3608. (org-split-string row "[ \t]*|[ \t]*"))))
  3609. (defun org-e-odt-org-table-to-list-table (lines &optional splice)
  3610. "Convert org-table to list-table.
  3611. LINES is a list of the form (ROW1 ROW2 ROW3 ...) where each
  3612. element is a `string' representing a single row of org-table.
  3613. Thus each ROW has vertical separators \"|\" separating the table
  3614. fields. A ROW could also be a row-group separator of the form
  3615. \"|---...|\". Return a list of the form (ROW1 ROW2 ROW3
  3616. ...). ROW could either be symbol `'hline' or a list of the
  3617. form (FIELD1 FIELD2 FIELD3 ...) as appropriate."
  3618. (let (line lines-1)
  3619. (cond
  3620. (splice
  3621. (while (setq line (pop lines))
  3622. (unless (string-match "^[ \t]*|-" line)
  3623. (push (org-e-odt-transcode-table-row line) lines-1))))
  3624. (t (while (setq line (pop lines))
  3625. (cond
  3626. ((string-match "^[ \t]*|-" line)
  3627. (when lines (push 'hline lines-1)))
  3628. (t (push (org-e-odt-transcode-table-row line) lines-1))))))
  3629. (nreverse lines-1)))
  3630. (defun org-e-odt-table-table (raw-table)
  3631. (require 'table)
  3632. (with-current-buffer (get-buffer-create "*org-export-table*")
  3633. (erase-buffer))
  3634. (let ((output (with-temp-buffer
  3635. (insert raw-table)
  3636. (goto-char 1)
  3637. (re-search-forward "^[ \t]*|[^|]" nil t)
  3638. (table-generate-source 'html "*org-export-table*")
  3639. (with-current-buffer "*org-export-table*"
  3640. (org-trim (buffer-string))))))
  3641. (kill-buffer (get-buffer "*org-export-table*"))
  3642. output))
  3643. (defun org-e-odt-table (table contents info)
  3644. "Transcode a TABLE element from Org to HTML.
  3645. CONTENTS is nil. INFO is a plist holding contextual information."
  3646. (let* ((label (org-element-property :name table))
  3647. (caption (org-e-odt--caption/label-string
  3648. (org-element-property :caption table) label info))
  3649. (attr (mapconcat #'identity
  3650. (org-element-property :attr_odt table)
  3651. " "))
  3652. (raw-table (org-element-property :raw-table table))
  3653. (table-type (org-element-property :type table)))
  3654. (case table-type
  3655. (table.el
  3656. ;; (org-e-odt-table-table raw-table)
  3657. )
  3658. (t
  3659. (let* ((table-info (org-export-table-format-info raw-table))
  3660. (columns-number (length (plist-get table-info :alignment)))
  3661. (lines (org-split-string
  3662. (org-export-clean-table
  3663. raw-table (plist-get table-info :special-column-p)) "\n"))
  3664. (genealogy (org-export-get-genealogy table info))
  3665. (parent (car genealogy))
  3666. (parent-type (org-element-type parent)))
  3667. (org-e-odt-list-table lines caption label attr))))))
  3668. ;;;; Target
  3669. (defun org-e-odt-target (target contents info)
  3670. "Transcode a TARGET object from Org to HTML.
  3671. CONTENTS is nil. INFO is a plist holding contextual
  3672. information."
  3673. (org-e-odt-format-anchor
  3674. "" (org-export-solidify-link-text (org-element-property :value target))))
  3675. ;;;; Time-stamp
  3676. (defun org-e-odt-time-stamp (time-stamp contents info)
  3677. "Transcode a TIME-STAMP object from Org to HTML.
  3678. CONTENTS is nil. INFO is a plist holding contextual
  3679. information."
  3680. ;; (let ((value (org-element-property :value time-stamp))
  3681. ;; (type (org-element-property :type time-stamp))
  3682. ;; (appt-type (org-element-property :appt-type time-stamp)))
  3683. ;; (concat (cond ((eq appt-type 'scheduled)
  3684. ;; (format "\\textbf{\\textsc{%s}} " org-scheduled-string))
  3685. ;; ((eq appt-type 'deadline)
  3686. ;; (format "\\textbf{\\textsc{%s}} " org-deadline-string))
  3687. ;; ((eq appt-type 'closed)
  3688. ;; (format "\\textbf{\\textsc{%s}} " org-closed-string)))
  3689. ;; (cond ((memq type '(active active-range))
  3690. ;; (format org-e-odt-active-timestamp-format value))
  3691. ;; ((memq type '(inactive inactive-range))
  3692. ;; (format org-e-odt-inactive-timestamp-format value))
  3693. ;; (t
  3694. ;; (format org-e-odt-diary-timestamp-format value)))))
  3695. (let ((value (org-element-property :value time-stamp))
  3696. (type (org-element-property :type time-stamp))
  3697. (appt-type (org-element-property :appt-type time-stamp)))
  3698. (setq value (org-export-secondary-string value 'e-odt info))
  3699. (org-e-odt-format-fontify
  3700. (concat
  3701. (org-e-odt-format-fontify
  3702. (cond ((eq appt-type 'scheduled) org-scheduled-string)
  3703. ((eq appt-type 'deadline) org-deadline-string)
  3704. ((eq appt-type 'closed) org-closed-string)) "timestamp-kwd")
  3705. ;; FIXME: (org-translate-time value)
  3706. (org-e-odt-format-fontify value "timestamp"))
  3707. "timestamp-wrapper")))
  3708. ;;;; Verbatim
  3709. (defun org-e-odt-verbatim (verbatim contents info)
  3710. "Transcode a VERBATIM object from Org to HTML.
  3711. CONTENTS is nil. INFO is a plist used as a communication
  3712. channel."
  3713. (org-e-odt-emphasis
  3714. verbatim (org-element-property :value verbatim) info))
  3715. ;;;; Verse Block
  3716. (defun org-e-odt-verse-block (verse-block contents info)
  3717. "Transcode a VERSE-BLOCK element from Org to HTML.
  3718. CONTENTS is nil. INFO is a plist holding contextual information."
  3719. ;; Replace each newline character with line break. Also replace
  3720. ;; each blank line with a line break.
  3721. (setq contents (replace-regexp-in-string
  3722. "^ *\\\\\\\\$" "<br/>\n"
  3723. (replace-regexp-in-string
  3724. "\\(\\\\\\\\\\)?[ \t]*\n" " <br/>\n"
  3725. (org-remove-indentation
  3726. (org-export-secondary-string
  3727. (org-element-property :value verse-block)
  3728. 'e-odt info)))))
  3729. ;; Replace each white space at beginning of a line with a
  3730. ;; non-breaking space.
  3731. (while (string-match "^[ \t]+" contents)
  3732. (let ((new-str (org-e-odt-format-spaces
  3733. (length (match-string 0 contents)))))
  3734. (setq contents (replace-match new-str nil t contents))))
  3735. (org-e-odt--wrap-label
  3736. verse-block (format "<p class=\"verse\">\n%s</p>" contents)))
  3737. ;;; Filter Functions
  3738. ;;;; Filter Settings
  3739. ;;;; Filters
  3740. ;;; Interactive functions
  3741. (defun org-e-odt-export-to-odt
  3742. (&optional subtreep visible-only body-only ext-plist pub-dir)
  3743. "Export current buffer to a HTML file.
  3744. If narrowing is active in the current buffer, only export its
  3745. narrowed part.
  3746. If a region is active, export that region.
  3747. When optional argument SUBTREEP is non-nil, export the sub-tree
  3748. at point, extracting information from the headline properties
  3749. first.
  3750. When optional argument VISIBLE-ONLY is non-nil, don't export
  3751. contents of hidden elements.
  3752. When optional argument BODY-ONLY is non-nil, only write code
  3753. between \"\\begin{document}\" and \"\\end{document}\".
  3754. EXT-PLIST, when provided, is a property list with external
  3755. parameters overriding Org default settings, but still inferior to
  3756. file-local settings.
  3757. When optional argument PUB-DIR is set, use it as the publishing
  3758. directory.
  3759. Return output file's name."
  3760. (interactive)
  3761. (setq debug-on-error t)
  3762. ;; (let* ((outfile (org-export-output-file-name ".html" subtreep pub-dir))
  3763. ;; (outfile "content.xml"))
  3764. ;; (org-export-to-file
  3765. ;; 'e-odt outfile subtreep visible-only body-only ext-plist))
  3766. (let* ((outbuf (org-e-odt-init-outfile))
  3767. (target (org-export-output-file-name ".odt" subtreep pub-dir))
  3768. (outdir (file-name-directory (buffer-file-name outbuf)))
  3769. (default-directory outdir))
  3770. ;; FIXME: for copying embedded images
  3771. (setq org-current-export-file
  3772. (file-name-directory
  3773. (org-export-output-file-name ".odt" subtreep nil)))
  3774. (org-export-to-buffer
  3775. 'e-odt outbuf
  3776. (memq 'subtree optns) (memq 'visible optns) (memq 'body optns))
  3777. (setq org-lparse-opt-plist nil) ; FIXME
  3778. (org-e-odt-save-as-outfile target ;; info
  3779. nil
  3780. )
  3781. ;; return outfile
  3782. target))
  3783. ;;; FIXMES, TODOS, FOR REVIEW etc
  3784. ;;;; org-format-table-html
  3785. ;;;; org-format-org-table-html
  3786. ;;;; org-format-table-table-html
  3787. ;;;; org-table-number-fraction
  3788. ;;;; org-table-number-regexp
  3789. ;;;; org-e-odt-table-caption-above
  3790. ;;;; org-whitespace
  3791. ;;;; "<span style=\"visibility:hidden;\">%s</span>"
  3792. ;;;; Remove display properties
  3793. ;;;; org-e-odt-final-hook
  3794. ;;;; org-e-odt-with-timestamp
  3795. ;;;; org-e-odt-html-helper-timestamp
  3796. ;;;; org-export-as-html-and-open
  3797. ;;;; org-export-as-html-batch
  3798. ;;;; org-export-as-html-to-buffer
  3799. ;;;; org-replace-region-by-html
  3800. ;;;; org-export-region-as-html
  3801. ;;;; org-export-as-html
  3802. ;;;; (org-export-directory :html opt-plist)
  3803. ;;;; (plist-get opt-plist :html-extension)
  3804. ;;;; org-e-odt-toplevel-hlevel
  3805. ;;;; org-e-odt-special-string-regexps
  3806. ;;;; org-e-odt-coding-system
  3807. ;;;; org-e-odt-coding-system
  3808. ;;;; org-e-odt-inline-image-extensions
  3809. ;;;; org-e-odt-protect-char-alist
  3810. ;;;; org-e-odt-table-use-header-tags-for-first-column
  3811. ;;;; org-e-odt-todo-kwd-class-prefix
  3812. ;;;; org-e-odt-tag-class-prefix
  3813. ;;;; org-e-odt-footnote-separator
  3814. ;;; Library Initializations
  3815. (mapc
  3816. (lambda (desc)
  3817. ;; Let Org open all OpenDocument files using system-registered app
  3818. (add-to-list 'org-file-apps
  3819. (cons (concat "\\." (car desc) "\\'") 'system))
  3820. ;; Let Emacs open all OpenDocument files in archive mode
  3821. (add-to-list 'auto-mode-alist
  3822. (cons (concat "\\." (car desc) "\\'") 'archive-mode)))
  3823. org-e-odt-file-extensions)
  3824. ;; FIXME
  3825. ;; (eval-after-load 'org-exp
  3826. ;; '(add-to-list 'org-export-inbuffer-options-extra
  3827. ;; '("ODT_STYLES_FILE" :odt-styles-file)))
  3828. (provide 'org-e-odt)
  3829. ;;; org-e-odt.el ends here