diff --git a/.gitignore b/.gitignore index 6f9c28d..a4e71ae 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ /ltximg/ **/.DS_Store +/tests/indent.log +/indent.log diff --git a/org-special-block-extras.el b/org-special-block-extras.el index d283fae..9101efa 100644 --- a/org-special-block-extras.el +++ b/org-special-block-extras.el @@ -579,7 +579,7 @@ Example declaration, with all possible features shown: (org-defblock remark (editor \"Editor Remark\" :face angry-red) (color \"red\" signoff \"\") - \"Top level (HTML & LaTeX)O-RESPECT-NEWLINES? editorial remarks; in Emacs they're angry red.\" + \"Top level (HTML & LaTeX) editorial remarks; in Emacs they're angry red.\" (format (if (equal backend 'html) \"⟦%s: %s%s⟧\" \"{\\color{%s}\\bfseries %s: %s%s}\") @@ -1791,7 +1791,7 @@ this command gives a searchable way to insert doc links." 'variable-documentation)) (-let [it (shell-command-to-string (format "wn %s -over -synsn" label))] - (if (s-blank-p it) + (if (and (s-blank-p it) (not org-export-with-broken-links)) (error "Error: No documentation-glossary entry for “%s”!" label) it))))) @@ -2184,6 +2184,15 @@ what is required by MathJaX." (s-join "\\\\") (format "$$\\begin{align*} & %s \n\\end{align*}$$"))) +(setq my/theorem-counter 0) + +(org-defblock theorem (title) + "Show block contents prefixed with “Theorem 𝒏”, where the 𝒏umbering automatically increments." + (format "
\npost"))
-;; [[file:org-special-block-extras.org::*Folded Details ---As well as boxed text and subtle colours][Folded Details ---As well as boxed text and subtle colours:4]]
+;; [[file:org-special-block-extras.org::#Folded-Details][Folded Details ---As well as boxed text and subtle colours:3]]
(deftest "The result is a
\nC-u 80_-∀
")) @@ -421,7 +421,7 @@ post") "M-s h ."))) ;; Nice Keystroke Renditions: kbd:C-h_h:3 ends here -;; [[file:org-special-block-extras.org::* /“Link Here!”/ & OctoIcons][ /“Link Here!”/ & OctoIcons:3]] +;; [[file:org-special-block-extras.org::#Link-Here-OctoIcons][ /“Link Here!”/ & OctoIcons:3]] (deftest "It works as expected: We have an anchor with the given ID, and the default SVG chain icon." [link:here] (⇝ (⟰ "link-here:example-location (Click the icon and see the URL has changed!)") @@ -431,7 +431,7 @@ post") (* anything))) ;; /“Link Here!”/ & OctoIcons:3 ends here -;; [[file:org-special-block-extras.org::*Badge Links][Badge Links:2]] +;; [[file:org-special-block-extras.org::#Badge-Links][Badge Links:2]] (deftest "It works when all 5 arguments are provided" [badge] (⇝ (⟰ "badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir") @@ -491,7 +491,7 @@ post") "")) ;; Badge Links:2 ends here -;; [[file:org-special-block-extras.org::*Intro, motivating examples][Intro, motivating examples:4]] +;; [[file:org-special-block-extras.org::#COMMENT-Intro][Intro, motivating examples:4]] (deftest "It gives a tooltip whose title is the Lisp docs of APPLY" [doc] (⇝ (⟰ "doc:apply") @@ -530,7 +530,7 @@ post") "\">Existential Angst. ")) ;; Intro, motivating examples:4 ends here -;; [[file:org-special-block-extras.org::*Marginal, “one-off”, remarks][Marginal, “one-off”, remarks:2]] +;; [[file:org-special-block-extras.org::#Marginal-one-off-remarks][Marginal, “one-off”, remarks:2]] (setq margin (⟰ "/Allah[[margin:][The God of Abraham; known as Elohim in the Bible]] does not burden a soul beyond what it can bear./ --- Quran 2:286")) @@ -553,7 +553,7 @@ post") (⇝ margin "")) ;; Marginal, “one-off”, remarks:2 ends here -;; [[file:org-special-block-extras.org::*Equational Proofs][Equational Proofs:4]] +;; [[file:org-special-block-extras.org::#Equational-Proofs][Equational Proofs:4]] (setq calc (⟰ "#+begin_calc :hint-format \"\\\\left\\{ %s\\\\right.\" + x + y -- Explanation of why $x \\;=\\; y$ diff --git a/tests/badge.yaml b/tests/badge.yaml new file mode 100644 index 0000000..b47fa6e --- /dev/null +++ b/tests/badge.yaml @@ -0,0 +1,190 @@ +input: |- + + 1. It works when all 5 arguments are provided + + badge:Let_me_google_that|for_you!|orange|https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir + + 2. It works when we use [ [ link ] ] syntax with generous spaces and newlines + + [[badge: Let me google that | for you! | orange | + https://lmgtfy.app/?q=badge+shields.io&iie=1|Elixir]] + + 3. It works when only the first 2 arguments are provided; + asterisks are passed unaltered into the first argument + + badge:Let_me_*not*_google_that|for_you + + 4. It works when all 5 arguments are provided - URL ‘here’ makes it a local link + + badge:key|value|informational|here|Elixir + + 5. We can use spaces, commas, dashes, and percentage symbols in the first argument + + badge:example_with_spaces,_-,_and_%|points_right_here|orange|here + + 6. It works when only first 2 arguments are given: Default colour & logo are green & no logo shown + + badge:key|value + + 7. When only a key is provided, the value slot is shown as an empty green stub + + badge:key + + 8. When only a value is provided, only the value is shown in a default green + ---no stub for the missing key, yay + + badge:|value + + 9. It's only a green stub when provided with an empty key and empty value + + badge:||green + + 10. It's only a green stub when we use no options at all + + [[badge:]] + +expectations: + html: |- +It works when all 5 arguments are provided
+ + ++ It works when we use [ [ link ] ] syntax with generous spaces and newlines +
+ + ++ It works when only the first 2 arguments are provided; asterisks are + passed unaltered into the first argument +
+ ++ +
++ It works when all 5 arguments are provided - URL ‘here’ makes it a local + link +
+ + ++ We can use spaces, commas, dashes, and percentage symbols in the first + argument +
+ + ++ It works when only first 2 arguments are given: Default colour & logo + are green & no logo shown +
+ ++ +
++ When only a key is provided, the value slot is shown as an empty green + stub +
+ ++ +
++ When only a value is provided, only the value is shown in a default green + —no stub for the missing key, yay +
+ ++ +
++ It's only a green stub when provided with an empty key and empty value +
+ ++ +
+It's only a green stub when we use no options at all
+ ++ +
++ This is the key insight… (We have an HTML box enclosing the user's + title and text) +
+Look at my text, it's red!
+ + + +Look at my text, it's pink!
+ + + +Look at my text, it's cyan!
+ + ++ Look + Here + Buddo! +
+ latex: |- + \begingroup\color{red} + Look at my text, it's red! + + \endgroup\, + + \begingroup\color{pink} + Look at my text, it's pink! + + \endgroup\, + + \begingroup\color{cyan} + Look at my text, it's cyan! + + \endgroup\, + + \begingroup\color{green}Look\endgroup\, + \begingroup\color{blue}Here\endgroup\, + \begingroup\color{orange}Buddo\endgroup\,! diff --git a/tests/details.yaml b/tests/details.yaml new file mode 100644 index 0000000..0f9830a --- /dev/null +++ b/tests/details.yaml @@ -0,0 +1,48 @@ +input: |- + + #+begin_details TITLE-RIGHT-HERE :title-color "cyan" + The result is a+ The result is a <details> tag containing the user's title & text. + But, in LaTeX, this is a colourful box. +
++ (FIXME: The use of quotes in the :title-color keyword is only required for the + LaTeX backend.) +
+ latex: |- + \definecolor{osbe-bg}{HTML}{e5f5e5}\colorlet{osbe-fg}{cyan}\begin{quote} + \begin{tcolorbox}[colback=osbe-bg,colframe=osbe-fg,title={TITLE-RIGHT-HERE},sharp corners,boxrule=0.4pt] + The result is a
+ The doc
link type can be used to show tooltips for Emacs Lisp
+ commands such as
+
+ thread-last +
+ ++ However, it can also be used for your own definitions/glossary. First define a + term as follows, which does not render anything in the resulting HTML. +
+ +Then you can refer to it using the given :label, if any:
+ ++ Category Theory +
+ +Or else refer to it with underscores in lieu of spaces:
+ ++ Category Theory +
+ ++ Either approach renders the name of the term, not the way its referenced. If + you want to change what's rendered, provide a description: +
+ ++ abstract nonsense +
+ +
+ Finally, if doc
gets a label that is not an Emacs Lisp command,
+ variable, nor a user-defined definition via #+begindocumentation,
+ then we try to look up its definition via the dictionary:
+
+ happiness +
+ latex: |- + 🚫 The LaTex backend is intentionally unmaintained. + 🫠 Whoops, there seems to be an error: + (void-variable label) diff --git a/tests/e2e.el b/tests/e2e.el new file mode 100644 index 0000000..d5ae522 --- /dev/null +++ b/tests/e2e.el @@ -0,0 +1,220 @@ +;; Emacs Lisp End-to-End Testing +;; +;; Read a YAML file that defines `input' and `expectations'. +;; Run `compute-values' on `input' and check the result is the same as `expectations' +;; Recursively read all YAML files in a specified directory. +;; +;; Sequence: +;; 1. Write a YAML test with no `expectations' +;; 2. (e2e-update-this-test) ;; Or: (e2e-update-tests) +;; 3. (e2e-run-tests) +;; 4. M-x magit, to see how the tests changed, commit if happy. +;; 5. Optionally, (ert-delete-all-tests) +;; +;; +;; Why? +;; +;; I think some of the unit tests I've written capture important +;; facts of the blocks I've defined, however the downside of +;; writing them is that they require thought. +;; +;; For example, nearly all of my tests are against the HTML +;; backend, even though org-special-block-extras is about +;; supporting multiple backends. Moreover, escaped strings aren't pretty. +;; Finally, since writing unit tests has friction, I don't even test +;; all options/keywords of my blocks. +;; +;; As such, I'd like to expedite the test writing process, and e2e.el +;; allows me to capture a snapshot of what a block produces and +;; I can then decide if a future change impacts the snapshot in +;; an acceptable fashion or not. +;; +;; When tests are easy to write, I'm more likely to write more of them. + + +(use-package yaml) +(use-package yaml-mode) +(use-package format-all) +(use-package ert) + + + +(defun e2e--read-yaml-file (file) + "Read and parse a YAML FILE, returning its contents as a hash table." + (with-temp-buffer + (insert-file-contents file) + (yaml-parse-string (buffer-string)))) + + +(defun e2e-run-this-test () + (interactive) + (-let [file (f-relative (buffer-file-name))] + (e2e--make-ert-test-for-yaml-file file) + (ert (concat "e2e/" (file-name-base file))))) + +(defun e2e--make-ert-test-for-yaml-file (file) + "ERT-compatible test for a YAML FILE based on 'input' and 'expectations'." + ;; Create a separate ert test for each YAML file + (let* ((data (e2e--read-yaml-file file)) + (input (gethash 'input data)) + (no-prettier (gethash 'no-prettier data)) + (expected-results (gethash 'expectations data)) + (actual-results (compute-values input no-prettier))) + + (eval `(ert-deftest ,(intern (format "e2e/%s" (file-name-base file))) () + :expected-result ,(if (map-elt data 'fails) :failed :passed) + ;; Iterate over each key in expected-results and create assertions + (map-every-p (lambda (key expected-value) + (let ((actual-value (map-elt ,actual-results key 'not-found))) + + (ert-info (`(lambda () + (when ,(and (stringp actual-value) (stringp expected-value)) + (insert-button "Show Diff" + 'action (lambda (button) + (e2e--show-string-diff ,expected-value ,actual-value)) + 'follow-link t + 'help-echo "Click to see the diff.")) + (format " Test failed in file “%s” for key “%s”" ,,file (quote ,key)))) + (should (equal actual-value expected-value))))) + ,expected-results) + + ;; TODO: Also assert that we can create a standalone PDF, unless there's a latex-backend-not-maintained key. + (when nil ;; unless (map-elt data 'latex-backend-not-maintained) + (let* ((file.tex (concat (f-base file) ".tex")) + (required-latex-imports (map-elt data 'required-latex-imports)) + (latex (map-elt (map-elt data 'expectations) 'latex))) + (with-temp-file file.tex + (insert + (format "\\documentclass{standalone} %s \\begin{document} %s \\end{document}" + (or required-latex-imports "") + latex))) + (assert (s-contains-p (format "Output written on %s.pdf" (f-base file)) + (shell-command-to-string (format "pdflatex -shell-escape -halt-on-error %s; rm -f %s" file.tex file.tex))))) + ))))) + + + +(defun e2e--show-string-diff (string1 string2) + "Show the difference between STRING1 and STRING2 using `diff` in Emacs." + (interactive "sEnter first string: \nsEnter second string: ") + (let ((temp-buffer1 (get-buffer-create "*Diff String 1*")) + (temp-buffer2 (get-buffer-create "*Diff String 2*"))) + ;; Fill the first buffer with string1 + (with-current-buffer temp-buffer1 + (erase-buffer) + (insert string1)) + + ;; Fill the second buffer with string2 + (with-current-buffer temp-buffer2 + (erase-buffer) + (insert string2)) + + ;; Call the diff command on the two buffers + (diff temp-buffer1 temp-buffer2))) + + +(cl-defun e2e-run-tests (&optional (directory ".")) + (interactive) + "Run all e2e tests recursively in DIRECTORY." + (loop for file in (directory-files-recursively directory "\\.yaml\\'") + do (e2e--make-ert-test-for-yaml-file file)) + ;; Run all tests matching regex + (ert "e2e/.*")) + + + +(cl-defun e2e-update-tests () + (interactive) + ;; update all tests + (loop for file in (directory-files-recursively "." "\\.yaml\\'") + do (e2e-update-test file))) + +(cl-defun e2e-update-this-test () + (interactive) + (e2e-update-test (buffer-file-name))) + +(cl-defun e2e-update-test (file) + (let* ((yaml (e2e--read-yaml-file file)) + (input (map-elt yaml 'input)) + (no-prettier (map-elt yaml 'no-prettier)) + ;; Creating an alist and not a hash-table so that ordering matters, for yaml encoding + (actual (-concat (list (cons 'input input)) + (map-remove (lambda (k v) (member k '(input expectations))) yaml) + (list (cons 'expectations (map-into (compute-values input no-prettier) 'alist)))))) + (with-temp-file file + ;; (insert (yaml-encode actual)) ;; Nope, it does not honour new lines + (insert (e2e--yaml-encode-alist actual)) + (-let [format-all-formatters '(("YAML" prettier))] + (yaml-mode) (format-all-buffer))))) + + + +(defun e2e--yaml-encode-alist (alist &optional indent-level) + "Encode an ALIST as a YAML-like string with multiline support. +Newlines within values are formatted using `|-' style. +Ensures a blank line before the `expectations' key if present. +INDENT-LEVEL specifies the current indentation level, defaulting to 0." + (let ((indent-level (or indent-level 0)) + (first-key t)) ;; Track if it’s the first key + (mapconcat + (lambda (pair) + (let* ((key (car pair)) + (value (cdr pair)) + (indent (make-string (* 2 indent-level) ? )) + (sub-indent (make-string (* 2 (1+ indent-level)) ? )) + ;; Insert a blank line before `expectations` + (separator (if (and (eq key 'expectations) (not first-key)) + "\n\n" "\n"))) + (setq first-key nil) ;; No longer the first key after first iteration + (concat separator + indent (symbol-name key) ": " + (cond + ;; Multiline strings: use `|-` style with additional indentation + ((and (stringp value) (string-match-p "\n" value)) + (concat "|-\n" + sub-indent + (replace-regexp-in-string "\n" (concat "\n" sub-indent) value))) + ;; Nested alists: recursively call e2e--yaml-encode-alist + ((and (listp value) (listp (car value))) + (concat "\n" (e2e--yaml-encode-alist value (1+ indent-level)))) + ;; Other values: simply output the value + (t + (prin1-to-string value)))))) + alist + ""))) + + + +(defun compute-values (input no-prettier) + "Computes new output given INPUT; `no-prettier' means no prettier/auto-format of result is done." + (defun hs-hide-all () t) ;; HACK. PROBLEM: “hiding all blocks”, is this hide-show-mode? + (map-into + ;; Temporarily redefine gensym, so tests are deterministic +(let ((seed 0)) +(cl-letf (((symbol-function 'gensym) + (lambda () (format "g%s" (incf seed))))) + (list + (cons 'html + (with-temp-buffer + (org-special-block-extras-mode) + (insert (org-export-string-as (format "\n%s\n" input) 'html :body-only-please)) + (unless no-prettier + (-let [format-all-formatters '(("HTML" prettier))] + ;; TODO: When all my osbe e2e tests pass, then I should remove this ignore-errors. + ;; If something doesn't format, then that means it's likely invalid and should error. + ;; ignore-errors for unclosedtags and other silly html errors + (html-mode) (ignore-errors (format-all-buffer)))) + (s-trim (buffer-string)))) + ;; Try to export, if it fails then just get the err msg. + (cons 'latex + (condition-case err + (with-temp-buffer + (org-special-block-extras-mode) + (insert (org-export-string-as (format "\n%s\n" input) 'latex :body-only-please)) + (unless no-prettier + (-let [format-all-formatters '(("LaTeX" latexindent))] ;; !! brew install latexindent + (latex-mode) (format-all-buffer))) + (s-trim (buffer-string))) + (error (format "🚫 The LaTex backend is intentionally unmaintained.\n🫠 Whoops, there seems to be an error: \n %S" err))))))) + 'hash-table)) + diff --git a/tests/fortune.yaml b/tests/fortune.yaml new file mode 100644 index 0000000..ed4d9de --- /dev/null +++ b/tests/fortune.yaml @@ -0,0 +1,13 @@ +fails: This link type works fine as a clickable element in Emacs, but fails on export. +priority: low +no-prettier: true +input: "[[fortune:cow][howdy buddo]]" +expectations: + html: |- +
+
zsh:28: parse error near `|' + cow+ + latex: |- + input: |- + [[fortune:cow][howdy buddo]] diff --git a/tests/kbd.yaml b/tests/kbd.yaml new file mode 100644 index 0000000..710d157 --- /dev/null +++ b/tests/kbd.yaml @@ -0,0 +1,82 @@ +input: |- + + 1. It becomes tags, but final symbol non-ascii *may* be ignored + + kbd:C-u_80_-∀ + + 2. [ [ It ] ] becomes tags + + [[kbd:C-u_80_-]] + + 3. Using syntax
+ It becomes <kbd> tags, but final symbol non-ascii may be + ignored +
+ +C-u 80_-∀
+[ [ It ] ] becomes <kbd> tags
+ ++ C-u 80 - +
++ Using syntax <it> becomes <kbd> tags, and surrounding space is + trimmed +
+ ++ C-u 80 - +
++ It has a tooltip documenting the underlying Lisp function, when possible +
+ ++ M-s h . +
+
+ The doc
link is for explanatory remarks, documentation, or
+ personal glossary that is intended to be used in multiple places.
+
+ However, sometimes we want a “one-off” remark, containing, say, references or
+ additional explanation and we want it without the ceremony of first defining a
+ glossary term then invoking it. Enter the margin
link. For
+ example:
+
+ Allah°  does not burden a soul beyond what it can bear. + —Quran 2:286 +
+ ++ In HTML, such “marginal remarks” appear as tooltips; in LaTeX, they appear in + the margin. +
+ latex: |- + The \texttt{doc} link is for explanatory remarks, documentation, or personal glossary that is + intended to be used in multiple places. + + However, sometimes we want a “one-off” remark, containing, say, references or additional + explanation and we want it without the ceremony of first defining a glossary term + then invoking it. Enter the \texttt{margin} link. For example: + + + \emph{Allah\!\!${}^{\textnormal{{\thefootnote}}}$ + \newsavebox{\OrgSpecialBlockExtrasMarginBox} + \begin{lrbox}{\OrgSpecialBlockExtrasMarginBox} + \begin{minipage}{\paperwidth - \textwidth - \oddsidemargin - 1in - 3ex} + \raggedright \iffalse Otherwise default alignment is fully justified. \fi + \footnotesize + \setminted{fontsize=\footnotesize, breaklines} \iffalse HACK! \fi + \color{gray!80} + {\color{black}${}^{\textnormal{{\thefootnote}}}$} + \normalfont + The God of Abraham; known as Elohim in the Bible + \end{minipage} + \end{lrbox} + \marginpar{\usebox{\OrgSpecialBlockExtrasMarginBox}\stepcounter{footnote}} + \hspace{-1.9ex} + \global\let\OrgSpecialBlockExtrasMarginBox\relax does not + burden a soul beyond what it can bear.} + ---Quran 2:286 + + In HTML, such “marginal remarks” appear as tooltips; in \LaTeX{}, they appear in the margin. diff --git a/tests/org-demo.yaml b/tests/org-demo.yaml new file mode 100644 index 0000000..2ea8019 --- /dev/null +++ b/tests/org-demo.yaml @@ -0,0 +1,87 @@ +input: |- + Sometimes, we want to show verbatim source and its resulting rendition ---which + is a major part of this article! So, let's make a block to mitigate such an + error-prone tedium. + + #+begin_org-demo + /italics/ and _underline_ + + $e^{i \times \pi} + 1 = 0$ + #+end_org-demo + + Output the CONTENTS of the block as both parsed Org and unparsed. + + Label the source text by SOURCE and the result text by RESULT + +expectations: + html: |- ++ Sometimes, we want to show verbatim source and its resulting rendition + —which is a major part of this article! So, let's make a block to + mitigate such an error-prone tedium. +
+ ++ /italics/ and _underline_ + + $e^{i \times \pi} + 1 = 0$ ++
italics and underline
+ +\(e^{i \times \pi} + 1 = 0\)
+Output the CONTENTS of the block as both parsed Org and unparsed.
+ +Label the source text by SOURCE and the result text by RESULT
+ latex: |- + Sometimes, we want to show verbatim source and its resulting rendition ---which + is a major part of this article! So, let's make a block to mitigate such an + error-prone tedium. + + \par \setlength{\columnseprule}{0 pt} + \begin{minipage}[t]{\linewidth} + \begin{multicols}{2} + \begin{tcolorbox}[title={Source},colback="cyan",colframe=red!75!black,colbacktitle=yellow!50!red,coltitle=red!25!black, fonttitle=\bfseries,subtitle style={boxrule=0.4pt, colback=yellow!50!red!25!white}] + + \begin{verbatim} + /italics/ and _underline_ + + $e^{i \times \pi} + 1 = 0$ + + \end{verbatim} + \end{tcolorbox} + \begin{tcolorbox}[title={Result},colback="cyan",colframe=red!75!black,colbacktitle=yellow!50!red,coltitle=red!25!black, fonttitle=\bfseries,subtitle style={boxrule=0.4pt, colback=yellow!50!red!25!white}] + \emph{italics} and \uline{underline} + + \(e^{i \times \pi} + 1 = 0\) + + \end{tcolorbox} + + \end{multicols}\end{minipage} + Output the CONTENTS of the block as both parsed Org and unparsed. + + Label the source text by SOURCE and the result text by RESULT diff --git a/tests/parallel.yaml b/tests/parallel.yaml new file mode 100644 index 0000000..bbf4cd6 --- /dev/null +++ b/tests/parallel.yaml @@ -0,0 +1,185 @@ +input: |- + + In the HTML Export, The result is 2 columns with no rule between + them and it contains the user's text, but ignores the + “#+columnbreak”. + + #+begin_parallel + Hello, to the left! + + #+columnbreak: + A super duper wide middle margin! + + + #+columnbreak: + Goodbye (“God-be-with-ye”) to the right! + + #+columnbreak: + woah + #+end_parallel + + + [Soft Columns] Below, the result is 2 columns with a solid BLACK + rule between them and it contains the user's text, but ignores the + “#+columnbreak”. + + #+begin_parallel 2 :bar t + X + + #+columnbreak: + + Y + + Z + #+end_parallel + + + [Hard Columns] The result is 3 columns with a solid GREEN rule + between them and it contains the user's text along with the + “#+columnbreak” evaluated at the expected positions. + #+begin_parallel 20% 60% 20% :bar green X + + #+columnbreak: + + Y + + #+columnbreak: + + Z + #+end_parallel +no-prettier: t +expectations: + html: |- ++ In the HTML Export, The result is 2 columns with no rule between + them and it contains the user's text, but ignores the + “#+columnbreak”. +
+ ++ Hello, to the left! +
+ ++ A super duper wide middle margin! +
+ + ++ Goodbye (“God-be-with-ye”) to the right! +
+ ++ woah +
+ ++ [Soft Columns] Below, the result is 2 columns with a solid BLACK + rule between them and it contains the user's text, but ignores the + “#+columnbreak”. +
+ ++ X +
+ ++ Y +
+ ++ Z +
+ ++ [Hard Columns] The result is 3 columns with a solid GREEN rule + between them and it contains the user's text along with the + “#+columnbreak” evaluated at the expected positions. +
++
+ Y +
+ ++
+ Z +
+ +
+ The rename
block is for Textual Substitution. For example, as a
+ translation tool:
+
+ Quran 12-4: Joseph said to his father ( + Jacob ), + “O my father, indeed I have seen (in a dream) eleven stars and the sun and + the moon; I saw them prostrating to me.” +
+ ++ In the rendered result, the Arabic names are replaed with their English + counterparts. +
+ latex: |- + The \texttt{rename} block is for Textual Substitution. For example, as a translation tool: + + + Quran 12-4: \textbf{\uline{Joseph}} said to his father ( \uline{\textbf{Jacob}} ), \emph{“O my father, + indeed I have seen (in a dream) eleven stars and the sun and the + moon; I saw them prostrating to me.”} + + + + In the rendered result, the Arabic names are replaed with their English counterparts. diff --git a/tests/show.yaml b/tests/show.yaml new file mode 100644 index 0000000..987d214 --- /dev/null +++ b/tests/show.yaml @@ -0,0 +1,46 @@ +input: |- + + The ~doc~ link shows documentation, but to see the value we can use ~show~ as in: + + doc:user-full-name + show:user-full-name + + This allows us to have “generic” sentences: + + My name is show:user-full-name, + and I am using Emacs show:emacs-version ^_^ + My favourite number is
+ The doc
link shows documentation, but to see the value we can use
+ show
as in:
+
+ user-full-name + "Musa Al-hassy" +
+ +This allows us to have “generic” sentences:
+ ++ My name is "Musa Al-hassy", and I am using Emacs "29.4" ^_^ My favourite + number is 7.716814692820414 +
+ ++ To see values of expressions in other programming languages, use Org Babel + inline source expressions. +
+ latex: |- + 🚫 The LaTex backend is intentionally unmaintained. + 🫠 Whoops, there seems to be an error: + (void-variable label) diff --git a/tests/solution.pdf b/tests/solution.pdf new file mode 100644 index 0000000..65a6de9 Binary files /dev/null and b/tests/solution.pdf differ diff --git a/tests/solution.yaml b/tests/solution.yaml new file mode 100644 index 0000000..017e0d7 --- /dev/null +++ b/tests/solution.yaml @@ -0,0 +1,117 @@ +input: |- + What is the name of Prophet Yusuf's father? + + Hint: The father's name also starts with `y`. + + #+begin_solution + Yacoub + #+end_solution +working-latex: |- + What is the name of Prophet Yusuf's father? + + Hint: The father's name also starts with `y`. + + \definecolor{osbe-bg}{HTML}{e5f5e5} + \colorlet{osbe-fg}{green} + + \begin{tcolorbox}[colback=osbe-bg, colframe=osbe-fg, title={Solution}, sharp corners, boxrule=0.4pt] + \begin{tcolorbox}[title={Did you actually try? Maybe see the ‘hints’ above!}, colback=blue!10!white, colframe=red!75!black, colbacktitle=yellow!50!red, coltitle=red!25!black, fonttitle=\bfseries, subtitle style={boxrule=0.4pt, colback=yellow!50!red!25!white}] + \begin{tcolorbox}[colback=osbe-bg, colframe=red, title={Solution, for real}, sharp corners, boxrule=0.4pt] + Yacoub + \end{tcolorbox} + \end{tcolorbox} + \end{tcolorbox} +explanation-of-changes-for-latex: |- + + The quote environment isn't designed to handle arbitrary content like tcolorbox. + Instead, I directly placed the tcolorbox environments without wrapping them in quote. + + Removed all colors specified in quotes (e.g., "blue"), as xcolor does not support them. + + 🚫 The LaTex backend is intentionally unmaintained +required-latex-imports: |- + \usepackage{newunicodechar} + \usepackage[hmargin=15mm,top=15mm,bottom=15mm]{geometry} + \usepackage[dvipsnames]{xcolor} + \usepackage{tcolorbox} + \usepackage{minted} + \usepackage{etoolbox} + \usepackage{multicol} + \usepackage{adjustbox} + + % TODO: Ideally the defblock itself would have these imports, + % For example, attached to the symbol's plist. + % Then use of the block would add the imports automatically. + % Moreover, we would not need this `required-latex-imports` key; + % instead it would be part of the `expectations` map, right before `latex`. + +expectations: + html: |- +What is the name of Prophet Yusuf's father?
+ +Hint: The father's name also starts with `y`.
+ +Yacoub
+
+ The spoiler
block is for “fill in the blanks” or “guess, and
+ hover to see the results” style of exposition.
+
+ Yusuf said to his father Yacoub , + “O my father, indeed I have seen eleven stars and + the sun and the moon ; I saw them prostrating to + me.” +
+ +
+ There are also options for the left delimiter of a hidden item, the right
+ delimiter, and the color of the hidden item. These default to
+ grey, ((, ))
respectively.
+
+ Yusuf said to his father Yacoub , + “O my father, indeed I have seen eleven stars and + the sun and the moon ; I saw them prostrating to + me.” +
+ latex: |- + The \texttt{spoiler} block is for “fill in the blanks” or “guess, and hover + to see the results” style of exposition. + + + \fbox{\phantom{Yusuf}}\footnote{Yusuf} said to his father \fbox{\phantom{Yacoub}}\footnote{Yacoub}, \emph{“O my father, indeed I have seen + \fbox{\phantom{eleven stars}}\footnote{eleven stars} and \fbox{\phantom{the sun and the moon}}\footnote{the sun and the moon}; I saw them prostrating to me.”} + + + + There are also options for the left delimiter of a hidden item, the right delimiter, + and the color of the hidden item. These default to \texttt{grey, ((, ))} respectively. + + + \fbox{\phantom{Yusuf}}\footnote{Yusuf} said to his father \fbox{\phantom{Yacoub}}\footnote{Yacoub}, \emph{“O my father, indeed I have seen + \fbox{\phantom{eleven stars}}\footnote{eleven stars} and \fbox{\phantom{the sun and the moon}}\footnote{the sun and the moon}; I saw them prostrating to me.”} diff --git a/tests/tree.yaml b/tests/tree.yaml new file mode 100644 index 0000000..78ff896 --- /dev/null +++ b/tests/tree.yaml @@ -0,0 +1,34 @@ +input: |- + #+begin_box Programming ≈ Proving + #+begin_tree + + Function Application :: f(a) : B + - a : A + - f : A → B + + + Modus Ponens :: q + - p + - p ⇒ q + #+end_tree + #+end_box + +expectations: + html: |- +