char*
OxMarkDownToHtml(char* sMarkDown)
{
	hoedown_renderer *renderer;
	hoedown_document *document;
	hoedown_buffer *buffer;
	unsigned int extensions = 0, render_flags = 0;
	const uint8_t *sHtml;

	renderer = hoedown_html_renderer_new(render_flags, 0);
	document = hoedown_document_new(renderer, extensions, 16);
	buffer = hoedown_buffer_new(16);
    
	hoedown_document_render(document, buffer, (const uint8_t *)sMarkDown, strlen(sMarkDown));
	sHtml = (char*)OxAllocate(buffer->size + 1);
	StringCchCopyA(sHtml, buffer->size + 1, buffer->data);
	hoedown_buffer_reset(buffer);
	hoedown_html_smartypants(buffer, sHtml, buffer->size);
	
	hoedown_buffer_free(buffer);
	hoedown_document_free(document);
	hoedown_html_renderer_free(renderer);

	return sHtml;
}
Exemple #2
0
//
// return html rendered markdown of note text
//
QString Note::toMarkdownHtml() {
    hoedown_renderer *renderer = hoedown_html_renderer_new( HOEDOWN_HTML_USE_XHTML, 16 );
    hoedown_document *document = hoedown_document_new(renderer, (hoedown_extensions) HOEDOWN_EXT_SPAN, 16);

    QString str = this->noteText;

    unsigned char *sequence = (unsigned char*)qstrdup( str.toUtf8().constData() );
    int length = strlen( (char*) sequence );

    // return an empty string if the note is empty
    if ( length == 0 )
    {
        return "";
    }

    hoedown_buffer *html = hoedown_buffer_new( length );

    // render markdown html
    hoedown_document_render( document, html, sequence, length );

    // get markdown html
    QString result = QString::fromUtf8( (char*) html->data, html->size );

    /* Cleanup */
    free(sequence);
    hoedown_buffer_free(html);

    hoedown_document_free(document);
    hoedown_html_renderer_free(renderer);

    return result;
}
Exemple #3
0
// Converts markdown to html
QString
Markdown::convert2html(const QString& markdown)
{
    QString html;

    if ( !markdown.isEmpty() ) {
        QString markdownClean = parseCustomLinksForHTML(markdown);

        hoedown_html_flags flags = HOEDOWN_HTML_USE_XHTML;
        hoedown_extensions extensions = (hoedown_extensions)(HOEDOWN_EXT_BLOCK|HOEDOWN_EXT_SPAN|HOEDOWN_EXT_FLAGS);
        size_t max_nesting = 16;
        hoedown_renderer *renderer = hoedown_html_renderer_new(flags, 0);
        hoedown_document *document = hoedown_document_new(renderer, extensions, max_nesting);
        hoedown_buffer *result = hoedown_buffer_new(max_nesting);
        std::string markdownStr = markdownClean.toStdString();
        hoedown_document_render( document, result, reinterpret_cast<const uint8_t*>(&markdownStr[0]), markdownStr.size() );

        std::ostringstream convert;
        for (size_t x = 0; x < result->size; x++) {
            convert << result->data[x];
        }

        html = QString::fromStdString( convert.str() );

        hoedown_buffer_free(result);
        hoedown_document_free(document);
        hoedown_html_renderer_free(renderer);
    }

    return html;
}
Exemple #4
0
void Preview::refresh()
{
	if (!needRefresh)
		return;
	
	if (type == MARKDOWN)
	{
		qDebug() << "Render Markdown and refresh preview";

		std::string std_str = content.toStdString();
		const char* cstr = std_str.c_str();

		hoedown_buffer_set(buf, 0, 0);

		hoedown_document_render(document, buf, (const uint8_t*)cstr, strlen(cstr));

		QString html((const char*)buf->data);
		html = themelize(html);

		webView->setHtml(html);

		needRefresh = false;
	}
	else if (type == HTML)
	{
		qDebug() << "Render html and refresh preview";
		qDebug() << "content: " << content;

		webView->setHtml(content);
		needRefresh = false;
	}
	
}
Exemple #5
0
QString Markdown::parseMarkdown(QString input) {

    if (input == "") input.append(" ");

    hoedown_buffer *ib, *ob;
    size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;
    hoedown_document *document;
    hoedown_extensions extensions;
    size_t max_nesting = DEF_MAX_NESTING;
    hoedown_renderer *renderer = NULL;
    void (*renderer_free)(hoedown_renderer*) = NULL;
    hoedown_html_flags html_flags;
    int toc_level = 0;

    html_flags = HOEDOWN_HTML_HARD_WRAP;
    extensions = HOEDOWN_EXT_QUOTE;

    renderer = hoedown_html_renderer_new(html_flags, toc_level);
    renderer_free = hoedown_html_renderer_free;

    ib = hoedown_buffer_new(iunit);

    // reading input

        std::string stdStringInput = input.toUtf8().constData();
        unsigned char* charInput = (unsigned char *)stdStringInput.c_str();

        ib->data = charInput + ib->size;
        ib->size = strlen((char*)charInput);

    // eori

    ob = hoedown_buffer_new(ounit);
    document = hoedown_document_new(renderer, extensions, max_nesting);
    hoedown_document_render(document, ob, ib->data, ib->size);

    std::string outputStdString = (char*) ob->data;

    // this is for trimming output buffer
    outputStdString.erase(ob->size, outputStdString.length());

    hoedown_document_free(document);
    hoedown_buffer_free(ob);
    renderer_free(renderer);
    //free(ib);

    QString output = QString::fromStdString(outputStdString);
    return output;
}
Exemple #6
0
int
main(int argc, char **argv)
{
	int show_time = 0;
	//struct timespec start, end;

	/* buffers */
	hoedown_buffer *ib, *ob;
	size_t iunit = DEF_IUNIT, ounit = DEF_OUNIT;

	/* files */
	FILE *in = NULL;

	/* renderer */
	int toc_level = 0;
	int renderer_type = RENDERER_HTML;

	/* document */
	hoedown_document *document;
	unsigned int extensions = 0;
	size_t max_nesting = DEF_MAX_NESTING;

	/* HTML renderer-specific */
	unsigned int html_flags = 0;


	/* option parsing */
	int just_args = 0;
	int i, j;
	for (i = 1; i < argc; i++) {
		char *arg = argv[i];
		if (!arg[0]) continue;

		if (just_args || arg[0] != '-') {
			/* regular argument */
			in = fopen(arg, "r");
			if (!in) {
				fprintf(stderr, "Unable to open input file \"%s\": %s\n", arg, strerror(errno));
				return 5;
			}
			continue;
		}

		if (!arg[1]) {
			/* arg is "-" */
			in = stdin;
			continue;
		}

		if (arg[1] != '-') {
			/* parse short options */
			char opt;
			const char *val;
			for (j = 1; (opt = arg[j]); j++) {
				if (opt == 'h') {
					print_help(argv[0]);
					return 1;
				}

				if (opt == 'v') {
					print_version();
					return 1;
				}

				if (opt == 'T') {
					show_time = 1;
					continue;
				}

				/* options requiring value */
				if (arg[++j]) val = arg+j;
				else if (argv[++i]) val = argv[i];
				else {
					fprintf(stderr, "Wrong option '-%c' found.\n", opt);
					return 1;
				}

				long int num;
				int isNum = parseint(val, &num);

				if (opt == 'n' && isNum) {
					max_nesting = num;
					break;
				}

				if (opt == 't' && isNum) {
					toc_level = num;
					break;
				}

				if (opt == 'i' && isNum) {
					iunit = num;
					break;
				}

				if (opt == 'o' && isNum) {
					ounit = num;
					break;
				}

				fprintf(stderr, "Wrong option '-%c' found.\n", opt);
				return 1;
			}
			continue;
		}

		if (!arg[2]) {
			/* arg is "--" */
			just_args = 1;
			continue;
		}

		/* parse long option */
		char opt [100];
		strncpy(opt, arg+2, 100);
		opt[99] = 0;

		char *val = strchr(opt, '=');

		long int num = 0;
		int isNum = 0;

		if (val) {
			*val = 0;
			val++;

			if (*val)
				isNum = parseint(val, &num);
		}

		int opt_parsed = 0;

		if (strcmp(opt, "help")==0) {
			print_help(argv[0]);
			return 1;
		}

		if (strcmp(opt, "version")==0) {
			print_version();
			return 1;
		}

		if (strcmp(opt, "max-nesting")==0 && isNum) {
			opt_parsed = 1;
			max_nesting = num;
		}
		if (strcmp(opt, "toc-level")==0 && isNum) {
			opt_parsed = 1;
			toc_level = num;
		}
		if (strcmp(opt, "input-unit")==0 && isNum) {
			opt_parsed = 1;
			iunit = num;
		}
		if (strcmp(opt, "output-unit")==0 && isNum) {
			opt_parsed = 1;
			ounit = num;
		}

		if (strcmp(opt, "html")==0) {
			opt_parsed = 1;
			renderer_type = RENDERER_HTML;
		}
		if (strcmp(opt, "html-toc")==0) {
			opt_parsed = 1;
			renderer_type = RENDERER_HTML_TOC;
		}
		if (strcmp(opt, "null")==0) {
			opt_parsed = 1;
			renderer_type = RENDERER_NULL;
		}

		const char *name;
		size_t i;

		/* extension categories */
		if ((name = strprefix(opt, category_prefix))) {
			for (i = 0; i < count_of(categories_info); i++) {
				struct extension_category_info *category = categories_info+i;
				if (strcmp(name, category->option_name)==0) {
					opt_parsed = 1;
					extensions |= category->flags;
					break;
				}
			}
		}

		/* extensions */
		for (i = 0; i < count_of(extensions_info); i++) {
			struct extension_info *extension = extensions_info+i;
			if (strcmp(opt, extension->option_name)==0) {
				opt_parsed = 1;
				extensions |= extension->flag;
				break;
			}
		}

		/* html flags */
		for (i = 0; i < count_of(html_flags_info); i++) {
			struct html_flag_info *html_flag = html_flags_info+i;
			if (strcmp(opt, html_flag->option_name)==0) {
				opt_parsed = 1;
				html_flags |= html_flag->flag;
				break;
			}
		}

		/* negations */
		if ((name = strprefix(opt, negative_prefix))) {
			for (i = 0; i < count_of(categories_info); i++) {
				struct extension_category_info *category = categories_info+i;
				if (strcmp(name, category->option_name)==0) {
					opt_parsed = 1;
					extensions &= ~(category->flags);
					break;
				}
			}
			for (i = 0; i < count_of(extensions_info); i++) {
				struct extension_info *extension = extensions_info+i;
				if (strcmp(name, extension->option_name)==0) {
					opt_parsed = 1;
					extensions &= ~(extension->flag);
					break;
				}
			}
			for (i = 0; i < count_of(html_flags_info); i++) {
				struct html_flag_info *html_flag = html_flags_info+i;
				if (strcmp(name, html_flag->option_name)==0) {
					opt_parsed = 1;
					html_flags &= ~(html_flag->flag);
					break;
				}
			}
		}

		if (strcmp(opt, "time")==0) {
			opt_parsed = 1;
			show_time = 1;
		}

		if (!opt_parsed) {
			fprintf(stderr, "Wrong option '%s' found.\n", arg);
			return 1;
		}
	}

	if (!in)
		in = stdin;


	/* reading everything */
	ib = hoedown_buffer_new(iunit);

	while (!feof(in)) {
		if (ferror(in)) {
			fprintf(stderr, "I/O errors found while reading input.\n");
			return 5;
		}
		hoedown_buffer_grow(ib, ib->size + iunit);
		ib->size += fread(ib->data + ib->size, 1, iunit, in);
	}

	if (in != stdin)
		fclose(in);


	/* creating the renderer */
	hoedown_renderer *renderer = NULL;
	void (*renderer_free)(hoedown_renderer*) = NULL;

	switch (renderer_type) {
		case RENDERER_HTML:
			renderer = hoedown_html_renderer_new(html_flags, toc_level);
			renderer_free = hoedown_html_renderer_free;
			break;
		case RENDERER_HTML_TOC:
			renderer = hoedown_html_toc_renderer_new(toc_level);
			renderer_free = hoedown_html_renderer_free;
			break;
		case RENDERER_NULL:
			renderer = null_renderer_new();
			renderer_free = null_renderer_free;
			break;
	};


	/* performing markdown rendering */
	ob = hoedown_buffer_new(ounit);
	document = hoedown_document_new(renderer, extensions, max_nesting);

	//clock_gettime(CLOCK_MONOTONIC, &start);
	hoedown_document_render(document, ob, ib->data, ib->size);
	//clock_gettime(CLOCK_MONOTONIC, &end);


	/* writing the result to stdout */
	(void)fwrite(ob->data, 1, ob->size, stdout);


	/* showing rendering time */
	if (show_time) {
		//TODO: enable this
		//long long elapsed = (  end.tv_sec*1000000000 +   end.tv_nsec)
		//                  - (start.tv_sec*1000000000 + start.tv_nsec);
		//if (elapsed < 1000000000)
		//	fprintf(stderr, "Time spent on rendering: %.2f ms.\n", ((double)elapsed)/1000000);
		//else
		//	fprintf(stderr, "Time spent on rendering: %.3f s.\n", ((double)elapsed)/1000000000);
	}


	/* cleanup */
	hoedown_buffer_free(ib);
	hoedown_buffer_free(ob);

	hoedown_document_free(document);
	renderer_free(renderer);

	if (ferror(stdout)) {
		fprintf(stderr, "I/O errors found while writing output.\n");
		return 5;
	}

	return 0;
}
QByteArray HoedownMarkdownConverterPrivate::markdown2Html(const QByteArray &markdownText) const {

    int markdownLength = markdownText.size();

    if(markdownLength == 0) {
        return QByteArray("");
    }

    hoedown_buffer *ib, *ob;
    hoedown_renderer *renderer = NULL;
    hoedown_document *document;

    // malloc
    ob = hoedown_buffer_new(markdownLength);
    ib = hoedown_buffer_new(markdownLength);
    renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 0);

