test-ox-publish.el 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. ;;; test-ox-publish.el --- Tests for "ox-publish.el" -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2016, 2019 Nicolas Goaziou
  3. ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. ;;; Code:
  15. ;;; Helper functions
  16. (defun org-test-publish (properties handler &optional remove-prop)
  17. "Publish a project defined by PROPERTIES.
  18. Call HANDLER with the publishing directory as its sole argument.
  19. Unless set otherwise in PROPERTIES, `:base-directory' is set to
  20. \"examples/pub/\" sub-directory from test directory and
  21. `:publishing-function' is set to `org-publish-attachment'.
  22. Because `org-publish-property' uses `plist-member' to check the
  23. existence of a property, a property with a value nil is different
  24. from a non-existing property. Properties in REMOVE-PROP will be
  25. removed from the final plist."
  26. (declare (indent 1))
  27. (let* ((org-publish-use-timestamps-flag nil)
  28. (org-publish-cache nil)
  29. (base-dir (expand-file-name "examples/pub/" org-test-dir))
  30. (pub-dir (make-temp-file "org-test" t))
  31. (org-publish-timestamp-directory
  32. (expand-file-name ".org-timestamps/" pub-dir))
  33. (props (org-plist-delete-all
  34. (org-combine-plists
  35. `(:base-directory ,base-dir
  36. :publishing-function org-publish-attachment)
  37. properties
  38. `(:publishing-directory ,pub-dir))
  39. remove-prop))
  40. (project
  41. `("test" ,@props)))
  42. (unwind-protect
  43. (progn
  44. (org-publish-projects (list project))
  45. (funcall handler pub-dir))
  46. ;; Clear published data.
  47. (delete-directory pub-dir t)
  48. ;; Delete auto-generated site-map file, if applicable.
  49. (let ((site-map (and (plist-get properties :auto-sitemap)
  50. (expand-file-name
  51. (or (plist-get properties :sitemap-filename)
  52. "sitemap.org")
  53. base-dir))))
  54. (when (and site-map (file-exists-p site-map))
  55. (delete-file site-map))))))
  56. ;;; Mandatory properties
  57. (ert-deftest test-org-publish/base-extension ()
  58. "Test `:base-extension' specifications"
  59. ;; Regular tests.
  60. (should
  61. (equal '("a.org" "b.org")
  62. (org-test-publish '(:base-extension "org")
  63. (lambda (dir)
  64. (remove ".org-timestamps"
  65. (cl-remove-if #'file-directory-p
  66. (directory-files dir)))))))
  67. (should
  68. (equal '("file.txt")
  69. (org-test-publish '(:base-extension "txt")
  70. (lambda (dir)
  71. (remove ".org-timestamps"
  72. (cl-remove-if #'file-directory-p
  73. (directory-files dir)))))))
  74. ;; A nil value is equivalent to ".org".
  75. (should
  76. (equal '("a.org" "b.org")
  77. (org-test-publish '(:base-extension nil)
  78. (lambda (dir)
  79. (remove ".org-timestamps"
  80. (cl-remove-if #'file-directory-p
  81. (directory-files dir)))))))
  82. ;; Symbol `any' includes all files, even those without extension.
  83. (should
  84. (equal '("a.org" "b.org" "file.txt" "noextension")
  85. (org-test-publish '(:base-extension any)
  86. (lambda (dir)
  87. (remove ".org-timestamps"
  88. (cl-remove-if #'file-directory-p
  89. (directory-files dir)))))))
  90. ;; Check the default trasformation function,
  91. ;; org-html-publish-to-html. Because org-test-publish uses
  92. ;; org-publish-attachment by default, we must not just override with
  93. ;; nil but tell it to remove the :publishing-function from the list.
  94. (should
  95. (let ((func (lambda (dir)
  96. (with-temp-buffer
  97. (insert-file-contents (expand-file-name "a.html" dir))
  98. (buffer-string)))))
  99. (equal (org-test-publish nil func '(:publishing-function))
  100. (org-test-publish '(:publishing-function org-html-publish-to-html) func)))))
  101. ;;; Site-map
  102. (ert-deftest test-org-publish/sitemap ()
  103. "Test site-map specifications."
  104. ;; Site-map creation is controlled with `:auto-sitemap'. It
  105. ;; defaults to "sitemap.org".
  106. (should
  107. (org-test-publish
  108. '(:auto-sitemap t)
  109. (lambda (dir) (file-exists-p (expand-file-name "sitemap.org" dir)))))
  110. (should-not
  111. (org-test-publish
  112. '(:auto-sitemap nil)
  113. (lambda (dir) (file-exists-p (expand-file-name "sitemap.org" dir)))))
  114. ;; Site-map file name is controlled with `:sitemap-filename'.
  115. (should
  116. (org-test-publish
  117. '(:auto-sitemap t :sitemap-filename "mysitemap.org")
  118. (lambda (dir) (file-exists-p (expand-file-name "mysitemap.org" dir)))))
  119. ;; Site-map title is controlled with `:sitemap-title'. It defaults
  120. ;; to the project name.
  121. (should
  122. (equal "#+TITLE: Sitemap for project test"
  123. (org-test-publish
  124. '(:auto-sitemap t)
  125. (lambda (dir)
  126. (with-temp-buffer
  127. (insert-file-contents (expand-file-name "sitemap.org" dir))
  128. (buffer-substring (point) (line-end-position)))))))
  129. (should
  130. (equal "#+TITLE: My title"
  131. (org-test-publish
  132. '(:auto-sitemap t :sitemap-title "My title")
  133. (lambda (dir)
  134. (with-temp-buffer
  135. (insert-file-contents (expand-file-name "sitemap.org" dir))
  136. (buffer-substring (point) (line-end-position)))))))
  137. ;; Allowed site-map styles: `list' and `tree'.
  138. (should
  139. (equal "
  140. - [[file:a.org][A]]
  141. - [[file:b.org][b]]
  142. - [[file:sub/c.org][C]]"
  143. (org-test-publish
  144. '(:auto-sitemap t
  145. :sitemap-sort-folders ignore
  146. :sitemap-style list
  147. :exclude "."
  148. :include ("a.org" "b.org" "sub/c.org"))
  149. (lambda (dir)
  150. (with-temp-buffer
  151. (insert-file-contents (expand-file-name "sitemap.org" dir))
  152. (buffer-substring (line-beginning-position 2) (point-max)))))))
  153. (should
  154. (equal "
  155. - [[file:a.org][A]]
  156. - [[file:b.org][b]]
  157. - sub
  158. - [[file:sub/c.org][C]]"
  159. (org-test-publish
  160. '(:auto-sitemap t
  161. :sitemap-style tree
  162. :exclude "."
  163. :include ("a.org" "b.org" "sub/c.org"))
  164. (lambda (dir)
  165. (with-temp-buffer
  166. (insert-file-contents (expand-file-name "sitemap.org" dir))
  167. (buffer-substring (line-beginning-position 2) (point-max)))))))
  168. ;; When style is `list', `:sitemap-sort-folders' controls the order
  169. ;; of appearance of directories among published files.
  170. (should
  171. (equal
  172. "
  173. - sub/
  174. - [[file:a.org][A]]
  175. - [[file:sub/c.org][C]]"
  176. (org-test-publish
  177. '(:auto-sitemap t
  178. :recursive t
  179. :sitemap-style list
  180. :sitemap-sort-folders first
  181. :exclude "."
  182. :include ("a.org" "sub/c.org"))
  183. (lambda (dir)
  184. (with-temp-buffer
  185. (insert-file-contents (expand-file-name "sitemap.org" dir))
  186. (buffer-substring (line-beginning-position 2) (point-max)))))))
  187. (should
  188. (equal
  189. "
  190. - [[file:a.org][A]]
  191. - [[file:sub/c.org][C]]
  192. - sub/"
  193. (org-test-publish
  194. '(:auto-sitemap t
  195. :recursive t
  196. :sitemap-style list
  197. :sitemap-sort-folders last
  198. :exclude "."
  199. :include ("a.org" "sub/c.org"))
  200. (lambda (dir)
  201. (with-temp-buffer
  202. (insert-file-contents (expand-file-name "sitemap.org" dir))
  203. (buffer-substring (line-beginning-position 2) (point-max)))))))
  204. ;; When style is `list', `:sitemap-sort-folders' can be used to
  205. ;; toggle visibility of directories in the site-map.
  206. (should
  207. (let ((case-fold-search t))
  208. (string-match-p
  209. "- sub/$"
  210. (org-test-publish
  211. '(:auto-sitemap t
  212. :recursive t
  213. :sitemap-style list
  214. :sitemap-sort-folders t
  215. :exclude "."
  216. :include ("a.org" "sub/c.org"))
  217. (lambda (dir)
  218. (with-temp-buffer
  219. (insert-file-contents (expand-file-name "sitemap.org" dir))
  220. (buffer-substring (line-beginning-position 2) (point-max))))))))
  221. (should-not
  222. (string-match-p
  223. "- sub/$"
  224. (org-test-publish
  225. '(:auto-sitemap t
  226. :recursive t
  227. :sitemap-style list
  228. :sitemap-sort-folders ignore
  229. :exclude "."
  230. :include ("a.org" "sub/c.org"))
  231. (lambda (dir)
  232. (with-temp-buffer
  233. (insert-file-contents (expand-file-name "sitemap.org" dir))
  234. (buffer-substring (line-beginning-position 2) (point-max)))))))
  235. ;; Using `:sitemap-sort-files', files can be sorted alphabetically
  236. ;; (according to their title, or file name when there is none),
  237. ;; chronologically a anti-chronologically.
  238. (should
  239. (equal
  240. "
  241. - [[file:a.org][A]]
  242. - [[file:b.org][b]]
  243. - [[file:sub/c.org][C]]"
  244. (org-test-publish
  245. '(:auto-sitemap t
  246. :recursive t
  247. :sitemap-style list
  248. :sitemap-sort-folders ignore
  249. :sitemap-sort-files alphabetically
  250. :exclude "."
  251. :include ("a.org" "b.org" "sub/c.org"))
  252. (lambda (dir)
  253. (with-temp-buffer
  254. (insert-file-contents (expand-file-name "sitemap.org" dir))
  255. (buffer-substring (line-beginning-position 2) (point-max)))))))
  256. (should
  257. (equal
  258. "
  259. - [[file:b.org][b]]
  260. - [[file:sub/c.org][C]]
  261. - [[file:a.org][A]]"
  262. (org-test-publish
  263. '(:auto-sitemap t
  264. :recursive t
  265. :sitemap-style list
  266. :sitemap-sort-folders ignore
  267. :sitemap-sort-files chronologically
  268. :exclude "."
  269. :include ("a.org" "b.org" "sub/c.org"))
  270. (lambda (dir)
  271. (with-temp-buffer
  272. (insert-file-contents (expand-file-name "sitemap.org" dir))
  273. (buffer-substring (line-beginning-position 2) (point-max)))))))
  274. (should
  275. (equal
  276. "
  277. - [[file:a.org][A]]
  278. - [[file:sub/c.org][C]]
  279. - [[file:b.org][b]]"
  280. (org-test-publish
  281. '(:auto-sitemap t
  282. :recursive t
  283. :sitemap-style list
  284. :sitemap-sort-folders ignore
  285. :sitemap-sort-files anti-chronologically
  286. :exclude "."
  287. :include ("a.org" "b.org" "sub/c.org"))
  288. (lambda (dir)
  289. (with-temp-buffer
  290. (insert-file-contents (expand-file-name "sitemap.org" dir))
  291. (buffer-substring (line-beginning-position 2) (point-max)))))))
  292. ;; `:sitemap-format-entry' formats entries in the site-map whereas
  293. ;; `:sitemap-function' controls the full site-map.
  294. (should
  295. (equal "
  296. - a.org"
  297. (org-test-publish
  298. '(:auto-sitemap t
  299. :exclude "."
  300. :include ("a.org")
  301. :sitemap-format-entry
  302. (lambda (f _s _p) f))
  303. (lambda (dir)
  304. (with-temp-buffer
  305. (insert-file-contents (expand-file-name "sitemap.org" dir))
  306. (buffer-substring (line-beginning-position 2) (point-max)))))))
  307. (should
  308. (equal "Custom!"
  309. (org-test-publish
  310. '(:auto-sitemap t
  311. :exclude "."
  312. :include ("a.org")
  313. :sitemap-function (lambda (_title _f) "Custom!"))
  314. (lambda (dir)
  315. (with-temp-buffer
  316. (insert-file-contents (expand-file-name "sitemap.org" dir))
  317. (buffer-string))))))
  318. (should
  319. (equal "[[file:a.org][A]]"
  320. (org-test-publish
  321. '(:auto-sitemap t
  322. :exclude "."
  323. :include ("a.org")
  324. :sitemap-function
  325. (lambda (_title f) (org-list-to-generic f nil)))
  326. (lambda (dir)
  327. (with-temp-buffer
  328. (insert-file-contents (expand-file-name "sitemap.org" dir))
  329. (buffer-string)))))))
  330. ;;; Cross references
  331. (ert-deftest test-org-publish/resolve-external-link ()
  332. "Test `org-publish-resolve-external-link' specifications."
  333. ;; Function should preserve internal reference when used between
  334. ;; published files.
  335. (should
  336. (apply
  337. #'equal
  338. (let* ((ids nil)
  339. (backend
  340. (org-export-create-backend
  341. :transcoders
  342. '((headline . (lambda (h c i)
  343. (concat (org-export-get-reference h i) " " c)))
  344. (paragraph . (lambda (p c i) c))
  345. (section . (lambda (s c i) c))
  346. (link . (lambda (l c i)
  347. (let ((option (org-element-property :search-option l))
  348. (path (org-element-property :path l)))
  349. (and option
  350. (org-publish-resolve-external-link
  351. option path))))))))
  352. (publish
  353. (lambda (plist filename pub-dir)
  354. (org-publish-org-to backend filename ".test" plist pub-dir))))
  355. (org-test-publish
  356. (list :publishing-function (list publish))
  357. (lambda (dir)
  358. (cl-subseq
  359. (split-string
  360. (mapconcat (lambda (f) (org-file-contents (expand-file-name f dir)))
  361. (directory-files dir nil "\\.test\\'")
  362. " "))
  363. 1 3))))))
  364. ;; When optional argument PREFER-CUSTOM is non-nil, use custom ID
  365. ;; instead of internal reference, whenever possible.
  366. (should
  367. (equal
  368. '("a1" "b1")
  369. (let* ((ids nil)
  370. (link-transcoder
  371. (lambda (l c i)
  372. (let ((option (org-element-property :search-option l))
  373. (path (org-element-property :path l)))
  374. (push (org-publish-resolve-external-link option path t)
  375. ids)
  376. "")))
  377. (backend
  378. (org-export-create-backend
  379. :transcoders `((headline . (lambda (h c i) c))
  380. (paragraph . (lambda (p c i) c))
  381. (section . (lambda (s c i) c))
  382. (link . ,link-transcoder))))
  383. (publish
  384. (lambda (plist filename pub-dir)
  385. (org-publish-org-to backend filename ".test" plist pub-dir))))
  386. (org-test-publish (list :publishing-function (list publish)
  387. :exclude "."
  388. :include '("a.org" "b.org"))
  389. #'ignore)
  390. (sort ids #'string<)))))
  391. ;;; Tools
  392. (ert-deftest test-org-publish/get-project-from-filename ()
  393. "Test `org-publish-get-project-from-filename' specifications."
  394. ;; Check base directory.
  395. (should
  396. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  397. (file (expand-file-name "a.org" base))
  398. (org-publish-project-alist `(("p" :base-directory ,base))))
  399. (org-publish-get-project-from-filename file)))
  400. ;; Return nil if no appropriate project is found.
  401. (should-not
  402. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  403. (file (expand-file-name "a.org" base))
  404. (org-publish-project-alist `(("p" :base-directory ,base))))
  405. (org-publish-get-project-from-filename "/other/file.org")))
  406. ;; Return the first project effectively publishing the provided
  407. ;; file.
  408. (should
  409. (equal "p2"
  410. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  411. (file (expand-file-name "a.org" base))
  412. (org-publish-project-alist
  413. `(("p1" :base-directory "/other/")
  414. ("p2" :base-directory ,base)
  415. ("p3" :base-directory ,base))))
  416. (car (org-publish-get-project-from-filename file)))))
  417. ;; When :recursive in non-nil, allow files in sub-directories.
  418. (should
  419. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  420. (file (expand-file-name "sub/c.org" base))
  421. (org-publish-project-alist
  422. `(("p" :base-directory ,base :recursive t))))
  423. (org-publish-get-project-from-filename file)))
  424. (should-not
  425. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  426. (file (expand-file-name "sub/c.org" base))
  427. (org-publish-project-alist
  428. `(("p" :base-directory ,base :recursive nil))))
  429. (org-publish-get-project-from-filename file)))
  430. ;; Also, when :recursive is non-nil, follow symlinks to directories.
  431. (should
  432. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  433. (file (expand-file-name "link/link.org" base))
  434. (org-publish-project-alist
  435. `(("p" :base-directory ,base :recursive t))))
  436. (org-publish-get-project-from-filename file)))
  437. (should-not
  438. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  439. (file (expand-file-name "link/link.org" base))
  440. (org-publish-project-alist
  441. `(("p" :base-directory ,base :recursive nil))))
  442. (org-publish-get-project-from-filename file)))
  443. ;; Check :base-extension.
  444. (should
  445. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  446. (file (expand-file-name "file.txt" base))
  447. (org-publish-project-alist
  448. `(("p" :base-directory ,base :base-extension "txt"))))
  449. (org-publish-get-project-from-filename file)))
  450. (should-not
  451. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  452. (file (expand-file-name "file.txt" base))
  453. (org-publish-project-alist
  454. `(("p" :base-directory ,base :base-extension "org"))))
  455. (org-publish-get-project-from-filename file)))
  456. ;; When :base-extension has the special value `any', allow any
  457. ;; extension, including none.
  458. (should
  459. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  460. (file (expand-file-name "file.txt" base))
  461. (org-publish-project-alist
  462. `(("p" :base-directory ,base :base-extension any))))
  463. (org-publish-get-project-from-filename file)))
  464. (should
  465. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  466. (file (expand-file-name "noextension" base))
  467. (org-publish-project-alist
  468. `(("p" :base-directory ,base :base-extension any))))
  469. (org-publish-get-project-from-filename file)))
  470. ;; Pathological case: Handle both :extension any and :recursive t.
  471. (should
  472. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  473. (file (expand-file-name "sub/c.org" base))
  474. (org-publish-project-alist
  475. `(("p" :base-directory ,base :recursive t :base-extension any))))
  476. (org-publish-get-base-files (org-publish-get-project-from-filename file))))
  477. ;; Check :exclude property.
  478. (should-not
  479. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  480. (file (expand-file-name "a.org" base))
  481. (org-publish-project-alist
  482. `(("p" :base-directory ,base :exclude "a"))))
  483. (org-publish-get-project-from-filename file)))
  484. (should
  485. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  486. (file (expand-file-name "a.org" base))
  487. (org-publish-project-alist
  488. `(("p" :base-directory ,base :exclude "other"))))
  489. (org-publish-get-project-from-filename file)))
  490. ;; The regexp matches against relative file name, not absolute one.
  491. (should
  492. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  493. (file (expand-file-name "a.org" base))
  494. (org-publish-project-alist
  495. `(("p" :base-directory ,base :exclude "examples/pub"))))
  496. (org-publish-get-project-from-filename file)))
  497. ;; Check :include property.
  498. (should
  499. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  500. (file (expand-file-name "file.txt" base))
  501. (org-publish-project-alist
  502. `(("p" :base-directory ,base :include (,file)))))
  503. (org-publish-get-project-from-filename file)))
  504. ;; :include property has precedence over :exclude one.
  505. (should
  506. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  507. (file (expand-file-name "a.org" base))
  508. (org-publish-project-alist
  509. `(("p"
  510. :base-directory ,base
  511. :include (,(file-name-nondirectory file))
  512. :exclude "a"))))
  513. (org-publish-get-project-from-filename file)))
  514. ;; With optional argument, return a meta-project publishing provided
  515. ;; file.
  516. (should
  517. (equal "meta"
  518. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  519. (file (expand-file-name "a.org" base))
  520. (org-publish-project-alist
  521. `(("meta" :components ("p"))
  522. ("p" :base-directory ,base))))
  523. (car (org-publish-get-project-from-filename file t))))))
  524. (ert-deftest test-org-publish/file-relative-name ()
  525. "Test `org-publish-file-relative-name' specifications."
  526. ;; Turn absolute file names into relative ones if file belongs to
  527. ;; base directory.
  528. (should
  529. (equal "a.org"
  530. (let* ((base (expand-file-name "examples/pub/" org-test-dir))
  531. (file (expand-file-name "a.org" base)))
  532. (org-publish-file-relative-name file `(:base-directory ,base)))))
  533. (should
  534. (equal "pub/a.org"
  535. (let* ((base (expand-file-name "examples/" org-test-dir))
  536. (file (expand-file-name "pub/a.org" base)))
  537. (org-publish-file-relative-name file `(:base-directory ,base)))))
  538. ;; Absolute file names that do not belong to base directory are
  539. ;; unchanged.
  540. (should
  541. (equal "/name.org"
  542. (let ((base (expand-file-name "examples/pub/" org-test-dir)))
  543. (org-publish-file-relative-name "/name.org"
  544. `(:base-directory ,base)))))
  545. ;; Relative file names are unchanged.
  546. (should
  547. (equal "a.org"
  548. (let ((base (expand-file-name "examples/pub/" org-test-dir)))
  549. (org-publish-file-relative-name "a.org" `(:base-directory ,base))))))
  550. (provide 'test-ox-publish)
  551. ;;; test-ox-publish.el ends here