org-e-odt.el 156 KB

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