/*
typedef enum hoedown_extensions {
    // block-level extensions
    HOEDOWN_EXT_TABLES = (1 << 0),
    HOEDOWN_EXT_FENCED_CODE = (1 << 1),
    HOEDOWN_EXT_FOOTNOTES = (1 << 2),

    // span-level extensions
    HOEDOWN_EXT_AUTOLINK = (1 << 3),
    HOEDOWN_EXT_STRIKETHROUGH = (1 << 4),
    HOEDOWN_EXT_UNDERLINE = (1 << 5),
    HOEDOWN_EXT_HIGHLIGHT = (1 << 6),
    HOEDOWN_EXT_QUOTE = (1 << 7),
    HOEDOWN_EXT_SUPERSCRIPT = (1 << 8),
    HOEDOWN_EXT_MATH = (1 << 9),

    // other flags
    HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11),
    HOEDOWN_EXT_SPACE_HEADERS = (1 << 12),
    HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13),

    // negative flags
    HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14)
} hoedown_extensions;
*/
    // 尽可能的指定
    document = hoedown_document_new(renderer, HOEDOWN_EXT_TABLES, 16);

    // put data
    hoedown_buffer_put(ib, (const uint8_t *) markdownText.toStdString().c_str(), markdownText.size());

    // render markdown to html
    hoedown_document_render(document, ob, ib->data, ib->size);

    QByteArray html((const char*)ob->data, ob->size);

    // free
    hoedown_buffer_free(ib);
    hoedown_document_free(document);
    hoedown_html_renderer_free(renderer);
    hoedown_buffer_free(ob);

    return html;
}
Exemple #8
0
/**
 * @brief Returns html rendered markdown of the note text
 * @param notesPath for transforming relative local urls to absolute ones
 * @param maxImageWidth defined maximum image width (ignored if forExport is true)
 * @param forExport defines whether the export or preview stylesheet
 * @return
 */
