org-e-odt.el 157 KB

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