Final form: publish now updates!

This commit is contained in:
John Doty 2017-10-18 09:53:13 -07:00
parent 685cbdc205
commit 5c58f5ee57
2 changed files with 65 additions and 33 deletions

View file

@ -1,10 +1,9 @@
;;; ox-quip.el -- Publish from org-mode to Quip. -*- lexical-binding: t -*- ;;; ox-quip.el -- Publish from org-mode to Quip. -*- lexical-binding: t -*-
;;; Commentary: ;;; Commentary:
;; Publisher from org-mode to Quip. (Export as markdown, push as a new ;; Publisher from org-mode to Quip. (Export as HTML, push as a new
;; thread or amend to existing quip thread.) ;; thread or amend to existing quip thread.)
;; ;;
;; BUG: Can't update documents on publish.
;; BUG: QUOTE is not rendered correctly. ;; BUG: QUOTE is not rendered correctly.
;;; Code: ;;; Code:
@ -126,7 +125,7 @@ correspondence."
)) ))
(defun org-quip--get-cleaned-dom (html &optional strip) (defun org-quip--get-cleaned-dom (html &optional strip)
"Clean HTML as a list of cleaned DOM elements. "Clean HTML as a list of cleaned DOM elements, and maybe STRIP attributes.
The return value is a list of elements, each one having been The return value is a list of elements, each one having been
scrubbed appropriately. This function can be called on both the scrubbed appropriately. This function can be called on both the
@ -144,14 +143,16 @@ to produce comparable results."
;; ============================================== ;; ==============================================
;; Functions to do with mapping HTML and ORG IDs. ;; Functions to do with mapping HTML and ORG IDs.
;; ============================================== ;; ==============================================
(defun org-quip--ensure-ids () (defun org-quip--ensure-ids (buffer)
"Ensure that each headline has a valid ID." "Ensure that each headline in BUFFER has a valid ID."
(with-current-buffer buffer
(org-map-entries (org-map-entries
(lambda () (lambda ()
(unless (org-entry-get nil "CUSTOM_ID") (unless (org-entry-get nil "CUSTOM_ID")
(let ((id (org-id-new))) (let ((id (org-id-new)))
(org-entry-put nil "CUSTOM_ID" id) (org-entry-put nil "CUSTOM_ID" id)
(org-id-add-location id (buffer-file-name (buffer-base-buffer)))))))) (org-id-add-location id (buffer-file-name (buffer-base-buffer)))))))
))
(defun org-quip--get-element-id (element) (defun org-quip--get-element-id (element)
"Return the ID attribute of the specified ELEMENT." "Return the ID attribute of the specified ELEMENT."
@ -381,6 +382,7 @@ Returns the published thread structure."
(org-export-as 'html nil nil t)))) (org-export-as 'html nil nil t))))
(defun org-quip--export-html-fragment (buffer start end) (defun org-quip--export-html-fragment (buffer start end)
"Export org BUFFER as HTML from START to END."
(save-excursion (save-excursion
(with-current-buffer buffer (with-current-buffer buffer
(save-restriction (save-restriction
@ -391,12 +393,12 @@ Returns the published thread structure."
(defun org-quip-publish-to-quip () (defun org-quip-publish-to-quip ()
"Publish the current buffer to Quip." "Publish the current buffer to Quip."
(interactive) (interactive)
(org-quip--ensure-ids) (org-quip--ensure-ids (current-buffer))
(let (let
((quip-id (org-quip--get-thread-identifier)) ((quip-id (org-quip--get-thread-identifier))
(content (org-quip--export-html (current-buffer)))) (content (org-quip--export-html (current-buffer))))
(if quip-id (if quip-id
(org-quip-update-quip quip-id content) (org-quip--update-quip (current-buffer) content quip-id)
(letrec ((quip-thread (org-quip--publish-quip content)) (letrec ((quip-thread (org-quip--publish-quip content))
(new-quip-id (alist-get 'id (alist-get 'thread quip-thread))) (new-quip-id (alist-get 'id (alist-get 'thread quip-thread)))
(quip-html (alist-get 'html quip-thread))) (quip-html (alist-get 'html quip-thread)))
@ -460,6 +462,16 @@ This replaces what's in the buffer so I hope you're OK with that."
(point)))) (point))))
(defun org-quip--get-element-end (element) (defun org-quip--get-element-end (element)
"Get the end point of 'org-mode' ELEMENT.
This is the end as we care about it: basically the end of the
main part of the element, not the end of the entire element and
its children. We also don't care about things like a headline's
property-drawer, so we skip that too.
\(Basically if you export from from the start of the element to
the value returned from this you get just the HTML for that
element.)"
(let ((type (org-element-type element)) (let ((type (org-element-type element))
(next-element)) (next-element))
(cond ((eq type 'headline) (cond ((eq type 'headline)
@ -534,8 +546,8 @@ commands."
(ignore-errors (delete-file old-diff-file)) (ignore-errors (delete-file old-diff-file))
(ignore-errors (delete-file new-diff-file))))) (ignore-errors (delete-file new-diff-file)))))
(defun org-quip--make-publish-diff (org-buffer quip-html) (defun org-quip--make-publish-diff (org-buffer new-html quip-html)
"Generate a diff between the specified ORG-BUFFER and QUIP-HTML. "Generate a diff between the ORG-BUFFER with NEW-HTML and QUIP-HTML.
The return value is a list of commands to execute against Quip." The return value is a list of commands to execute against Quip."
;; ;;
@ -571,7 +583,6 @@ The return value is a list of commands to execute against Quip."
(letrec ((old-dom (org-quip--get-cleaned-dom quip-html)) (letrec ((old-dom (org-quip--get-cleaned-dom quip-html))
(old-id-list (mapcar #'org-quip--get-element-id old-dom)) (old-id-list (mapcar #'org-quip--get-element-id old-dom))
(new-html (org-quip--export-html buffer))
(new-dom (org-quip--get-cleaned-dom new-html)) (new-dom (org-quip--get-cleaned-dom new-html))
(new-id-list (mapcar #'org-quip--get-element-id new-dom)) (new-id-list (mapcar #'org-quip--get-element-id new-dom))
(new-pos-list (org-quip--get-positions-from-ids buffer (new-pos-list (org-quip--get-positions-from-ids buffer
@ -636,6 +647,9 @@ The return value is a list of commands to execute against Quip."
(setq remove-ids (remove new-id remove-ids)) (setq remove-ids (remove new-id remove-ids))
(list 'replace new-id new-html)) (list 'replace new-id new-html))
((null last-id)
(list 'prepend new-html))
(t (t
(list 'insert-after last-id new-html))) (list 'insert-after last-id new-html)))
insert-commands)) insert-commands))
@ -666,22 +680,40 @@ The return value is a list of commands to execute against Quip."
(mapcar (lambda (id) (list 'remove id)) remove-ids)) (mapcar (lambda (id) (list 'remove id)) remove-ids))
))) )))
(defun org-quip--test-blarg () (defun org-quip--update-quip (buffer new-html thread-id)
"This is a test blarg." "Update quip from 'org-mode' BUFFER with NEW-HTML and existing THREAD-ID."
(save-excursion
(org-quip--ensure-ids buffer)
(letrec ((old-html (alist-get 'html (quip-get-thread thread-id)))
(diff-commands (org-quip--make-publish-diff buffer
new-html
old-html)))
;; Invoke all of the diff commands on quip.
(mapc (lambda (command)
(cond ((eq 'remove (car command))
(quip-thread-delete-section thread-id (second command)))
(letrec ((buffer (get-buffer "leavingconfigerator.org")) ((eq 'replace (car command))
(thread-id (org-quip--get-buffer-thread-id buffer)) (quip-thread-replace-section thread-id
(second command)
(third command)
"html"))
(old-html (alist-get 'html (quip-get-thread thread-id)))) ((eq 'insert-after (car command))
(quip-thread-append-after thread-id
(second command)
(third command)
"html"))
;(org-quip--diff-org-and-quip old-html (org-quip--export-html buffer)) ((eq 'prepend (car command))
(org-quip--make-publish-diff buffer old-html) (quip-thread-prepend thread-id (second command) "html"))
) ))
diff-commands)
(third '(1))
)
;; Re-fetch the HTML from quip and sync IDs.
(setq old-html (alist-get 'html (quip-get-thread thread-id)))
(org-quip--sync-ids-with-quip buffer new-html old-html))))
(provide 'ox-quip) (provide 'ox-quip)
;;; ox-quip.el ends here ;;; ox-quip.el ends here

View file

@ -68,12 +68,12 @@ that the content should be interpreted as such."
"Get the Quip thread with the specified ID. Return the parsed JSON response." "Get the Quip thread with the specified ID. Return the parsed JSON response."
(quip-invoke-json (concat "threads/" id) "GET" nil)) (quip-invoke-json (concat "threads/" id) "GET" nil))
(defconst quip-location-append 0) (defconst quip-location-append "0")
(defconst quip-location-prepend 1) (defconst quip-location-prepend "1")
(defconst quip-location-after-section 2) (defconst quip-location-after-section "2")
(defconst quip-location-before-section 3) (defconst quip-location-before-section "3")
(defconst quip-location-replace-section 4) (defconst quip-location-replace-section "4")
(defconst quip-location-delete-section 5) (defconst quip-location-delete-section "5")
(defun quip-thread-append (thread content &optional format) (defun quip-thread-append (thread content &optional format)
; checkdoc-order: nil ; checkdoc-order: nil