diff options
Diffstat (limited to 'wrappers')
-rwxr-xr-x | wrappers/wrapper.lua | 326 | ||||
-rwxr-xr-x | wrappers/wrapper.py | 22 | ||||
-rwxr-xr-x | wrappers/wrapper.rb | 4 | ||||
-rw-r--r-- | wrappers/wrapper.rkt | 190 | ||||
-rwxr-xr-x | wrappers/wrapper3.py | 25 |
5 files changed, 392 insertions, 175 deletions
diff --git a/wrappers/wrapper.lua b/wrappers/wrapper.lua index 11c5183..023e0b3 100755 --- a/wrappers/wrapper.lua +++ b/wrappers/wrapper.lua @@ -5,197 +5,235 @@ local ffi = require("ffi") cmark = ffi.load("libcmark") ffi.cdef[[ +char *cmark_markdown_to_html(const char *text, int len, int options); - char *cmark_markdown_to_html(const char *text, int len); - typedef enum { - /* Block */ - CMARK_NODE_DOCUMENT, - CMARK_NODE_BLOCK_QUOTE, - CMARK_NODE_LIST, - CMARK_NODE_LIST_ITEM, - CMARK_NODE_CODE_BLOCK, - CMARK_NODE_HTML, - CMARK_NODE_PARAGRAPH, - CMARK_NODE_HEADER, - CMARK_NODE_HRULE, - CMARK_NODE_REFERENCE_DEF, +typedef enum { + /* Error status */ + CMARK_NODE_NONE, - CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT, - CMARK_NODE_LAST_BLOCK = CMARK_NODE_REFERENCE_DEF, + /* Block */ + CMARK_NODE_DOCUMENT, + CMARK_NODE_BLOCK_QUOTE, + CMARK_NODE_LIST, + CMARK_NODE_ITEM, + CMARK_NODE_CODE_BLOCK, + CMARK_NODE_HTML, + CMARK_NODE_PARAGRAPH, + CMARK_NODE_HEADER, + CMARK_NODE_HRULE, - /* Inline */ - CMARK_NODE_TEXT, - CMARK_NODE_SOFTBREAK, - CMARK_NODE_LINEBREAK, - CMARK_NODE_INLINE_CODE, - CMARK_NODE_INLINE_HTML, - CMARK_NODE_EMPH, - CMARK_NODE_STRONG, - CMARK_NODE_LINK, - CMARK_NODE_IMAGE, + CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT, + CMARK_NODE_LAST_BLOCK = CMARK_NODE_HRULE, - CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT, - CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE, - } cmark_node_type; + /* Inline */ + CMARK_NODE_TEXT, + CMARK_NODE_SOFTBREAK, + CMARK_NODE_LINEBREAK, + CMARK_NODE_CODE, + CMARK_NODE_INLINE_HTML, + CMARK_NODE_EMPH, + CMARK_NODE_STRONG, + CMARK_NODE_LINK, + CMARK_NODE_IMAGE, - typedef enum { - CMARK_NO_LIST, - CMARK_BULLET_LIST, - CMARK_ORDERED_LIST - } cmark_list_type; + CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT, + CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE, +} cmark_node_type; - typedef enum { - CMARK_PERIOD_DELIM, - CMARK_PAREN_DELIM - } cmark_delim_type; - typedef struct cmark_node cmark_node; - typedef struct cmark_parser cmark_parser; +typedef enum { + CMARK_NO_LIST, + CMARK_BULLET_LIST, + CMARK_ORDERED_LIST +} cmark_list_type; - cmark_node* cmark_node_new(cmark_node_type type); +typedef enum { + CMARK_NO_DELIM, + CMARK_PERIOD_DELIM, + CMARK_PAREN_DELIM +} cmark_delim_type; - void - cmark_node_free(cmark_node *node); +typedef struct cmark_node cmark_node; +typedef struct cmark_parser cmark_parser; +typedef struct cmark_iter cmark_iter; - cmark_node* cmark_node_next(cmark_node *node); +typedef enum { + CMARK_EVENT_NONE, + CMARK_EVENT_DONE, + CMARK_EVENT_ENTER, + CMARK_EVENT_EXIT +} cmark_event_type; - cmark_node* cmark_node_previous(cmark_node *node); +cmark_node* +cmark_node_new(cmark_node_type type); - cmark_node* cmark_node_parent(cmark_node *node); +void +cmark_node_free(cmark_node *node); - cmark_node* cmark_node_first_child(cmark_node *node); +cmark_node* +cmark_node_next(cmark_node *node); - cmark_node* cmark_node_last_child(cmark_node *node); +cmark_node* +cmark_node_previous(cmark_node *node); - cmark_node_type cmark_node_get_type(cmark_node *node); +cmark_node* +cmark_node_parent(cmark_node *node); - const char* cmark_node_get_string_content(cmark_node *node); +cmark_node* +cmark_node_first_child(cmark_node *node); - int cmark_node_set_string_content(cmark_node *node, const char *content); +cmark_node* +cmark_node_last_child(cmark_node *node); - int cmark_node_get_header_level(cmark_node *node); +cmark_iter* +cmark_iter_new(cmark_node *root); - int cmark_node_set_header_level(cmark_node *node, int level); +void +cmark_iter_free(cmark_iter *iter); - cmark_list_type cmark_node_get_list_type(cmark_node *node); +cmark_event_type +cmark_iter_next(cmark_iter *iter); - int cmark_node_set_list_type(cmark_node *node, cmark_list_type type); +cmark_node* +cmark_iter_get_node(cmark_iter *iter); - int cmark_node_get_list_start(cmark_node *node); +cmark_event_type +cmark_iter_get_event_type(cmark_iter *iter); - int cmark_node_set_list_start(cmark_node *node, int start); +cmark_node* +cmark_iter_get_root(cmark_iter *iter); - int cmark_node_get_list_tight(cmark_node *node); +void +cmark_iter_reset(cmark_iter *iter, cmark_node *current, + cmark_event_type event_type); - int cmark_node_set_list_tight(cmark_node *node, int tight); +void* +cmark_node_get_user_data(cmark_node *node); - const char* cmark_node_get_fence_info(cmark_node *node); +int +cmark_node_set_user_data(cmark_node *node, void *user_data); - int cmark_node_set_fence_info(cmark_node *node, const char *info); +cmark_node_type +cmark_node_get_type(cmark_node *node); - const char* cmark_node_get_url(cmark_node *node); +const char* +cmark_node_get_type_string(cmark_node *node); - int cmark_node_set_url(cmark_node *node, const char *url); +const char* +cmark_node_get_literal(cmark_node *node); - const char* cmark_node_get_title(cmark_node *node); +int +cmark_node_set_literal(cmark_node *node, const char *content); - int cmark_node_set_title(cmark_node *node, const char *title); +int +cmark_node_get_header_level(cmark_node *node); - int cmark_node_get_start_line(cmark_node *node); +int +cmark_node_set_header_level(cmark_node *node, int level); - int cmark_node_get_start_column(cmark_node *node); +cmark_list_type +cmark_node_get_list_type(cmark_node *node); - int cmark_node_get_end_line(cmark_node *node); +int +cmark_node_set_list_type(cmark_node *node, cmark_list_type type); - void cmark_node_unlink(cmark_node *node); +cmark_delim_type +cmark_node_get_list_delim(cmark_node *node); - int cmark_node_insert_before(cmark_node *node, cmark_node *sibling); +int +cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim); - int cmark_node_insert_after(cmark_node *node, cmark_node *sibling); +int +cmark_node_get_list_start(cmark_node *node); - int cmark_node_prepend_child(cmark_node *node, cmark_node *child); +int +cmark_node_set_list_start(cmark_node *node, int start); - int cmark_node_append_child(cmark_node *node, cmark_node *child); +int +cmark_node_get_list_tight(cmark_node *node); - cmark_parser *cmark_parser_new(); +int +cmark_node_set_list_tight(cmark_node *node, int tight); - void cmark_parser_free(cmark_parser *parser); +const char* +cmark_node_get_fence_info(cmark_node *node); - cmark_node *cmark_parser_finish(cmark_parser *parser); +int +cmark_node_set_fence_info(cmark_node *node, const char *info); - void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len); +const char* +cmark_node_get_url(cmark_node *node); - cmark_node *cmark_parse_document(const char *buffer, size_t len); +int +cmark_node_set_url(cmark_node *node, const char *url); - char *cmark_render_ast(cmark_node *root); +const char* +cmark_node_get_title(cmark_node *node); - char *cmark_render_html(cmark_node *root); +int +cmark_node_set_title(cmark_node *node, const char *title); + +int +cmark_node_get_start_line(cmark_node *node); + +int +cmark_node_get_start_column(cmark_node *node); + +int +cmark_node_get_end_line(cmark_node *node); + +int +cmark_node_get_end_column(cmark_node *node); + +void +cmark_node_unlink(cmark_node *node); + +int +cmark_node_insert_before(cmark_node *node, cmark_node *sibling); + +int +cmark_node_insert_after(cmark_node *node, cmark_node *sibling); + +int +cmark_node_prepend_child(cmark_node *node, cmark_node *child); + +int +cmark_node_append_child(cmark_node *node, cmark_node *child); + +void +cmark_consolidate_text_nodes(cmark_node *root); + +cmark_parser *cmark_parser_new(int options); + +void cmark_parser_free(cmark_parser *parser); + +void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len); + +cmark_node *cmark_parser_finish(cmark_parser *parser); + +cmark_node *cmark_parse_document(const char *buffer, size_t len, int options); + +char *cmark_render_xml(cmark_node *root, int options); + +char *cmark_render_html(cmark_node *root, int options); + +char *cmark_render_man(cmark_node *root, int options); + +char *cmark_render_commonmark(cmark_node *root, int options, int width); + +extern const int cmark_version; + +extern const char cmark_version_string[]; ]] +CMARK_OPT_DEFAULT = 0 +CMARK_OPT_SOURCEPOS = 1 +CMARK_OPT_HARDBREAKS = 2 +CMARK_OPT_NORMALIZE = 4 +CMARK_OPT_SMART = 8 + local inp = io.read("*all") -local doc = cmark.cmark_parse_document(inp, string.len(inp)) - -local cur = doc -local next -local child - -local walk = function(action) - level = 0 - while cur ~= nil do - action(cur, level) - child = cmark.cmark_node_first_child(cur) - if child == nil then - next = cmark.cmark_node_next(cur) - while next == nil do - cur = cmark.cmark_node_parent(cur) - level = level - 1 - if cur == nil then - break - else - next = cmark.cmark_node_next(cur) - end - end - cur = next - else - level = level + 1 - cur = child - end - end -end - -local type_table = { - 'BLOCK_QUOTE', - 'LIST', - 'LIST_ITEM', - 'CODE_BLOCK', - 'HTML', - 'PARAGRAPH', - 'HEADER', - 'HRULE', - 'REFERENCE_DEF', - 'TEXT', - 'SOFTBREAK', - 'LINEBREAK', - 'INLINE_CODE', - 'INLINE_HTML', - 'EMPH', - 'STRONG', - 'LINK', - 'IMAGE', -} -type_table[0] = 'DOCUMENT' - -local function print_type(node, level) - local t = tonumber(cmark.cmark_node_get_type(node)) - io.write(string.rep(' ', level) .. type_table[t]) - if t == cmark.CMARK_NODE_TEXT then - io.write(' ' .. ffi.string(cmark.cmark_node_get_string_content(node))) - end - io.write('\n') -end - -walk(print_type) - --- local html = ffi.string(cmark.cmark_render_html(doc)) --- print(html) +local doc = cmark.cmark_parse_document(inp, string.len(inp), CMARK_OPT_SMART) +local html = ffi.string(cmark.cmark_render_html(doc, CMARK_OPT_DEFAULT)) +print(html) diff --git a/wrappers/wrapper.py b/wrappers/wrapper.py index 52cbfc7..44d982c 100755 --- a/wrappers/wrapper.py +++ b/wrappers/wrapper.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # Example for using the shared library from python +# Will work with either python 2 or python 3 +# Requires cmark library to be installed from ctypes import CDLL, c_char_p, c_long import sys @@ -9,15 +11,27 @@ import platform sysname = platform.system() if sysname == 'Darwin': - cmark = CDLL("build/src/libcmark.dylib") + libname = "libcmark.dylib" +elif sysname == 'Windows': + libname = "cmark.dll" else: - cmark = CDLL("build/src/libcmark.so") + libname = "libcmark.so" +cmark = CDLL(libname) markdown = cmark.cmark_markdown_to_html markdown.restype = c_char_p -markdown.argtypes = [c_char_p, c_long] +markdown.argtypes = [c_char_p, c_long, c_long] + +opts = 8 # CMARK_OPT_PRETTY def md2html(text): - return markdown(text, len(text)) + if sys.version_info >= (3,0): + textbytes = text.encode('utf-8') + textlen = len(textbytes) + return markdown(textbytes, textlen, opts).decode('utf-8') + else: + textbytes = text + textlen = len(text) + return markdown(textbytes, textlen, opts) sys.stdout.write(md2html(sys.stdin.read())) diff --git a/wrappers/wrapper.rb b/wrappers/wrapper.rb index 59a9b87..2359366 100755 --- a/wrappers/wrapper.rb +++ b/wrappers/wrapper.rb @@ -4,12 +4,12 @@ require 'ffi' module CMark extend FFI::Library ffi_lib ['libcmark', 'cmark'] - attach_function :cmark_markdown_to_html, [:string, :int], :string + attach_function :cmark_markdown_to_html, [:string, :int, :int], :string end def markdown_to_html(s) len = s.bytesize - CMark::cmark_markdown_to_html(s, len) + CMark::cmark_markdown_to_html(s, len, 0) end STDOUT.write(markdown_to_html(ARGF.read())) diff --git a/wrappers/wrapper.rkt b/wrappers/wrapper.rkt new file mode 100644 index 0000000..d9b34e8 --- /dev/null +++ b/wrappers/wrapper.rkt @@ -0,0 +1,190 @@ +#lang racket/base + +;; requires racket >= 5.3 because of submodules + +;; Lowlevel interface + +(module low-level racket/base + + (require ffi/unsafe ffi/unsafe/define) + + (provide (all-defined-out)) + + (define-ffi-definer defcmark (ffi-lib "libcmark")) + + (define _cmark_node_type + (_enum '(none + ;; Block + document block-quote list item code-block + html paragraph header hrule + ;; Inline + text softbreak linebreak code inline-html + emph strong link image))) + (define _cmark_list_type + (_enum '(no_list bullet_list ordered_list))) + (define _cmark_delim_type + (_enum '(no_delim period_delim paren_delim))) + (define _cmark_opts + (_bitmask '(sourcepos = 1 hardbreaks = 2 normalize = 4 smart = 8))) + + (define-cpointer-type _node) + + (defcmark cmark_markdown_to_html + (_fun [bs : _bytes] [_int = (bytes-length bs)] _cmark_opts + -> [r : _bytes] -> (begin0 (bytes->string/utf-8 r) (free r)))) + + (defcmark cmark_parse_document + (_fun [bs : _bytes] [_int = (bytes-length bs)] _cmark_opts + -> _node)) + + (defcmark cmark_render_html + (_fun _node _cmark_opts + -> [r : _bytes] -> (begin0 (bytes->string/utf-8 r) (free r)))) + + (defcmark cmark_node_new (_fun _cmark_node_type -> _node)) + (defcmark cmark_node_free (_fun _node -> _void)) + + (defcmark cmark_node_next (_fun _node -> _node/null)) + (defcmark cmark_node_previous (_fun _node -> _node/null)) + (defcmark cmark_node_parent (_fun _node -> _node/null)) + (defcmark cmark_node_first_child (_fun _node -> _node/null)) + (defcmark cmark_node_last_child (_fun _node -> _node/null)) + + (defcmark cmark_node_get_user_data (_fun _node -> _racket)) + (defcmark cmark_node_set_user_data (_fun _node _racket -> _bool)) + (defcmark cmark_node_get_type (_fun _node -> _cmark_node_type)) + (defcmark cmark_node_get_type_string (_fun _node -> _bytes)) + (defcmark cmark_node_get_literal (_fun _node -> _string)) + (defcmark cmark_node_set_literal (_fun _node _string -> _bool)) + (defcmark cmark_node_get_header_level (_fun _node -> _int)) + (defcmark cmark_node_set_header_level (_fun _node _int -> _bool)) + (defcmark cmark_node_get_list_type (_fun _node -> _cmark_list_type)) + (defcmark cmark_node_set_list_type (_fun _node _cmark_list_type -> _bool)) + (defcmark cmark_node_get_list_delim (_fun _node -> _cmark_delim_type)) + (defcmark cmark_node_set_list_delim (_fun _node _cmark_delim_type -> _bool)) + (defcmark cmark_node_get_list_start (_fun _node -> _int)) + (defcmark cmark_node_set_list_start (_fun _node _int -> _bool)) + (defcmark cmark_node_get_list_tight (_fun _node -> _bool)) + (defcmark cmark_node_set_list_tight (_fun _node _bool -> _bool)) + (defcmark cmark_node_get_fence_info (_fun _node -> _string)) + (defcmark cmark_node_set_fence_info (_fun _node _string -> _bool)) + (defcmark cmark_node_get_url (_fun _node -> _string)) + (defcmark cmark_node_set_url (_fun _node _string -> _bool)) + (defcmark cmark_node_get_title (_fun _node -> _string)) + (defcmark cmark_node_set_title (_fun _node _string -> _bool)) + (defcmark cmark_node_get_start_line (_fun _node -> _int)) + (defcmark cmark_node_get_start_column (_fun _node -> _int)) + (defcmark cmark_node_get_end_line (_fun _node -> _int)) + (defcmark cmark_node_get_end_column (_fun _node -> _int)) + + (defcmark cmark_node_unlink (_fun _node -> _void)) + (defcmark cmark_node_insert_before (_fun _node _node -> _bool)) + (defcmark cmark_node_insert_after (_fun _node _node -> _bool)) + (defcmark cmark_node_prepend_child (_fun _node _node -> _bool)) + (defcmark cmark_node_append_child (_fun _node _node -> _bool)) + (defcmark cmark_consolidate_text_nodes (_fun _node -> _void)) + + ) + +;; Rackety interface + +(module high-level racket/base + + (require (submod ".." low-level) ffi/unsafe) + + (provide cmark-markdown-to-html) + (define (cmark-markdown-to-html str [options '(normalize smart)]) + (cmark_markdown_to_html (if (bytes? str) str (string->bytes/utf-8 str)) + options)) + + (require (for-syntax racket/base racket/syntax)) + (define-syntax (make-getter+setter stx) + (syntax-case stx () + [(_ name) (with-syntax ([(getter setter) + (map (λ(op) (format-id #'name "cmark_node_~a_~a" + op #'name)) + '(get set))]) + #'(cons getter setter))])) + (define-syntax-rule (define-getters+setters name [type field ...] ...) + (define name (list (list 'type (make-getter+setter field) ...) ...))) + (define-getters+setters getters+setters + [header header_level] [code-block fence_info] + [link url title] [image url title] + [list list_type list_delim list_start list_tight]) + + (provide cmark->sexpr) + (define (cmark->sexpr node) + (define text (cmark_node_get_literal node)) + (define type (cmark_node_get_type node)) + (define children + (let loop ([node (cmark_node_first_child node)]) + (if (not node) '() + (cons (cmark->sexpr node) (loop (cmark_node_next node)))))) + (define info + (cond [(assq type getters+setters) + => (λ(gss) (map (λ(gs) ((car gs) node)) (cdr gss)))] + [else '()])) + (define (assert-no what-not b) + (when b (error 'cmark->sexpr "unexpected ~a in ~s" what-not type))) + (cond [(memq type '(document paragraph header block-quote list item + emph strong link image)) + (assert-no 'text text) + (list type info children)] + [(memq type '(text code code-block html inline-html + softbreak linebreak hrule)) + (assert-no 'children (pair? children)) + (list type info text)] + [else (error 'cmark->sexpr "unknown type: ~s" type)])) + + (provide sexpr->cmark) + (define (sexpr->cmark sexpr) ; assumes valid input, as generated by the above + (define (loop sexpr) + (define type (car sexpr)) + (define info (cadr sexpr)) + (define data (caddr sexpr)) + (define node (cmark_node_new type)) + (let ([gss (assq type getters+setters)]) + (when gss + (unless (= (length (cdr gss)) (length info)) + (error 'sexpr->cmark "bad number of info values in ~s" sexpr)) + (for-each (λ(gs x) ((cdr gs) node x)) (cdr gss) info))) + (cond [(string? data) (cmark_node_set_literal node data)] + [(not data) (void)] + [(list? data) + (for ([child (in-list data)]) + (cmark_node_append_child node (sexpr->cmark child)))] + [else (error 'sexpr->cmark "bad data in ~s" sexpr)]) + node) + (define root (loop sexpr)) + (register-finalizer root cmark_node_free) + root) + + ;; Registers a `cmark_node_free` finalizer + (provide cmark-parse-document) + (define (cmark-parse-document str [options '(normalize smart)]) + (define root (cmark_parse_document + (if (bytes? str) str (string->bytes/utf-8 str)) + options)) + (register-finalizer root cmark_node_free) + root) + + (provide cmark-render-html) + (define (cmark-render-html root [options '(normalize smart)]) + (cmark_render_html root options))) + +#; ;; sample use +(begin + (require 'high-level racket/string) + (cmark-render-html + (cmark-parse-document + (string-join '("foo" + "===" + "" + "> blah" + ">" + "> blah *blah* `bar()` blah:" + ">" + "> function foo() {" + "> bar();" + "> }") + "\n")))) diff --git a/wrappers/wrapper3.py b/wrappers/wrapper3.py deleted file mode 100755 index 7a777fa..0000000 --- a/wrappers/wrapper3.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 - -# Example for using the shared library from python - -from ctypes import CDLL, c_char_p, c_long -import sys -import platform - -sysname = platform.system() - -if sysname == 'Darwin': - cmark = CDLL("build/src/libcmark.dylib") -else: - cmark = CDLL("build/src/libcmark.so") - -markdown = cmark.cmark_markdown_to_html -markdown.restype = c_char_p -markdown.argtypes = [c_char_p, c_long] - -def md2html(text): - textbytes = text.encode('utf-8') - textlen = len(textbytes) - return markdown(textbytes, textlen).decode('utf-8') - -sys.stdout.write(md2html(sys.stdin.read())) |