QString Note::toMarkdownHtml(QString notesPath, int maxImageWidth, bool forExport) {
    hoedown_renderer *renderer =
            hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16);
    hoedown_extensions extensions =
            (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN);
    hoedown_document *document = hoedown_document_new(renderer, extensions, 16);

    // get the decrypted note text (or the normal note text if there isn't any)
    QString str = getDecryptedNoteText();

    QString windowsSlash = "";

#ifdef Q_OS_WIN32
    // we need an other slash for Windows
    windowsSlash = "/";
#endif

    // parse for relative file urls and make them absolute
    // (for example to show images under the note path)
    str.replace(
            QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"),
            "(file://" + windowsSlash + notesPath + "/\\1)");

    unsigned char *sequence = (unsigned char *) qstrdup(
            str.toUtf8().constData());
    qint64 length = strlen((char *) sequence);

    // return an empty string if the note is empty
    if (length == 0) {
        return "";
    }

    hoedown_buffer *html = hoedown_buffer_new(length);

    // render markdown html
    hoedown_document_render(document, html, sequence, length);

    // get markdown html
    QString result = QString::fromUtf8((char *) html->data, html->size);

    /* Cleanup */
    free(sequence);
    hoedown_buffer_free(html);

    hoedown_document_free(document);
    hoedown_html_renderer_free(renderer);

    QSettings(settings);
    QString fontString = settings.value("MainWindow/noteTextView.code.font")
            .toString();

    // set the stylesheet for the <code> blocks
    QString codeStyleSheet = "";
    if (fontString != "") {
        // set the note text view font
        QFont font;
        font.fromString(fontString);

        // add the font for the code block
        codeStyleSheet = QString(
                "pre, code { %1; }").arg(encodeCssFont(font));
    }

    bool darkModeColors = settings.value("darkModeColors").toBool();

    QString codeBackgroundColor = darkModeColors ? "#444444" : "#f1f1f1";

    // do some more code formatting
    codeStyleSheet += QString(
            "pre, code { padding: 16px; overflow: auto;"
                    " line-height: 1.45em; background-color: %1;"
                    " border-radius: 3px; }").arg(codeBackgroundColor);

    // remove double code blocks
    result.replace("<pre><code>", "<pre>")
            .replace("</code></pre>", "</pre>");

    if (forExport) {
        // get defined body font from settings
        QString bodyfontString = settings.value("MainWindow/noteTextView.font")
                .toString();

        // create export stylesheet
        QString exportStyleSheet = "";
        if (bodyfontString != "") {
            QFont bodyFont;
            bodyFont.fromString(bodyfontString);

            exportStyleSheet = QString(
                    "body { %1; }").arg(encodeCssFont(bodyFont));
        }

        result = QString("<html><head><meta charset=\"utf-8\"/><style>"
                    "h1 { margin: 5px 0 20px 0; }"
                    "h2, h3 { margin: 10px 0 15px 0; }"
                    "img { max-width: 100%; }"
                    "a { color: #FF9137; text-decoration: none; } %1 %2"
                    "</style></head><body>%3</body></html>")
            .arg(codeStyleSheet, exportStyleSheet, result);
    } else {
        // for preview
        result = QString("<html><head><style>"
                    "h1 { margin: 5px 0 20px 0; }"
                    "h2, h3 { margin: 10px 0 15px 0; }"
                    "a { color: #FF9137; text-decoration: none; } %1"
                    "</style></head><body>%2</body></html>")
            .arg(codeStyleSheet, result);
    }

    // check if width of embedded local images is too high
    QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\"");
    QRegularExpressionMatchIterator i = re.globalMatch(result);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        QString fileName = match.captured(1);

