Generation of HTML markup with Common Lisp using cl-markup.

(defpackage :cl-markup-test (use :cl))
(in-package :cl-markup-test)
;; central feature is MARKUP:
(markup (:p 123))
=> "<p>123</p>"
;; MARKUP expects list arguments, atoms are beeing rejected
(markup "abc")
=> The value "abc" is not of type LIST.
   [Condition of type TYPE-ERROR]
;; arguments can be multiple lists
(markup (:p 123) (:p 234))
=> "<p>123</p><p>234</p>"
;; first element of list is used as tag, not bothering what type it is
;; and wether it smells like HTML
(markup ("p" 123))
=> "<p>123</p>"
(markup (p 123))
=> "<p>123</p>"
(markup ('p 123))
=> "<'p>123</'p>" ; oops
(markup (123 p))
=> error: The variable P is unbound.
   [Condition of type UNBOUND-VARIABLE]
(markup (123 "p"))
=> "<123>p</123>"  ; !!
;; whole HTML pages can be produced with cl-markup macros HTML, HTML5,
;; XHTML and XML.
(html5 (:p 42))
=> "<!DOCTYPE html><html><p>42</p></html>"
;; lisp expressions can be inserted everywhere except first position of list
(markup (:p (concatenate 'string "1" "2" "3")))
=> "<p>123</p>"
;; these expressions are considered good citizens when they produce
;; string results, else:
(markup (:p (+ 100 20 3)))
=> The value 123 is not of type STRING.
   [Condition of type TYPE-ERROR]
;; weird things seem to happen when combining snippets
(let ((snip (markup (:p "abc"))))
  (markup (:div snip)))
=> "<div>&lt;p&gt;abc&lt;/p&gt;</div>" ; !!
;; This is a feature called auto-escape and it provides correct
;; solutions for these kind of tasks:
(markup (:p "1<3"))
=> "<p>1&lt;3</p>"
(markup (:p "R&B"))
=> "<p>R&amp;B</p>"
;; auto-escaping can be turned off like this
(let* ((*auto-escape* nil)
       (snip (markup (:p "abc"))))
  (markup (:div snip)))
=> "<div><p>abc</p></div>"
;; another way to shelter strings against greedy auto-escape
;; is wrapping them in a list
(let ((snip (markup (:p "abc"))))
  (markup (:div (list snip))))
=> "<div><p>abc</p></div>"
;; same result using backquote syntax
(let ((snip (markup (:p "abc"))))
  (markup (:div `(,snip))))
=> "<div><p>abc</p></div>"
;; and this can also be done with CL-MARKUPs RAW macro.  RAW sounds
;; like a kind of strange name for a list-wrapping feature.  Maybe the
;; name tries to express that this procedure treats the string
;; like the raw markup from which it evolved.
(let ((snip (markup (:p "abc"))))
  (markup (:div (raw snip))))
=> "<div><p>abc</p></div>"
;; and now for the best of all: it is possible to write cl macros
;; producing HTML snippets.
(defmacro snip (name)
  `(markup (:p ,name)))
(snip "foo")
=> "<p>foo</p>"
;; It is save to handle string results.
;; Trying to pass markup asks for trouble
(defmacro snip-markup (name)
  `(:p ,name))
(markup (snip-markup "foo"))
=> "<snip-markup>foo</snip-markup>" ;; oops
;; MARKUP is a macro, it does not evaluate its arguments

Filemaker Custom Function: FM2Word

This custom function generates MS Word documents out of FileMaker data. The format is Word XML 2003 which is a bit outdatet, but still accessible with actual Word versions. I selected this grammar because it is easiest and does not require creation of a zip archive (‘docx’ is technically a zip file).

 *  Generates Microsoft Word 2003 XML Documents from FileMaker.
 *  Export result into a textfile with extension '.xml' and it can be opened in MS Word, OpenOffice, Libre Office, ...
 *  The expected input is a text with tags:
 *  #<p># - start paragraph
 *  #</p># - end paragraph
 *  #</p><p># - end + start paragraph
 *  #<table># - tables
 *  #</table>#
 *  #<table-row>#
 *  #</table-row>#
 *  #<table-cell>#
 *  #</table-cell>#
 *  #<section># - section break, continuous no new page
 *  #<section-2-col># - section break starting two column page layout
 *  #<section-3-col># - section break starting three column page layout
 *  #<b># - bold
 *  #</b>#
 *  #<i># - italics
 *  #</i>#
 *  #<pict>#
 *  #</pict>#
 * Author: Jens Teich,


styles= "<w:styles>" &

"<w:style w:type='paragraph' w:styleId='FileMakersHomebrew'>" &
"<w:name w:val='FileMakersHomebrew'/>" &
"<w:basedOn w:val='Standard'/>" &
"<w:rsid w:val='00AF7A99'/>" &
"<w:pPr><w:spacing w:line='360' w:line-rule='auto'/></w:pPr><w:rPr>" &
"<w:rFonts w:ascii='Garamond' w:h-ansi='Garamond'/>" &
"<wx:font wx:val='Garamond'/>" &
"<w:color w:val='7030A0'/>" &
"<w:sz w:val='24'/>" &
"<w:lang w:val='EN-US'/>" &
"</w:rPr>" &
"</w:style>" &

"</w:styles>" ;

include_style_FileMakersHomebrew = "";

header = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" &
"<?mso-application progid='Word.Document'?>" &
"<w:wordDocument xmlns:w='' " &
"xmlns:wx='' " &
"xmlns:v='urn:schemas-microsoft-com:vml' " &"
xmlns:o='urn:schemas-microsoft-com:office:office'>" ;

// footer = "</w:t></w:r></w:p></w:body></w:wordDocument>"
footer = "</w:body></w:wordDocument>"


header &
styles &

"<w:body>" & //<w:p><w:r><w:t>" &

Substitute ( input ;
["¶" ; "" ];["'" ; "\"" ];
["#<p-Style-FileMaker-Homebrew>#"; "<w:p><w:pPr><w:pStyle w:val='FileMakersHomebrew'/></w:pPr><w:r><w:t>"];
["#<section>#";"<w:p><w:pPr><w:sectPr><w:type w:val='continuous'/></w:sectPr></w:pPr></w:p>"];
["#<section-2-col>#";"<w:p><w:pPr><w:sectPr><w:type w:val='continuous'/><w:cols w:num='2' w:space='708'/></w:sectPr></w:pPr></w:p>"];
["#<section-3-col>#";"<w:p><w:pPr><w:sectPr><w:type w:val='continuous'/><w:cols w:num='3' w:space='708'/></w:sectPr></w:pPr></w:p>"];
["#<pict>#";"<w:pict><v:shape><v:imagedata src='"];
["#</pict>#";"'/></v:shape></w:pict>"]) &



It it not (yet?) possible to print a FileMaker layout into a Word document, but this cf might be a step in this direction.

Use custom function like this:

FM2Word( "#<p>#Hello World!#</p><p>#
Second Paragraph.#</p><p>#
Third Paragraph!#</p>#" )

And get this (line breaks and indentation manually inserted for better readability):

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<?mso-application progid='Word.Document'?>

    <w:style w:type='paragraph' w:styleId='FileMakersHomebrew'>
      <w:name w:val='FileMakersHomebrew'/>
      <w:basedOn w:val='Standard'/>
      <w:rsid w:val='00AF7A99'/>
      <w:pPr><w:spacing w:line='360' w:line-rule='auto'/></w:pPr>
	<w:rFonts w:ascii='Garamond' w:h-ansi='Garamond'/>
	<wx:font wx:val='Garamond'/>
	<w:color w:val='7030A0'/>
	<w:sz w:val='24'/>
	<w:lang w:val='EN-US'/>

    <w:p><w:r><w:t>Hello World!</w:t></w:r></w:p>
    <w:p><w:r><w:t>Second Paragraph.</w:t></w:r></w:p>
    <w:p><w:r><w:t>Third Paragraph!</w:t></w:r></w:p>

The custom function contains style ‘FileMakersHomebrew’ which shows how to define custom (MS Word) styles and make life much easier.

Sample file showing usage: test-word-transfer.fmp12.