Compare commits

...

3 Commits

7 changed files with 63 additions and 31 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/hoedown"]
path = src/hoedown
url = git@github.com:hoedown/hoedown.git

View File

@ -21,9 +21,21 @@ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/resources.c"
COMMENT "Generating resources" COMMENT "Generating resources"
) )
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/hoedown/libhoedown.a"
COMMAND make libhoedown.a
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/hoedown"
COMMENT "Compiling libhoedown"
)
ADD_LIBRARY(HOEDOWN STATIC IMPORTED)
SET_TARGET_PROPERTIES(HOEDOWN PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/src/hoedown/libhoedown.a"
)
aux_source_directory(./src SRC_LIST) aux_source_directory(./src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST}) add_executable(${PROJECT_NAME} ${SRC_LIST})
target_sources(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/resources.c") target_sources(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/resources.c")
target_link_libraries(${PROJECT_NAME} ${GTK3_LIBRARIES} ${WEBKIT_LIBRARIES}) target_sources(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src/hoedown/libhoedown.a")
target_link_libraries(${PROJECT_NAME} ${GTK3_LIBRARIES} ${WEBKIT_LIBRARIES} HOEDOWN)
install (TARGETS ${PROJECT_NAME} DESTINATION bin) install (TARGETS ${PROJECT_NAME} DESTINATION bin)

View File

@ -13,7 +13,7 @@ Renders everything as is. You will see the source code except for the header abo
The following constructs are supported: *italics*, **bold**, Headings 1 to 4. The following constructs are supported: *italics*, **bold**, Headings 1 to 4.
## Full HTML with Images ## Full HTML with Images
As the external md command is invoked and a web browser used to render the content, all markdown syntax supported by the md command is supported. Markdown is rendered using [Hoedown](https://github.com/hoedown/hoedown/) and displayed using an integrated web browser. This all Markdown syntax (including images) are supported.
# Encrypted Entries Using GPG # Encrypted Entries Using GPG
MDiary supports gpg encrypted entries. To use this feature, place a gpg encrypted entry as *<name>.md.gpg* in the workspace. MDiary will automatically show a decrypt button in the header bar which will invoke gpg to decrypt all encrypted entries in the workspace for this session. MDiary supports gpg encrypted entries. To use this feature, place a gpg encrypted entry as *<name>.md.gpg* in the workspace. MDiary will automatically show a decrypt button in the header bar which will invoke gpg to decrypt all encrypted entries in the workspace for this session.

1
src/hoedown Submodule

@ -0,0 +1 @@
Subproject commit 980b9c549b4348d50b683ecee6abee470b98acda

View File

@ -771,16 +771,18 @@ void mainWindow_calendarSelected(GtkWidget *widget, gpointer user_data)
static void mainWindow_set_text(struct mainWindow *mainWindow, gchar *text, gchar *file_url) static void mainWindow_set_text(struct mainWindow *mainWindow, gchar *text, gchar *file_url)
{ {
gchar *tempfile_path = "/tmp/mdiary.tmp.md";
gchar *cmd = NULL; gchar *cmd = NULL;
gchar *cmd_stdout = NULL; gchar *cmd_stdout = NULL;
gchar *cmd_stderr = NULL; gchar *cmd_stderr = NULL;
gint exit_status = 0;
gchar *base_url = NULL;
GFileOutputStream *stream = NULL; GFileOutputStream *stream = NULL;
GFile *file = NULL; GFile *file = NULL;
GtkTextIter iter; GtkTextIter iter;
GtkTextIter iter_end; GtkTextIter iter_end;
hoedown_buffer *ob;
hoedown_renderer *renderer = NULL;
void (*renderer_free)(hoedown_renderer *) = NULL;
hoedown_document *document;
gchar *base_url = NULL;
if (mainWindow->renderer == RENDERER_TEXT) { if (mainWindow->renderer == RENDERER_TEXT) {
gtk_text_buffer_set_text(mainWindow->textBuffer, text, strlen(text)); gtk_text_buffer_set_text(mainWindow->textBuffer, text, strlen(text));
@ -802,24 +804,21 @@ static void mainWindow_set_text(struct mainWindow *mainWindow, gchar *text, gcha
} else { } else {
if (text[0] != '\0') { if (text[0] != '\0') {
base_url = g_strdup_printf("file://%s", file_url); base_url = g_strdup_printf("file://%s", file_url);
file = g_file_new_for_path(tempfile_path); g_info("Rendering markdown as full HTML...");
stream = g_file_replace(
file, NULL, FALSE,
G_FILE_CREATE_NONE,
NULL, NULL);
g_output_stream_write(G_OUTPUT_STREAM(stream), text, strlen(text), NULL, NULL);
g_output_stream_flush(G_OUTPUT_STREAM(stream), NULL, NULL);
cmd = g_strdup_printf("markdown %s", tempfile_path); renderer = hoedown_html_renderer_new(0, 0);
if (g_spawn_command_line_sync(cmd, &cmd_stdout, &cmd_stderr, &exit_status, NULL) && renderer_free = hoedown_html_renderer_free;
exit_status == 0) {
webkit_web_view_load_html(WEBKIT_WEB_VIEW(mainWindow->webkitView), ob = hoedown_buffer_new(64);
cmd_stdout, base_url); document = hoedown_document_new(renderer, 0, 16);
} else { hoedown_document_render(document, ob, (const uint8_t *) text, strlen(text));
g_warning("Could not render markdown for file. Showing plain text instead.\n");
webkit_web_view_load_html(WEBKIT_WEB_VIEW(mainWindow->webkitView), webkit_web_view_load_html(WEBKIT_WEB_VIEW(mainWindow->webkitView),
text, base_url); hoedown_buffer_cstr(ob), base_url);
}
hoedown_buffer_free(ob);
hoedown_document_free(document);
renderer_free(renderer);
g_free(base_url); g_free(base_url);
} else { } else {
webkit_web_view_load_html(WEBKIT_WEB_VIEW(mainWindow->webkitView), webkit_web_view_load_html(WEBKIT_WEB_VIEW(mainWindow->webkitView),

View File

@ -8,6 +8,9 @@
#include "mdiary.h" #include "mdiary.h"
#include "md_pango.h" #include "md_pango.h"
#include "hoedown/src/document.h"
#include "hoedown/src/html.h"
#define FILE_LIST_MAX_LEN 5 #define FILE_LIST_MAX_LEN 5
enum { enum {

View File

@ -246,7 +246,7 @@ static gchar *mdiary_get_line_from_string(gchar **str_ptr)
* @param autoCompletion * @param autoCompletion
*/ */
static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner, static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
gchar *filename, gchar *content, gchar *filename, gchar *content, GList *autotags,
GtkListStore *entryListStore, GtkListStore *autoCompletion) GtkListStore *entryListStore, GtkListStore *autoCompletion)
{ {
GFile *file = NULL; GFile *file = NULL;
@ -263,6 +263,8 @@ static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
GString *text = NULL; GString *text = NULL;
guint header_state = 0; guint header_state = 0;
GList *l;
g_message("Add file: %s\n", filename); g_message("Add file: %s\n", filename);
mdiary_scanner->entries_failed++; /* Will be decremented again when entry was successfully added. */ mdiary_scanner->entries_failed++; /* Will be decremented again when entry was successfully added. */
@ -323,7 +325,7 @@ static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
} }
if (!tagList) { if (!tagList) {
g_warning("PARSER: Could not detect tags in file!\n"); g_warning("PARSER: Could not detect tags in file!\n");
tagList = g_list_append(tagList, "untagged"); tagList = g_list_append(tagList, g_strdup("untagged"));
} }
if (!text) { if (!text) {
g_warning("PARSER: Could not find any text in file!\n"); g_warning("PARSER: Could not find any text in file!\n");
@ -338,6 +340,11 @@ static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
title = g_strdup("Untitled"); title = g_strdup("Untitled");
} }
for (l = autotags; l != NULL; l = l->next)
{
tagList = g_list_append(tagList, g_strdup(l->data));
}
mdiary_scanner->entries_failed--; mdiary_scanner->entries_failed--;
mdiary_scanner->entries_added++; mdiary_scanner->entries_added++;
mdiary_add_entry_to_store(entryListStore, mdiary_add_entry_to_store(entryListStore,
@ -359,6 +366,8 @@ static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
g_input_stream_close(G_INPUT_STREAM(stream), NULL, NULL); g_input_stream_close(G_INPUT_STREAM(stream), NULL, NULL);
g_object_unref(file); g_object_unref(file);
} }
g_list_free_full(tagList, *g_free);
g_string_free(text, 0); g_string_free(text, 0);
g_free(summary); g_free(summary);
g_free(title); g_free(title);
@ -366,7 +375,7 @@ static void mdiary_add_file_to_store(struct mdiary_scanner *mdiary_scanner,
} }
static void mdiary_add_gpg_to_store(struct mdiary_scanner *mdiary_scanner, static void mdiary_add_gpg_to_store(struct mdiary_scanner *mdiary_scanner,
gchar *filename, gchar *filename, GList **add_tags,
GtkListStore *entryListStore, GtkListStore *autoCompletion) GtkListStore *entryListStore, GtkListStore *autoCompletion)
{ {
gchar *cmd = NULL; gchar *cmd = NULL;
@ -378,7 +387,7 @@ static void mdiary_add_gpg_to_store(struct mdiary_scanner *mdiary_scanner,
if (g_spawn_command_line_sync(cmd, &cmd_stdout, &cmd_stderr, &exit_status, NULL) && exit_status == 0) { if (g_spawn_command_line_sync(cmd, &cmd_stdout, &cmd_stderr, &exit_status, NULL) && exit_status == 0) {
g_message("GPG: Decryption OK!\n"); g_message("GPG: Decryption OK!\n");
mdiary_add_file_to_store(mdiary_scanner, filename, cmd_stdout, entryListStore, autoCompletion); mdiary_add_file_to_store(mdiary_scanner, filename, cmd_stdout, *add_tags, entryListStore, autoCompletion);
} else { } else {
mdiary_scanner->entries_failed++; mdiary_scanner->entries_failed++;
mdiary_scanner->error_code |= MDS_ERROR_GPG; mdiary_scanner->error_code |= MDS_ERROR_GPG;
@ -396,6 +405,7 @@ static void mdiary_add_gpg_to_store(struct mdiary_scanner *mdiary_scanner,
static void mdiary_recurse_and_collect(struct mdiary_scanner *mdiary_scanner, static void mdiary_recurse_and_collect(struct mdiary_scanner *mdiary_scanner,
gchar *base_dir, gchar *base_dir,
GList **autotags,
GtkListStore *entryListStore, GtkListStore *entryListStore,
GtkListStore *autoCompletion, GtkListStore *autoCompletion,
guint max_level) guint max_level)
@ -417,27 +427,28 @@ static void mdiary_recurse_and_collect(struct mdiary_scanner *mdiary_scanner,
if (g_regex_match(regex, fullPath, 0, &match_info) && if (g_regex_match(regex, fullPath, 0, &match_info) &&
g_match_info_matches(match_info)) g_match_info_matches(match_info))
mdiary_add_file_to_store(mdiary_scanner, mdiary_add_file_to_store(mdiary_scanner,
fullPath, NULL, fullPath, NULL, *autotags,
entryListStore, autoCompletion); entryListStore, autoCompletion);
g_regex_unref(regex); g_regex_unref(regex);
regex = g_regex_new("\\.md.gpg$", G_REGEX_CASELESS, 0, NULL); regex = g_regex_new("\\.md.gpg$", G_REGEX_CASELESS, 0, NULL);
if (g_regex_match(regex, fullPath, 0, &match_info) && if (g_regex_match(regex, fullPath, 0, &match_info) &&
g_match_info_matches(match_info)) { g_match_info_matches(match_info)) {
mdiary_scanner->entries_encrypted++; mdiary_scanner->entries_encrypted++;
if (mdiary_scanner->gpg_enabled) if (mdiary_scanner->gpg_enabled)
mdiary_add_gpg_to_store(mdiary_scanner, mdiary_add_gpg_to_store(mdiary_scanner,
fullPath, fullPath, autotags,
entryListStore, autoCompletion); entryListStore, autoCompletion);
} }
g_regex_unref(regex); g_regex_unref(regex);
} else if (g_file_test(fullPath, G_FILE_TEST_IS_DIR) && max_level) { } else if (g_file_test(fullPath, G_FILE_TEST_IS_DIR) && max_level) {
*autotags = g_list_append(*autotags, dirname);
mdiary_recurse_and_collect(mdiary_scanner, mdiary_recurse_and_collect(mdiary_scanner,
fullPath, fullPath, autotags,
entryListStore, autoCompletion, entryListStore, autoCompletion,
max_level--); max_level--);
*autotags = g_list_remove(*autotags, g_list_last(*autotags)->data);
} }
g_free(fullPath); g_free(fullPath);
} }
@ -478,8 +489,11 @@ gint mdiary_scan_to_store(struct mdiary_scanner *mdiary_scanner,
gchar *base_dir, gchar *base_dir,
GtkListStore *entryListStore, GtkListStore *autoCompletion) GtkListStore *entryListStore, GtkListStore *autoCompletion)
{ {
GList *autotags = NULL;
mdiary_recurse_and_collect(mdiary_scanner, base_dir, entryListStore, autoCompletion, 5); mdiary_recurse_and_collect(mdiary_scanner, base_dir, &autotags, entryListStore, autoCompletion, 5);
g_list_free(autotags);
return mdiary_scanner->entries_added; return mdiary_scanner->entries_added;
} }