org-e-odt.el 158 KB

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