#ifdef Q_OS_WIN
        // remove the leading slash under Windows to get a more correct filename
        QImage image(Utils::Misc::removeIfStartsWith(fileName, "/"));
#else
        QImage image(fileName);
#endif

        if (forExport) {
            result.replace(
                    QRegularExpression("<img src=\"file:\\/\\/" +
                                       QRegularExpression::escape(fileName) +
                                       "\""),
                    QString("<img src=\"file://%2\"").arg(fileName));
        } else {
            // for preview
            // cap the image width at 980px or the note text view width
            if (image.width() > maxImageWidth) {
                result.replace(
                        QRegularExpression("<img src=\"file:\\/\\/" +
                                           QRegularExpression::escape(fileName) +
                                           "\""),
                        QString("<img width=\"%1\" src=\"file://%2\"").arg(
                                QString::number(maxImageWidth), fileName));
            }
        }
    }

    // check if there is a script that wants to modify the content
    QString scriptResult = ScriptingService::instance()
            ->callNoteToMarkdownHtmlHook(this, result);

    if (!scriptResult.isEmpty()) {
        result = scriptResult;
    }

    return result;
}
Exemple #9
0
/**
 * @brief Returns html rendered markdown of the note text
 * @param notesPath for transforming relative local urls to absolute ones
 * @return
 */
