]> granicus.if.org Git - multimarkdown/commitdiff
ADDED: Use assets for reference image definitions in TextBundle format
authorFletcher T. Penney <fletcher@fletcherpenney.net>
Sun, 2 Jul 2017 18:47:49 +0000 (14:47 -0400)
committerFletcher T. Penney <fletcher@fletcherpenney.net>
Sun, 2 Jul 2017 18:47:49 +0000 (14:47 -0400)
Sources/libMultiMarkdown/d_string.c
Sources/libMultiMarkdown/include/d_string.h
Sources/libMultiMarkdown/textbundle.c
Sources/libMultiMarkdown/writer.c

index 470102df8c9b1e98d04f08bf8a9b44ff29bc26dc..86ab7739acda4a8fcb903f67e11fa4f276f3cbbf 100644 (file)
@@ -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;
+}
+
index 6ac2fbdd1323a4b7f42662cd937d4b32914f2af3..787fb81d866ed83b1898f5d5b32b6e231e254cd1 100644 (file)
@@ -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
index 43f0ab80cbb54b39c9a2533f72e68edc4f2def28..e24640b1e9d0a97b27950e07b71f1c01c0a03623 100644 (file)
@@ -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");
        }
index f0e877d7d00bb8c260247c22c7ebbc9eda9f5278..db58f6e21da77ac8e820b50492fa9c3d05a528f8 100644 (file)
@@ -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);
        }
 }