From: Fletcher T. Penney Date: Sun, 2 Jul 2017 18:47:49 +0000 (-0400) Subject: ADDED: Use assets for reference image definitions in TextBundle format X-Git-Tag: 6.1.0^2~14^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c7655a64ae406ed3dd5dac32c0a239818ad06f8a;p=multimarkdown ADDED: Use assets for reference image definitions in TextBundle format --- diff --git a/Sources/libMultiMarkdown/d_string.c b/Sources/libMultiMarkdown/d_string.c index 470102d..86ab773 100644 --- a/Sources/libMultiMarkdown/d_string.c +++ b/Sources/libMultiMarkdown/d_string.c @@ -368,3 +368,37 @@ char * d_string_copy_substring(DString * d, size_t start, size_t len) { return result; } + + +/// Replace occurences of "original" with "replace" inside the specified range +/// Returns the change in overall length +long d_string_replace_text_in_range(DString * d, size_t pos, size_t len, const char * original, const char * replace) { + long delta = 0; // Overall change in length + + long len_o = strlen(original); + long len_r = strlen(replace); + long change = len_r - len_o; // Change in length for each replacement + + char * start = &(d->str[pos]); + char * stop; + + if (len == -1) { + stop = &(d->str[d->currentStringLength]); + } else { + stop = &(d->str[pos + len]); + } + + char * match = strstr(start, original); + + while (match && match < stop) { + d_string_erase(d, match - d->str, len_o); + d_string_insert(d, match - d->str, replace); + + delta += change; + stop += change; + match = strstr(match + len_r, original); + } + + return delta; +} + diff --git a/Sources/libMultiMarkdown/include/d_string.h b/Sources/libMultiMarkdown/include/d_string.h index 6ac2fbd..787fb81 100644 --- a/Sources/libMultiMarkdown/include/d_string.h +++ b/Sources/libMultiMarkdown/include/d_string.h @@ -169,5 +169,14 @@ char * d_string_copy_substring( size_t len //!< How many characters(bytes) to copy ); +/// Replace occurences of "original" with "replace" inside the specified range +/// Returns the change in overall length +long d_string_replace_text_in_range( + DString * d, + size_t pos, + size_t len, + const char * original, + const char * replace +); #endif diff --git a/Sources/libMultiMarkdown/textbundle.c b/Sources/libMultiMarkdown/textbundle.c index 43f0ab8..e24640b 100644 --- a/Sources/libMultiMarkdown/textbundle.c +++ b/Sources/libMultiMarkdown/textbundle.c @@ -201,7 +201,7 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc chunk.size = 0; char destination[100] = "assets/"; - destination[49] = '\0'; + destination[43] = '\0'; mz_bool status; @@ -243,13 +243,13 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc if (e->asset_hash){ char destination[100] = "assets/"; - destination[49] = '\0'; + destination[43] = '\0'; mz_bool status; HASH_ITER(hh, e->asset_hash, a, a_tmp) { - memcpy(&destination[13], a->asset_path, 36); + memcpy(&destination[7], a->asset_path, 36); // Attempt to add asset from local file if (!add_asset_from_file(pZip, a, destination, directory)) { @@ -261,6 +261,105 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc #endif +void traverse_for_images(token * t, DString * text, mmd_engine * e, long * offset, char * destination, char * url) { + asset * a; + char * clean; + link * l; + + while (t) { + switch(t->type) { + case PAIR_BRACKET_IMAGE: + if (t->next && t->next->type == PAIR_PAREN) { + t = t->next; + + memcpy(url, &text->str[t->start + *offset + 1], t->len - 2); + url[t->len - 2] = '\0'; + clean = clean_string(url, false); + + HASH_FIND_STR(e->asset_hash, clean, a); + + if (a) { + // Replace url with asset path + memcpy(&destination[7], a->asset_path, 36); + * offset += d_string_replace_text_in_range(text, t->start + *offset, t->len, clean, destination); + } + + free(clean); + } + break; + case BLOCK_EMPTY: + // Is this a link definition? + for (int i = 0; i < e->definition_stack->size; ++i) { + if (t == stack_peek_index(e->definition_stack, i)) { + // Find matching link + for (int j = 0; j < e->link_stack->size; ++j) { + l = stack_peek_index(e->link_stack, j); + if (l->label->start == t->child->start) { + // This is a match + HASH_FIND_STR(e->asset_hash, l->url, a); + + if (a) { + memcpy(&destination[7], a->asset_path, 36); + * offset += d_string_replace_text_in_range(text, t->start + *offset, t->len, l->url, destination); + } + } + } + } + } + break; + default: + if (t->child) { + traverse_for_images(t->child, text, e, offset, destination, url); + } + break; + } + + t = t->next; + } +} + + +void sub_asset_paths(DString * text, mmd_engine * e) { + long offset = 0; + asset * a, * a_tmp; + token * t = e->root->child; + + char destination[100] = "assets/"; + destination[43] = '\0'; + + // Is there CSS metadata? + if (e->metadata_stack) { + if (e->metadata_stack->size > 0) { + meta * m; + + for (int i = 0; i < e->metadata_stack->size; ++i) + { + m = stack_peek_index(e->metadata_stack, i); + if (strcmp("css", m->key) == 0) { + // Get METADATA range + t = e->root->child; + token_skip_until_type(&t, BLOCK_META); + + // Substitute inside metadata block + HASH_FIND_STR(e->asset_hash, m->value, a); + if (a) { + memcpy(&destination[7], a->asset_path, 36); + offset += d_string_replace_text_in_range(text, t->start, t->len, m->value, destination); + } + } + } + } + } + + + // Find images + char url[1000] = ""; + + // Travel parse tree for images and image reference definitions + traverse_for_images(t, text, e, &offset, &destination[0], &url[0]); +} + + // Use the miniz library to create a zip archive for the TEXTBUNDLE_COMPRESSED document void textbundle_write_wrapper(const char * filepath, const char * body, mmd_engine * e, const char * directory) { FILE * output_stream; @@ -307,8 +406,12 @@ DString * textbundle_create(const char * body, mmd_engine * e, const char * dire } // Add main document - len = e->dstr->currentStringLength; - status = mz_zip_writer_add_mem(&zip, "text.markdown", e->dstr->str, len, MZ_BEST_COMPRESSION); + DString * temp = d_string_new(e->dstr->str); + + sub_asset_paths(temp, e); + + len = temp->currentStringLength; + status = mz_zip_writer_add_mem(&zip, "text.markdown", temp->str, len, MZ_BEST_COMPRESSION); if (!status) { fprintf(stderr, "Error adding content to zip.\n"); } diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index f0e877d..db58f6e 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -2421,7 +2421,7 @@ void store_asset(scratch_pad * scratch, char * url) { if (!a) { // Asset not found - create new one a = asset_new(url, scratch); - HASH_ADD_KEYPTR(hh, scratch->asset_hash, url, strlen(url), a); + HASH_ADD_KEYPTR(hh, scratch->asset_hash, a->url, strlen(a->url), a); } }