Example #1
0
static inline void outc(cmark_renderer *renderer, cmark_escaping escape,
                        int32_t c, unsigned char nextc) {
  bool needs_escaping = false;
  char encoded[20];

  needs_escaping =
      escape != LITERAL &&
      ((escape == NORMAL &&
        (c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
         c == '>' || c == '\\' || c == '`' || c == '!' ||
         (c == '&' && isalpha(nextc)) || (c == '!' && nextc == '[') ||
         (renderer->begin_line && (c == '-' || c == '+' || c == '=')) ||
         ((c == '.' || c == ')') &&
          isdigit(renderer->buffer->ptr[renderer->buffer->size - 1])))) ||
       (escape == URL && (c == '`' || c == '<' || c == '>' || isspace(c) ||
                          c == '\\' || c == ')' || c == '(')) ||
       (escape == TITLE &&
        (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));

  if (needs_escaping) {
    if (isspace(c)) {
      // use percent encoding for spaces
      sprintf(encoded, "%%%2x", c);
      cmark_strbuf_puts(renderer->buffer, encoded);
      renderer->column += 3;
    } else {
      cmark_render_ascii(renderer, "\\");
      cmark_render_code_point(renderer, c);
    }
  } else {
    cmark_render_code_point(renderer, c);
  }
}
Example #2
0
// Functions to convert cmark_nodes to groff man strings.
static
void S_outc(cmark_renderer *renderer,
            cmark_escaping escape,
            int32_t c,
            unsigned char nextc)
{
	(void)(nextc);

	if (escape == LITERAL) {
		cmark_render_code_point(renderer, c);
		return;
	}

	switch(c) {
	case 46:
		if (renderer->begin_line) {
			cmark_render_ascii(renderer, "\\&.");
		} else {
			cmark_render_code_point(renderer, c);
		}
		break;
	case 39:
		if (renderer->begin_line) {
			cmark_render_ascii(renderer, "\\&'");
		} else {
			cmark_render_code_point(renderer, c);
		}
		break;
	case 45:
		cmark_render_ascii(renderer, "\\-");
		break;
	case 92:
		cmark_render_ascii(renderer, "\\e");
		break;
	case 8216: // left single quote
		cmark_render_ascii(renderer, "\\[oq]");
		break;
	case 8217: // right single quote
		cmark_render_ascii(renderer, "\\[cq]");
		break;
	case 8220: // left double quote
		cmark_render_ascii(renderer, "\\[lq]");
		break;
	case 8221: // right double quote
		cmark_render_ascii(renderer, "\\[rq]");
		break;
	case 8212: // em dash
		cmark_render_ascii(renderer, "\\[em]");
		break;
	case 8211: // en dash
		cmark_render_ascii(renderer, "\\[en]");
		break;
	default:
		cmark_render_code_point(renderer, c);
	}
}
Example #3
0
static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
                              int32_t c, unsigned char nextc) {
  bool needs_escaping = false;
  bool follows_digit =
      renderer->buffer->size > 0 &&
      cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]);
  char encoded[ENCODED_SIZE];

  needs_escaping =
      c < 0x80 && escape != LITERAL &&
      ((escape == NORMAL &&
        (c < 0x20 ||
	 c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
         c == '>' || c == '\\' || c == '`' || c == '!' ||
         (c == '&' && cmark_isalpha(nextc)) || (c == '!' && nextc == '[') ||
         (renderer->begin_content && (c == '-' || c == '+' || c == '=') &&
          // begin_content doesn't get set to false til we've passed digits
          // at the beginning of line, so...
          !follows_digit) ||
         (renderer->begin_content && (c == '.' || c == ')') && follows_digit &&
          (nextc == 0 || cmark_isspace(nextc))))) ||
       (escape == URL &&
        (c == '`' || c == '<' || c == '>' || cmark_isspace(c) || c == '\\' ||
         c == ')' || c == '(')) ||
       (escape == TITLE &&
        (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));

  if (needs_escaping) {
    if (escape == URL && cmark_isspace(c)) {
      // use percent encoding for spaces
      snprintf(encoded, ENCODED_SIZE, "%%%2X", c);
      cmark_strbuf_puts(renderer->buffer, encoded);
      renderer->column += 3;
    } else if (cmark_ispunct(c)) {
      cmark_render_ascii(renderer, "\\");
      cmark_render_code_point(renderer, c);
    } else { // render as entity
      snprintf(encoded, ENCODED_SIZE, "&#%d;", c);
      cmark_strbuf_puts(renderer->buffer, encoded);
      renderer->column += strlen(encoded);
    }
  } else {
    cmark_render_code_point(renderer, c);
  }
}
Example #4
0
static void S_out(cmark_renderer *renderer, cmark_node *node,
                  const char *source, bool wrap,
                  cmark_escaping escape) {
  int length = (int)strlen(source);
  unsigned char nextc;
  int32_t c;
  int i = 0;
  int last_nonspace;
  int len;
  cmark_chunk remainder = cmark_chunk_literal("");
  int k = renderer->buffer->size - 1;

  cmark_syntax_extension *ext = NULL;
  cmark_node *n = node;
  while (n && !ext) {
    ext = n->extension;
    if (!ext)
      n = n->parent;
  }
  if (ext && !ext->commonmark_escape_func)
    ext = NULL;

  wrap = wrap && !renderer->no_linebreaks;

  if (renderer->in_tight_list_item && renderer->need_cr > 1) {
    renderer->need_cr = 1;
  }
  while (renderer->need_cr) {
    if (k < 0 || renderer->buffer->ptr[k] == '\n') {
      k -= 1;
    } else {
      cmark_strbuf_putc(renderer->buffer, '\n');
      if (renderer->need_cr > 1) {
        cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
                         renderer->prefix->size);
      }
    }
    renderer->column = 0;
    renderer->begin_line = true;
    renderer->begin_content = true;
    renderer->need_cr -= 1;
  }

  while (i < length) {
    if (renderer->begin_line) {
      cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
                       renderer->prefix->size);
      // note: this assumes prefix is ascii:
      renderer->column = renderer->prefix->size;
    }

    len = cmark_utf8proc_iterate((const uint8_t *)source + i, length - i, &c);
    if (len == -1) { // error condition
      return;        // return without rendering rest of string
    }

    if (ext && ext->commonmark_escape_func(ext, node, c))
      cmark_strbuf_putc(renderer->buffer, '\\');

    nextc = source[i + len];
    if (c == 32 && wrap) {
      if (!renderer->begin_line) {
        last_nonspace = renderer->buffer->size;
        cmark_strbuf_putc(renderer->buffer, ' ');
        renderer->column += 1;
        renderer->begin_line = false;
        renderer->begin_content = false;
        // skip following spaces
        while (source[i + 1] == ' ') {
          i++;
        }
        // We don't allow breaks that make a digit the first character
        // because this causes problems with commonmark output.
        if (!cmark_isdigit(source[i + 1])) {
          renderer->last_breakable = last_nonspace;
        }
      }

    } else if (c == 10) {
      cmark_strbuf_putc(renderer->buffer, '\n');
      renderer->column = 0;
      renderer->begin_line = true;
      renderer->begin_content = true;
      renderer->last_breakable = 0;
    } else if (escape == LITERAL) {
      cmark_render_code_point(renderer, c);
      renderer->begin_line = false;
      // we don't set 'begin_content' to false til we've
      // finished parsing a digit.  Reason:  in commonmark
      // we need to escape a potential list marker after
      // a digit:
      renderer->begin_content =
          renderer->begin_content && cmark_isdigit((char)c) == 1;
    } else {
      (renderer->outc)(renderer, node, escape, c, nextc);
      renderer->begin_line = false;
      renderer->begin_content =
          renderer->begin_content && cmark_isdigit((char)c) == 1;
    }

    // If adding the character went beyond width, look for an
    // earlier place where the line could be broken:
    if (renderer->width > 0 && renderer->column > renderer->width &&
        !renderer->begin_line && renderer->last_breakable > 0) {

      // copy from last_breakable to remainder
      cmark_chunk_set_cstr(renderer->mem, &remainder,
                           (char *)renderer->buffer->ptr +
                               renderer->last_breakable + 1);
      // truncate at last_breakable
      cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable);
      // add newline, prefix, and remainder
      cmark_strbuf_putc(renderer->buffer, '\n');
      cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
                       renderer->prefix->size);
      cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len);
      renderer->column = renderer->prefix->size + remainder.len;
      cmark_chunk_free(renderer->mem, &remainder);
      renderer->last_breakable = 0;
      renderer->begin_line = false;
      renderer->begin_content = false;
    }

    i += len;
  }
}
Example #5
0
static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
                              int32_t c, unsigned char nextc) {
  if (escape == LITERAL) {
    cmark_render_code_point(renderer, c);
    return;
  }

  switch (c) {
  case 123: // '{'
  case 125: // '}'
  case 35:  // '#'
  case 37:  // '%'
  case 38:  // '&'
    cmark_render_ascii(renderer, "\\");
    cmark_render_code_point(renderer, c);
    break;
  case 36: // '$'
  case 95: // '_'
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "\\");
    }
    cmark_render_code_point(renderer, c);
    break;
  case 45:             // '-'
    if (nextc == 45) { // prevent ligature
      cmark_render_ascii(renderer, "-{}");
    } else {
      cmark_render_ascii(renderer, "-");
    }
    break;
  case 126: // '~'
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "\\textasciitilde{}");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 94: // '^'
    cmark_render_ascii(renderer, "\\^{}");
    break;
  case 92: // '\\'
    if (escape == URL) {
      // / acts as path sep even on windows:
      cmark_render_ascii(renderer, "/");
    } else {
      cmark_render_ascii(renderer, "\\textbackslash{}");
    }
    break;
  case 124: // '|'
    cmark_render_ascii(renderer, "\\textbar{}");
    break;
  case 60: // '<'
    cmark_render_ascii(renderer, "\\textless{}");
    break;
  case 62: // '>'
    cmark_render_ascii(renderer, "\\textgreater{}");
    break;
  case 91: // '['
  case 93: // ']'
    cmark_render_ascii(renderer, "{");
    cmark_render_code_point(renderer, c);
    cmark_render_ascii(renderer, "}");
    break;
  case 34: // '"'
    cmark_render_ascii(renderer, "\\textquotedbl{}");
    // requires \usepackage[T1]{fontenc}
    break;
  case 39: // '\''
    cmark_render_ascii(renderer, "\\textquotesingle{}");
    // requires \usepackage{textcomp}
    break;
  case 160: // nbsp
    cmark_render_ascii(renderer, "~");
    break;
  case 8230: // hellip
    cmark_render_ascii(renderer, "\\ldots{}");
    break;
  case 8216: // lsquo
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "`");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 8217: // rsquo
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "\'");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 8220: // ldquo
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "``");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 8221: // rdquo
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "''");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 8212: // emdash
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "---");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  case 8211: // endash
    if (escape == NORMAL) {
      cmark_render_ascii(renderer, "--");
    } else {
      cmark_render_code_point(renderer, c);
    }
    break;
  default:
    cmark_render_code_point(renderer, c);
  }
}
Example #6
0
static
void S_out(cmark_renderer *renderer,
           const char *source,
           bool wrap,
           cmark_escaping escape)
{
	int length = cmark_strbuf_safe_strlen(source);
	unsigned char nextc;
	int32_t c;
	int i = 0;
	int len;
	cmark_chunk remainder = cmark_chunk_literal("");
	int k = renderer->buffer->size - 1;

	wrap = wrap && !renderer->no_wrap;

	if (renderer->in_tight_list_item && renderer->need_cr > 1) {
		renderer->need_cr = 1;
	}
	while (renderer->need_cr) {
		if (k < 0 || renderer->buffer->ptr[k] == '\n') {
			k -= 1;
		} else {
			cmark_strbuf_putc(renderer->buffer, '\n');
			if (renderer->need_cr > 1) {
				cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
				                 renderer->prefix->size);
			}
		}
		renderer->column = 0;
		renderer->begin_line = true;
		renderer->need_cr -= 1;
	}

	while (i < length) {
		if (renderer->begin_line) {
			cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
			                 renderer->prefix->size);
			// note: this assumes prefix is ascii:
			renderer->column = renderer->prefix->size;
		}

		len = utf8proc_iterate((const uint8_t *)source + i, length - i, &c);
		if (len == -1) { // error condition
			return;  // return without rendering rest of string
		}
		nextc = source[i + len];
		if (c == 32 && wrap) {
			if (!renderer->begin_line) {
				cmark_strbuf_putc(renderer->buffer, ' ');
				renderer->column += 1;
				renderer->begin_line = false;
				renderer->last_breakable = renderer->buffer->size -
				                           1;
				// skip following spaces
				while (source[i + 1] == ' ') {
					i++;
				}
			}

		} else if (c == 10) {
			cmark_strbuf_putc(renderer->buffer, '\n');
			renderer->column = 0;
			renderer->begin_line = true;
			renderer->last_breakable = 0;
		} else if (escape == LITERAL) {
			cmark_render_code_point(renderer, c);
			renderer->begin_line = false;
		} else {
			(renderer->outc)(renderer, escape, c, nextc);
			renderer->begin_line = false;
		}

		// If adding the character went beyond width, look for an
		// earlier place where the line could be broken:
		if (renderer->width > 0 &&
		    renderer->column > renderer->width &&
		    !renderer->begin_line &&
		    renderer->last_breakable > 0) {

			// copy from last_breakable to remainder
			cmark_chunk_set_cstr(&remainder, (char *) renderer->buffer->ptr + renderer->last_breakable + 1);
			// truncate at last_breakable
			cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable);
			// add newline, prefix, and remainder
			cmark_strbuf_putc(renderer->buffer, '\n');
			cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
			                 renderer->prefix->size);
			cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len);
			renderer->column = renderer->prefix->size + remainder.len;
			cmark_chunk_free(&remainder);
			renderer->last_breakable = 0;
			renderer->begin_line = false;
		}

		i += len;
	}
}