QString Note::toMarkdownHtml(QString notesPath) {
    hoedown_renderer *renderer =
            hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16);
    hoedown_extensions extensions =
            (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN);
    hoedown_document *document = hoedown_document_new(renderer, extensions, 16);

    // get the decrypted note text (or the normal note text if there isn't any)
    QString str = getDecryptedNoteText();

    QString windowsSlash = "";

#ifdef Q_OS_WIN32
    // we need an other slash for Windows
    windowsSlash = "/";
#endif

    // parse for relative file urls and make them absolute
    // (for example to show images under the note path)
    str.replace(
            QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"),
            "(file://" + windowsSlash + notesPath + "/\\1)");

    unsigned char *sequence = (unsigned char *) qstrdup(
            str.toUtf8().constData());
    qint64 length = strlen((char *) sequence);

    // return an empty string if the note is empty
    if (length == 0) {
        return "";
    }

    hoedown_buffer *html = hoedown_buffer_new(length);

    // render markdown html
    hoedown_document_render(document, html, sequence, length);

    // get markdown html
    QString result = QString::fromUtf8((char *) html->data, html->size);

    /* Cleanup */
    free(sequence);
    hoedown_buffer_free(html);

    hoedown_document_free(document);
    hoedown_html_renderer_free(renderer);

    QSettings(settings);
    QString fontString = settings.value("MainWindow/noteTextView.code.font")
            .toString();

    // set the stylesheet for the <code> blocks
    QString codeStyleSheet = "";
    if (fontString != "") {
        // set the note text view font
        QFont font;
        font.fromString(fontString);

        codeStyleSheet = "pre, code {" + encodeCssFont(font) + "}";
    }

    result = "<html><head>"
                    "<style>h1, h2, h3 { margin: 5pt 0 10pt 0; }"
                    "a { color: #FF9137; text-decoration: none; }" +
            codeStyleSheet + "</style></head><body>" +
            result + "</body></html>";

    // check if width of embedded local images is too high
    QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\"");
    QRegularExpressionMatchIterator i = re.globalMatch(result);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        QString fileName = match.captured(1);
        QImage image(fileName);

        // cap the image width at 980px
        if (image.width() > 980) {
            result.replace(
                    QRegularExpression("<img src=\"file:\\/\\/" +
                                       QRegularExpression::escape(fileName) +
                                       "\""),
                    "<img width=\"980\" src=\"file://" + fileName + "\"");
        }
    }

    return result;
}
Exemple #10
0
/**
 * @brief Returns html rendered markdown of the note text
 * @param notesPath for transforming relative local urls to absolute ones
 * @return
 */
