From 1e158a5a9785703853eb2080543e3d24a6d76b12 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 18 Apr 2016 14:24:35 +0200 Subject: [PATCH] mdhelp: add support for and Example (in markdown): passwd passwd --- src/docs.c | 4 +- src/prop.c | 5 +- src/webui/doc_md.c | 186 ++++++++++++++++++++++++++--------------- support/doc/md_to_c.py | 28 +++++++ 4 files changed, 152 insertions(+), 71 deletions(-) diff --git a/src/docs.c b/src/docs.c index 3a7ac9a12..c4b71f55e 100644 --- a/src/docs.c +++ b/src/docs.c @@ -1,7 +1,9 @@ #include #include "docs.h" -#define LANGPREF "\xff" +#define LANGPREF "\xff\x01" +#define DOCINCPREF "\xff\x02" +#define ITEMSINCPREF "\xff\x03" #define N_(s) s #include "docs_inc.c" diff --git a/src/prop.c b/src/prop.c index 7bf6d9372..4dedd7c7f 100644 --- a/src/prop.c +++ b/src/prop.c @@ -584,7 +584,10 @@ prop_md_doc(const char **doc, const char *lang) for (; *doc; doc++) { if (*doc[0] == '\xff') { - s = tvh_gettext_lang(lang, *doc + 1); + if (*doc[1] == 1) + s = tvh_gettext_lang(lang, *doc + 2); + else + s = ""; } else { s = *doc; } diff --git a/src/webui/doc_md.c b/src/webui/doc_md.c index 3acda5fa7..986b21fce 100644 --- a/src/webui/doc_md.c +++ b/src/webui/doc_md.c @@ -22,6 +22,9 @@ #include "http.h" #include "docs.h" +static int md_class(htsbuf_queue_t *hq, const char *clazz, const char *lang, + int hdr, int docs, int props); + /* */ static int md_nl(htsbuf_queue_t *hq, int nl) @@ -90,72 +93,15 @@ md_text(htsbuf_queue_t *hq, const char *first, const char *next, const char *tex } } -/** - * List of all classes with documentation - */ -static int -http_markdown_classes(http_connection_t *hc) -{ - idclass_t const **all, **all2; - const idclass_t *ic; - htsbuf_queue_t *hq = &hc->hc_reply; - - pthread_mutex_lock(&global_lock); - all = idclass_find_all(); - if (all == NULL) { - pthread_mutex_unlock(&global_lock); - return HTTP_STATUS_NOT_FOUND; - } - for (all2 = all; *all2; all2++) { - ic = *all2; - if (ic->ic_caption) { - htsbuf_append_str(hq, ic->ic_class); - htsbuf_append(hq, "\n", 1); - } - } - pthread_mutex_unlock(&global_lock); - - free(all); - return 0; -} - -/** - * - */ +/* */ static int -http_markdown_class(http_connection_t *hc, const char *clazz) +md_props(htsbuf_queue_t *hq, htsmsg_t *m, const char *lang, int nl) { - const idclass_t *ic; - const char *lang = hc->hc_access->aa_lang_ui; - htsbuf_queue_t *hq = &hc->hc_reply; - htsmsg_t *m, *l, *n, *e, *x; + htsmsg_t *l, *n, *e, *x; htsmsg_field_t *f, *f2; - const char *s, **doc; - int nl = 0, first = 1, b; + const char *s; + int first = 1, b; - pthread_mutex_lock(&global_lock); - ic = idclass_find(clazz); - if (ic == NULL) { - pthread_mutex_unlock(&global_lock); - return HTTP_STATUS_NOT_FOUND; - } - doc = idclass_get_doc(ic); - m = idclass_serializedoc(ic, lang); - pthread_mutex_unlock(&global_lock); - s = htsmsg_get_str(m, "caption"); - if (s) { - md_header(hq, "## ", s); - nl = md_nl(hq, 1); - } - if (doc) { - for (; *doc; doc++) { - if (*doc[0] == '\xff') { - htsbuf_append_str(hq, tvh_gettext_lang(lang, *doc + 1)); - } else { - htsbuf_append_str(hq, *doc); - } - } - } l = htsmsg_get_list(m, "props"); HTSMSG_FOREACH(f, l) { n = htsmsg_field_get_map(f); @@ -211,10 +157,118 @@ http_markdown_class(http_connection_t *hc, const char *clazz) } } } + return nl; +} + +/* */ +static void +md_render(htsbuf_queue_t *hq, const char *doc, const char *lang) +{ + if (doc[0] == '\xff') { + switch (doc[1]) { + case 1: + htsbuf_append_str(hq, tvh_gettext_lang(lang, doc + 2)); + break; + case 2: + md_class(hq, doc + 2, lang, 0, 1, 0); + break; + case 3: + md_class(hq, doc + 2, lang, 0, 0, 1); + break; + } + } else { + htsbuf_append_str(hq, doc); + } +} + +/* */ +static int +md_doc(htsbuf_queue_t *hq, const char **doc, const char *lang, int nl) +{ + if (doc == NULL) + return nl; + for (; *doc; doc++) { + md_render(hq, *doc, lang); + nl = 1; + } + return nl; +} + +/* */ +static int +md_class(htsbuf_queue_t *hq, const char *clazz, const char *lang, + int hdr, int docs, int props) +{ + const idclass_t *ic; + htsmsg_t *m; + const char *s, **doc; + int nl = 0; + + pthread_mutex_lock(&global_lock); + ic = idclass_find(clazz); + if (ic == NULL) { + pthread_mutex_unlock(&global_lock); + return HTTP_STATUS_NOT_FOUND; + } + doc = idclass_get_doc(ic); + m = idclass_serializedoc(ic, lang); + pthread_mutex_unlock(&global_lock); + if (hdr) { + s = htsmsg_get_str(m, "caption"); + if (s) { + md_header(hq, "## ", s); + nl = md_nl(hq, 1); + } + } + if (docs) + nl = md_doc(hq, doc, lang, nl); + if (props) + nl = md_props(hq, m, lang, nl); htsmsg_destroy(m); return 0; } +/** + * List of all classes with documentation + */ +static int +http_markdown_classes(http_connection_t *hc) +{ + idclass_t const **all, **all2; + const idclass_t *ic; + htsbuf_queue_t *hq = &hc->hc_reply; + + pthread_mutex_lock(&global_lock); + all = idclass_find_all(); + if (all == NULL) { + pthread_mutex_unlock(&global_lock); + return HTTP_STATUS_NOT_FOUND; + } + for (all2 = all; *all2; all2++) { + ic = *all2; + if (ic->ic_caption) { + htsbuf_append_str(hq, ic->ic_class); + htsbuf_append(hq, "\n", 1); + } + } + pthread_mutex_unlock(&global_lock); + + free(all); + return 0; +} + +/** + * + */ +static int +http_markdown_class(http_connection_t *hc, const char *clazz) +{ + const char *lang = hc->hc_access->aa_lang_ui; + htsbuf_queue_t *hq = &hc->hc_reply; + + return md_class(hq, clazz, lang, 1, 1, 1); +} + /** * */ @@ -227,13 +281,7 @@ http_markdown_page(http_connection_t *hc, const struct tvh_doc_page *page) if (doc == NULL) return HTTP_STATUS_NOT_FOUND; - for (; *doc; doc++) { - if (*doc[0] == '\xff') { - htsbuf_append_str(hq, tvh_gettext_lang(lang, *doc + 1)); - } else { - htsbuf_append_str(hq, *doc); - } - } + md_doc(hq, doc, lang, 0); return 0; } diff --git a/support/doc/md_to_c.py b/support/doc/md_to_c.py index 4d2f93a90..4ff36663f 100755 --- a/support/doc/md_to_c.py +++ b/support/doc/md_to_c.py @@ -100,8 +100,22 @@ class TVH_C_Renderer(Renderer): r += t if type == 'x': xfound = 1 + elif type != '_': + fatal('wrong type: ' + type + ' {' + t + '}') return d + (xfound and self.get_lang(r) or self.get_nolang(r)) + def extra_cmd(self, text, tag, type): + pos1 = text.find('<' + tag + '>') + if pos1 < 0: + return 0 + pos2 = text.find('') + if pos2 < 0: + return 0 + link = text[pos1 + len(tag) + 2:pos2] + if len(link) <= 0: + return 0 + return type + str(len(link)) + ':' + link + def get_block(self, text): type = text[0] p = text.find(':') @@ -179,6 +193,11 @@ class TVH_C_Renderer(Renderer): return r def block_html(self, text): + if DEBUG: debug('block html: ' + repr(text)) + a = self.extra_cmd(text, 'tvh_class_doc', 'd') + if a: return a + a = self.extra_cmd(text, 'tvh_class_items', 'i') + if a: return a fatal('Block HTML not allowed: ' + repr(text)) def inline_html(self, text): @@ -365,6 +384,15 @@ def optimize(text): if x: r += lang(x) x = '' n += t + elif type == 'd' or type == 'i': + if n: r += nolang(n) + if x: r += lang(x) + n = '' + x = '' + if type == 'd': + r += 'DOCINCPREF "' + t + '",\n' + else: + r += 'ITEMSINCPREF "' + t + '",\n' text = text[p+l+1:] if x: r += lang(x) x = '' -- 2.47.3