aboutsummaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/seam-export.el8
-rw-r--r--lisp/seam-html.el42
-rw-r--r--lisp/seam-test.el36
-rw-r--r--lisp/seam.el25
4 files changed, 62 insertions, 49 deletions
diff --git a/lisp/seam-export.el b/lisp/seam-export.el
index 7fa6c2d..d0f59cc 100644
--- a/lisp/seam-export.el
+++ b/lisp/seam-export.el
@@ -226,12 +226,12 @@ notes)."
(defun seam-export--generate-backlinks (file)
(seam-export--to-string
- (let ((files (sort
+ (let ((files (cl-sort
(let ((seam--subset seam-export--types))
(cl-loop for x in (seam-get-links-to-file file)
collect (cons (seam-get-title-from-file x) x)))
- :key #'car
- :lessp #'string<)))
+ #'string<
+ :key #'car)))
(when files
(cl-loop for (title . file) in files
do (insert (format "- [[seam:%s][%s]]\n" (file-name-base file) title)))))))
@@ -264,7 +264,7 @@ notes)."
"contents"
(seam-export--to-string
(insert-file-contents note-file)
- (re-search-forward (org-headline-re 1))
+ (re-search-forward "^\\* ")
(org-mode) ;Needed for `org-set-property'.
(org-set-property "seam-title-p" "t")))
(seam-export--replace-variable
diff --git a/lisp/seam-html.el b/lisp/seam-html.el
index 018e56f..e95ff9d 100644
--- a/lisp/seam-html.el
+++ b/lisp/seam-html.el
@@ -1,6 +1,7 @@
;;; seam-html.el --- Seam HTML exporter -*- lexical-binding: t -*-
;; Copyright (C) 2025 Spencer Williams
+;; Copyright (C) 2011-2025 Free Software Foundation, Inc.
;; Author: Spencer Williams <spnw@plexwave.org>
@@ -28,15 +29,34 @@
;; This was blithely hacked together using large chunks of code lifted
;; straight from ox-html.el, and could do with much improvement.
;;
-;; Original ox-html code is licensed under GPL v3+. Copyright (c)
-;; 2011-2025 Free Software Foundation, Inc. Original authors: Carsten
-;; Dominik <carsten.dominik@gmail.com> and Jambunathan K <kjambunathan
-;; at gmail dot com>.
+;; The original authors of ox-html are:
+;; Carsten Dominik <carsten.dominik@gmail.com>
+;; Jambunathan K <kjambunathan at gmail dot com>
;;; Code:
(require 'ox-html)
+;;; Org <9.7 compatibility.
+
+(fset 'seam-html--element-parent-element
+ (if (fboundp 'org-element-parent-element)
+ 'org-element-parent-element
+ 'org-export-get-parent-element))
+
+(fset 'seam-html--element-parent
+ (if (fboundp 'org-element-parent)
+ 'org-element-parent
+ (lambda (node)
+ (org-element-property :parent node))))
+
+(fset 'seam-html--element-type-p
+ (if (fboundp 'org-element-type-p)
+ 'org-element-type-p
+ (lambda (node types)
+ (memq (org-element-type node)
+ (ensure-list types)))))
+
;;; NOTE: This function does not respect `:headline-levels' or
;;; `:html-self-link-headlines'.
(defun seam-html-headline (headline contents info)
@@ -102,8 +122,8 @@ images, set it to:
(lambda (paragraph) (org-element-property :caption paragraph))"
(let ((paragraph (pcase (org-element-type element)
(`paragraph element)
- (`link (org-element-parent element)))))
- (and (org-element-type-p paragraph 'paragraph)
+ (`link (seam-html--element-parent element)))))
+ (and (seam-html--element-type-p paragraph 'paragraph)
(or (not (and (boundp 'seam-html-standalone-image-predicate)
(fboundp seam-html-standalone-image-predicate)))
(funcall seam-html-standalone-image-predicate paragraph))
@@ -187,9 +207,9 @@ INFO is a plist holding contextual information. See
;; do this for the first link in parent (inner image link
;; for inline images). This is needed as long as
;; attributes cannot be set on a per link basis.
- (let* ((parent (org-element-parent-element link))
- (link (let ((container (org-element-parent link)))
- (if (and (org-element-type-p container 'link)
+ (let* ((parent (seam-html--element-parent-element link))
+ (link (let ((container (seam-html--element-parent link)))
+ (if (and (seam-html--element-type-p container 'link)
(org-html-inline-image-p link info))
container
link))))
@@ -268,7 +288,7 @@ INFO is a plist holding contextual information. See
(_
(if (and destination
(memq (plist-get info :with-latex) '(mathjax t))
- (org-element-type-p destination 'latex-environment)
+ (seam-html--element-type-p destination 'latex-environment)
(eq 'math (org-latex--environment-type destination)))
;; Caption and labels are introduced within LaTeX
;; environment. Use "ref" or "eqref" macro, depending on user
@@ -279,7 +299,7 @@ INFO is a plist holding contextual information. See
(seam-html-standalone-image-predicate
#'org-html--has-caption-p)
(counter-predicate
- (if (org-element-type-p destination 'latex-environment)
+ (if (seam-html--element-type-p destination 'latex-environment)
#'org-html--math-environment-p
#'org-html--has-caption-p))
(number
diff --git a/lisp/seam-test.el b/lisp/seam-test.el
index 5d4a562..9ab1b22 100644
--- a/lisp/seam-test.el
+++ b/lisp/seam-test.el
@@ -39,7 +39,7 @@
(defmacro seam-test-environment (&rest body)
(declare (indent 0))
- `(let* ((seam-test-directory (make-temp-file "seam-test" t))
+ `(let* ((seam-test-directory (file-name-as-directory (make-temp-file "seam-test" t)))
(seam-note-directory seam-test-directory)
(default-directory seam-test-directory)
(seam-note-types '("private" "public"))
@@ -66,15 +66,17 @@
(let ,options
(let ,(cl-loop for (name . args) in varlist
collect `(,name (seam-make-note ,@args)))
+ ;; FIXME: It's quite possible for tests to fail in such a way
+ ;; that this does not kill the buffers.
(unwind-protect (progn ,@body)
(mapcar #'kill-buffer (list ,@(mapcar #'car varlist))))))))
-(defun seam-test-remove-testdir (filename)
- (string-remove-prefix (concat seam-test-directory "/") filename))
+(defun seam-test-strip-testdir (filename)
+ (string-remove-prefix seam-test-directory filename))
(defun seam-test-list-files ()
(mapcar
- #'seam-test-remove-testdir
+ #'seam-test-strip-testdir
(directory-files-recursively seam-test-directory "")))
(defun seam-test-add-contents (buffer contents)
@@ -119,9 +121,9 @@
(ert-deftest seam-test-make-note-weird-filename ()
(should
(equal
- '("./Weird file name!" ("private/weird-file-name.org"))
+ '("./Weir'd file name!" ("private/weird-file-name.org"))
(seam-test-with-notes ()
- ((weird "./Weird file name! "))
+ ((weird "./Weir'd file name! "))
(list (buffer-name weird)
(seam-test-list-files))))))
@@ -222,7 +224,7 @@
(seam-test-replace-contents bar "* qux")
(list
(seam-test-links-from-html "html/foo.html")
- (mapcar #'seam-test-remove-testdir (seam-get-links-from-file (buffer-file-name foo)))
+ (mapcar #'seam-test-strip-testdir (seam-get-links-from-file (buffer-file-name foo)))
(seam-test-list-files)))))))
(ert-deftest seam-test-link-update-no-unnecessary-export ()
@@ -297,9 +299,9 @@ the class."
(seam-test-add-contents foo (seam-test-link-to-buffer qux))
(seam-test-add-contents bar (seam-test-link-to-buffer qux))
(list
- (mapcar #'seam-test-remove-testdir (seam-get-links-from-file (buffer-file-name foo)))
- (mapcar #'seam-test-remove-testdir (seam-get-links-to-file (buffer-file-name bar)))
- (mapcar #'seam-test-remove-testdir (seam-get-links-to-file (buffer-file-name qux))))))))
+ (mapcar #'seam-test-strip-testdir (seam-get-links-from-file (buffer-file-name foo)))
+ (mapcar #'seam-test-strip-testdir (seam-get-links-to-file (buffer-file-name bar)))
+ (mapcar #'seam-test-strip-testdir (seam-get-links-to-file (buffer-file-name qux))))))))
(ert-deftest seam-test-delete-note ()
"Test that deleting a note also deletes its HTML and re-exports linking
@@ -358,20 +360,6 @@ backlink."
(insert-file-contents "html/bar.html")
(re-search-forward "<a href=\"/foo.html\">")))))
-(ert-deftest seam-test-backlinks-comment ()
- "Test that a commented-out link does not add a backlink."
- :expected-result :failed
- (should-error
- (identity
- (seam-test-with-notes ((seam-export-template-string "{{backlinks}}"))
- ((foo "foo" "public")
- (bar "bar" "public"))
- (with-current-buffer foo
- (seam-test-add-contents foo (concat "# " (seam-test-link-to-buffer bar))))
- (with-temp-buffer
- (insert-file-contents "html/bar.html")
- (re-search-forward "<a href=\"/foo.html\">"))))))
-
(ert-deftest seam-test-set-type-private ()
"Test that setting a public note to private will delete its HTML file and
update linking HTML files such that they no longer link to it."
diff --git a/lisp/seam.el b/lisp/seam.el
index 589e947..4cc21e7 100644
--- a/lisp/seam.el
+++ b/lisp/seam.el
@@ -33,6 +33,7 @@
;;; Code:
(require 'seam-export)
+(require 'org)
(require 'cl-lib)
(require 'grep)
@@ -71,7 +72,10 @@ naming. Must be a function taking two arguments: TITLE and TYPE."
(mapcar #'car seam-export-alist))
(defun seam-slugify (title)
- (downcase (string-join (string-split title "\\W+" t) "-")))
+ (setq title (string-replace "'" "" title))
+ (setq title (string-split title "\\W+" t))
+ (setq title (string-join title "-"))
+ (downcase title))
(defun seam-lookup-slug (slug)
(cl-dolist (type seam-note-types)
@@ -156,8 +160,7 @@ naming. Must be a function taking two arguments: TITLE and TYPE."
(save-restriction
(widen)
(goto-char 1)
- (ignore-errors
- (re-search-forward (org-headline-re 1))
+ (when (re-search-forward "^\\* " nil t)
(let ((start (point)))
(end-of-line)
(let ((title (string-trim (buffer-substring-no-properties start (point)))))
@@ -175,8 +178,7 @@ naming. Must be a function taking two arguments: TITLE and TYPE."
(save-restriction
(widen)
(goto-char 1)
- (ignore-errors
- (re-search-forward (org-headline-re 1))
+ (when (re-search-forward "^\\* " nil t)
(org-element-property :SEAM_SLUG (org-element-at-point))))))
(seam-slugify (seam-get-title-from-buffer buffer))))
@@ -196,6 +198,8 @@ naming. Must be a function taking two arguments: TITLE and TYPE."
(file (file-name-concat seam-note-directory
type
(concat slug ".org"))))
+ (when (string= "" slug)
+ (error "Cannot create a note with an empty slug"))
(seam--check-conflict slug)
(let ((buffer (funcall (if select #'find-file #'find-file-noselect) file)))
(with-current-buffer buffer
@@ -214,7 +218,7 @@ naming. Must be a function taking two arguments: TITLE and TYPE."
(and self (list self)))))
(let ((files (cl-loop for (title . file) in notes
collect (cons (seam-format-title title (seam-get-note-type file)) file))))
- (let ((completion (string-trim (funcall seam-completing-read-function prompt files))))
+ (let ((completion (string-trim (funcall seam-completing-read-function prompt (mapcar #'car files)))))
(or (assoc completion files)
(cons completion nil)))))))
@@ -503,10 +507,11 @@ Otherwise, it's nil."
update-count)))
(cl-defun seam-set-buffer-name (&optional (buffer (current-buffer)))
- (with-current-buffer buffer
- (rename-buffer
- (seam-format-title (seam-get-title-from-buffer)
- (seam-get-note-type (buffer-file-name buffer))))))
+ (when-let ((title (seam-get-title-from-buffer)))
+ (with-current-buffer buffer
+ (rename-buffer
+ (seam-format-title title
+ (seam-get-note-type (buffer-file-name buffer)))))))
(defun seam-setup-buffer ()
"Setup hooks when loading a Seam file."