QString Note::toMarkdownHtml(QString notesPath) {
    hoedown_renderer *renderer =
            hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 16);
    hoedown_extensions extensions =
            (hoedown_extensions) (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN);
    hoedown_document *document = hoedown_document_new(renderer, extensions, 16);

    // get the decrypted note text (or the normal note text if there isn't any)
    QString str = getDecryptedNoteText();

    // parse for relative file urls and make them absolute
    // (for example to show images under the note path)
    str.replace(
            QRegularExpression("\\(file:\\/\\/([^\\/].+)\\)"),
            "(file://" + notesPath + "/\\1)");

    unsigned char *sequence = (unsigned char *) qstrdup(str.toUtf8().constData());
    int length = strlen((char *) sequence);

    // return an empty string if the note is empty
    if (length == 0) {
        return "";
    }

    hoedown_buffer *html = hoedown_buffer_new(length);

    // render markdown html
    hoedown_document_render(document, html, sequence, length);

    // get markdown html
    QString result = QString::fromUtf8((char *) html->data, html->size);

    /* Cleanup */
    free(sequence);
    hoedown_buffer_free(html);

    hoedown_document_free(document);
    hoedown_html_renderer_free(renderer);

    result =
            "<html><head><style>h1, h2, h3 { margin: 5pt 0 10pt 0; }"
            "a { color: #FF9137; text-decoration: none; }</style></head><body>" +
            result + "</body></html>";

    // check if width of embedded local images is too high
    QRegularExpression re("<img src=\"file:\\/\\/([^\"]+)\"");
    QRegularExpressionMatchIterator i = re.globalMatch(result);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        QString fileName = match.captured(1);
        QImage image(fileName);

        // cap the image width at 980px
        if (image.width() > 980) {
            result.replace(
                    QRegularExpression("<img src=\"file:\\/\\/" + QRegularExpression::escape(fileName) + "\""),
                           "<img width=\"980\" src=\"file://" + fileName + "\"");
        }
    }

    return result;
}
Exemple #11
0
int
main(int argc, char **argv)
{
    struct option_data data;
    clock_t t1, t2;
    FILE *file = stdin;
    hoedown_buffer *ib, *ob, *meta;
    hoedown_renderer *renderer = NULL;
    void (*renderer_free)(hoedown_renderer *) = NULL;
    hoedown_document *document;

    /* Parse options */
    data.basename = argv[0];
    data.done = 0;
    data.show_time = 0;
    data.iunit = DEF_IUNIT;
    data.ounit = DEF_OUNIT;
    data.filename = NULL;
    data.renderer = RENDERER_HTML;
    data.toc_level = 0;
    data.html_flags = 0;
    data.extensions = 0;
    data.max_nesting = DEF_MAX_NESTING;
    data.link_attributes = 0;

    argc = parse_options(argc, argv, parse_short_option, parse_long_option, parse_argument, &data);
    if (data.done) return 0;
    if (!argc) return 1;

    /* Add extesion flags, case html_flags */
    if (data.html_flags & HOEDOWN_HTML_FENCED_CODE_SCRIPT) {
        data.extensions |= HOEDOWN_EXT_FENCED_CODE;
    }

    /* Open input file, if needed */
    if (data.filename) {
        file = fopen(data.filename, "r");
        if (!file) {
            fprintf(stderr, "Unable to open input file \"%s\": %s\n", data.filename, strerror(errno));
            return 5;
        }
    }

    /* Read everything */
    ib = hoedown_buffer_new(data.iunit);

    if (hoedown_buffer_putf(ib, file)) {
        fprintf(stderr, "I/O errors found while reading input.\n");
        return 5;
    }

    if (file != stdin) fclose(file);

    /* Create the renderer */
    switch (data.renderer) {
    case RENDERER_HTML:
        renderer = hoedown_html_renderer_new(data.html_flags, data.toc_level);
        renderer_free = hoedown_html_renderer_free;
        break;
    case RENDERER_HTML_TOC:
        renderer = hoedown_html_toc_renderer_new(data.toc_level);
        renderer_free = hoedown_html_renderer_free;
        break;
    case RENDERER_CONTEXT_TEST:
        renderer = hoedown_context_test_renderer_new();
        renderer_free = hoedown_context_test_renderer_free;
        break;
    };

    /* Perform Markdown rendering */
    ob = hoedown_buffer_new(data.ounit);
    meta = hoedown_buffer_new(data.ounit);
    document = hoedown_document_new(renderer, data.extensions, data.max_nesting, NULL, meta);

    /* state */
    if (data.renderer == RENDERER_CONTEXT_TEST) {
        hoedown_context_test_renderer_state *state;
        state = (hoedown_context_test_renderer_state *)renderer->opaque;
        state->doc = document;
    } else {
        hoedown_html_renderer_state *state;
        state = (hoedown_html_renderer_state *)renderer->opaque;
        /* toc_data */
        if (data.toc_level > 0) {
            state->toc_data.current_level = 0;
            state->toc_data.level_offset = 0;
            state->toc_data.nesting_level = data.toc_level;
            state->toc_data.header = "<div class=\"toc\">";
            state->toc_data.footer = "</div>";
        }
        /* link_attributes */
        if (data.link_attributes) {
            state->link_attributes = rndr_test_link_attributes;
        }
    }

    t1 = clock();
    hoedown_document_render(document, ob, ib->data, ib->size);
    t2 = clock();

    /* Cleanup */
    hoedown_buffer_free(ib);
    hoedown_document_free(document);
    renderer_free(renderer);

    /* Write the result to stdout */
    (void)fwrite(ob->data, 1, ob->size, stdout);
    hoedown_buffer_free(ob);

    if (ferror(stdout)) {
        hoedown_buffer_free(meta);
        fprintf(stderr, "I/O errors found while writing output.\n");
        return 5;
    }

    /* Meta block */
    if (meta->size > 0) {
        fprintf(stdout, "-- Meta Block --\n");
        (void)fwrite(meta->data, 1, meta->size, stdout);
    }
    hoedown_buffer_free(meta);
    if (ferror(stdout)) {
        fprintf(stderr, "I/O errors found while writing output.\n");
        return 5;
    }

    /* Show rendering time */
    if (data.show_time) {
        double elapsed;

        if (t1 == ((clock_t) -1) || t2 == ((clock_t) -1)) {
            fprintf(stderr, "Failed to get the time.\n");
            return 1;
        }

        elapsed = (double)(t2 - t1) / CLOCKS_PER_SEC;
        if (elapsed < 1)
            fprintf(stderr, "Time spent on rendering: %7.2f ms.\n", elapsed*1e3);
        else
            fprintf(stderr, "Time spent on rendering: %6.3f s.\n", elapsed);
    }

    return 0;
}