]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mdhelp: add support for <tvh_class_doc> and <tvh_class_items>
authorJaroslav Kysela <perex@perex.cz>
Mon, 18 Apr 2016 12:24:35 +0000 (14:24 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 18 Apr 2016 12:26:47 +0000 (14:26 +0200)
Example (in markdown):

<tvh_class_doc>passwd</tvh_class_doc>
<tvh_class_items>passwd</tvh_class_items>

src/docs.c
src/prop.c
src/webui/doc_md.c
support/doc/md_to_c.py

index 3a7ac9a1210d96737977295d9cf6dbe5d46416ab..c4b71f55ef21548ef292fa1368e18601463625e6 100644 (file)
@@ -1,7 +1,9 @@
 #include <unistd.h>
 #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"
index 7bf6d9372d4806533f422bffac88687d78f774ce..4dedd7c7fb126e71b39c878eaee70f1063ddb8c2 100644 (file)
@@ -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;
     }
index 3acda5fa7589aa7d1bfb355742a0eb163bf5321e..986b21fcea12f00107c6d5a0ace2d311ab499840 100644 (file)
@@ -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;
 }
 
index 4d2f93a9008b9e354ddd9767c7610d6533e2cb33..4ff36663f429baba3f0df40fc470754aea8a5926 100755 (executable)
@@ -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('</' + tag + '>')
+    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 = ''