Пример #1
0
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
                         cmark_event_type ev_type, int options) {
  int list_number;
  int enumlevel;
  char list_number_string[LIST_NUMBER_STRING_SIZE];
  bool entering = (ev_type == CMARK_EVENT_ENTER);
  cmark_list_type list_type;
  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);

  // avoid warning about unused parameter:
  (void)(options);

  switch (node->type) {
  case CMARK_NODE_DOCUMENT:
    break;

  case CMARK_NODE_BLOCK_QUOTE:
    if (entering) {
      LIT("\\begin{quote}");
      CR();
    } else {
      LIT("\\end{quote}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_LIST:
    list_type = cmark_node_get_list_type(node);
    if (entering) {
      LIT("\\begin{");
      LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
      LIT("}");
      CR();
      list_number = cmark_node_get_list_start(node);
      if (list_number > 1) {
	enumlevel = S_get_enumlevel(node);
	// latex normally supports only five levels
	if (enumlevel >= 1 && enumlevel <= 5) {
          snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d",
                   list_number);
          LIT("\\setcounter{enum");
          switch(enumlevel) {
	  case 1: LIT("i"); break;
	  case 2: LIT("ii"); break;
	  case 3: LIT("iii"); break;
	  case 4: LIT("iv"); break;
	  case 5: LIT("v"); break;
	  default: LIT("i"); break;
	  }
          LIT("}{");
          OUT(list_number_string, false, NORMAL);
          LIT("}");
	}
        CR();
      }
    } else {
      LIT("\\end{");
      LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
      LIT("}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_ITEM:
    if (entering) {
      LIT("\\item ");
    } else {
      CR();
    }
    break;

  case CMARK_NODE_HEADING:
    if (entering) {
      switch (cmark_node_get_heading_level(node)) {
      case 1:
        LIT("\\section");
        break;
      case 2:
        LIT("\\subsection");
        break;
      case 3:
        LIT("\\subsubsection");
        break;
      case 4:
        LIT("\\paragraph");
        break;
      case 5:
        LIT("\\subparagraph");
        break;
      }
      LIT("{");
    } else {
      LIT("}");
      BLANKLINE();
    }
    break;

  case CMARK_NODE_CODE_BLOCK:
    CR();
    LIT("\\begin{verbatim}");
    CR();
    OUT(cmark_node_get_literal(node), false, LITERAL);
    CR();
    LIT("\\end{verbatim}");
    BLANKLINE();
    break;

  case CMARK_NODE_HTML_BLOCK:
    break;

  case CMARK_NODE_CUSTOM_BLOCK:
    CR();
    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
        false, LITERAL);
    CR();
    break;

  case CMARK_NODE_THEMATIC_BREAK:
    BLANKLINE();
    LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}");
    BLANKLINE();
    break;

  case CMARK_NODE_PARAGRAPH:
    if (!entering) {
      BLANKLINE();
    }
    break;

  case CMARK_NODE_TEXT:
    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
    break;

  case CMARK_NODE_LINEBREAK:
    LIT("\\\\");
    CR();
    break;

  case CMARK_NODE_SOFTBREAK:
    if (options & CMARK_OPT_HARDBREAKS) {
      LIT("\\\\");
      CR();
    } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
      CR();
    } else {
      OUT(" ", allow_wrap, NORMAL);
    }
    break;

  case CMARK_NODE_CODE:
    LIT("\\texttt{");
    OUT(cmark_node_get_literal(node), false, NORMAL);
    LIT("}");
    break;

  case CMARK_NODE_HTML_INLINE:
    break;

  case CMARK_NODE_CUSTOM_INLINE:
    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
        false, LITERAL);
    break;

  case CMARK_NODE_STRONG:
    if (entering) {
      LIT("\\textbf{");
    } else {
      LIT("}");
    }
    break;

  case CMARK_NODE_EMPH:
    if (entering) {
      LIT("\\emph{");
    } else {
      LIT("}");
    }
    break;

  case CMARK_NODE_LINK:
    if (entering) {
      const char *url = cmark_node_get_url(node);
      // requires \usepackage{hyperref}
      switch (get_link_type(node)) {
      case URL_AUTOLINK:
        LIT("\\url{");
        OUT(url, false, URL);
        LIT("}");
        return 0; // Don't process further nodes to avoid double-rendering artefacts
      case EMAIL_AUTOLINK:
        LIT("\\href{");
        OUT(url, false, URL);
        LIT("}\\nolinkurl{");
        break;
      case NORMAL_LINK:
        LIT("\\href{");
        OUT(url, false, URL);
        LIT("}{");
        break;
      case INTERNAL_LINK:
        LIT("\\protect\\hyperlink{");
        OUT(url + 1, false, URL);
        LIT("}{");
        break;
      case NO_LINK:
        LIT("{"); // error?
      }
    } else {
      LIT("}");
    }

    break;

  case CMARK_NODE_IMAGE:
    if (entering) {
      LIT("\\protect\\includegraphics{");
      // requires \include{graphicx}
      OUT(cmark_node_get_url(node), false, URL);
      LIT("}");
      return 0;
    }
    break;

  default:
    assert(false);
    break;
  }

  return 1;
}
Пример #2
0
static int
S_render_node(cmark_renderer *renderer,
	      cmark_node *node,
	      cmark_event_type ev_type,
	      int options)
{
	int list_number;
	char list_number_string[20];
	bool entering = (ev_type == CMARK_EVENT_ENTER);
	cmark_list_type list_type;
	const char* roman_numerals[] = { "", "i", "ii", "iii", "iv", "v",
	                                 "vi", "vii", "viii", "ix", "x"
	                               };

	// avoid warning about unused parameter:
	(void)(options);

	switch (node->type) {
	case CMARK_NODE_DOCUMENT:
		break;

	case CMARK_NODE_BLOCK_QUOTE:
		if (entering) {
			LIT("\\begin{quote}");
			CR();
		} else {
			LIT("\\end{quote}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_LIST:
		list_type = cmark_node_get_list_type(node);
		if (entering) {
			LIT("\\begin{");
			LIT(list_type == CMARK_ORDERED_LIST ?
			    "enumerate" : "itemize");
			LIT("}");
			CR();
			list_number = cmark_node_get_list_start(node);
			if (list_number > 1) {
				sprintf(list_number_string,
				         "%d", list_number);
				LIT("\\setcounter{enum");
				LIT((char *)roman_numerals[S_get_enumlevel(node)]);
				LIT("}{");
				OUT(list_number_string, false, NORMAL);
				LIT("}");
				CR();
			}
		} else {
			LIT("\\end{");
			LIT(list_type == CMARK_ORDERED_LIST ?
			    "enumerate" : "itemize");
			LIT("}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_ITEM:
		if (entering) {
			LIT("\\item ");
		} else {
			CR();
		}
		break;

	case CMARK_NODE_HEADER:
		if (entering) {
			switch (cmark_node_get_header_level(node)) {
			case 1:
				LIT("\\section");
				break;
			case 2:
				LIT("\\subsection");
				break;
			case 3:
				LIT("\\subsubsection");
				break;
			case 4:
				LIT("\\paragraph");
				break;
			case 5:
				LIT("\\subparagraph");
				break;
			}
			LIT("{");
		} else {
			LIT("}");
			BLANKLINE();
		}
		break;

	case CMARK_NODE_CODE_BLOCK:
		CR();
		LIT("\\begin{verbatim}");
		CR();
		OUT(cmark_node_get_literal(node), false, LITERAL);
		CR();
		LIT("\\end{verbatim}");
		BLANKLINE();
		break;

	case CMARK_NODE_HTML:
		break;

	case CMARK_NODE_HRULE:
		BLANKLINE();
		LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}");
		BLANKLINE();
		break;

	case CMARK_NODE_PARAGRAPH:
		if (!entering) {
			BLANKLINE();
		}
		break;

	case CMARK_NODE_TEXT:
		OUT(cmark_node_get_literal(node), true, NORMAL);
		break;

	case CMARK_NODE_LINEBREAK:
		LIT("\\\\");
		CR();
		break;

	case CMARK_NODE_SOFTBREAK:
		if (renderer->width == 0) {
			CR();
		} else {
			OUT(" ", true, NORMAL);
		}
		break;

	case CMARK_NODE_CODE:
		LIT("\\texttt{");
		OUT(cmark_node_get_literal(node), false, NORMAL);
		LIT("}");
		break;

	case CMARK_NODE_INLINE_HTML:
		break;

	case CMARK_NODE_STRONG:
		if (entering) {
			LIT("\\textbf{");
		} else {
			LIT("}");
		}
		break;

	case CMARK_NODE_EMPH:
		if (entering) {
			LIT("\\emph{");
		} else {
			LIT("}");
		}
		break;

	case CMARK_NODE_LINK:
		if (entering) {
			const char* url = cmark_node_get_url(node);
			// requires \usepackage{hyperref}
			switch(get_link_type(node)) {
			case URL_AUTOLINK:
				LIT("\\url{");
				OUT(url, false, URL);
				break;
			case EMAIL_AUTOLINK:
				LIT("\\href{");
				OUT(url, false, URL);
				LIT("}\\nolinkurl{");
				break;
			case NORMAL_LINK:
				LIT("\\href{");
				OUT(url, false, URL);
				LIT("}{");
				break;
			case NO_LINK:
				LIT("{");  // error?
			}
		} else {
			LIT("}");
		}

		break;

	case CMARK_NODE_IMAGE:
		if (entering) {
			LIT("\\protect\\includegraphics{");
			// requires \include{graphicx}
			OUT(cmark_node_get_url(node), false, URL);
			LIT("}");
			return 0;
		}
		break;

	default:
		assert(false);
		break;
	}

	return 1;
}