To provide for weaving into HTML and into EPUB books.
void HTMLWeaving::create(void) { Create HTML1.1; Create ePub1.2; }
weave_format *wf = WeavingFormats::create_weave_format(I"HTML", I".html"); METHOD_ADD(wf, RENDER_FOR_MTID, HTMLWeaving::render);
- This code is used in §1.
weave_format *wf = WeavingFormats::create_weave_format(I"ePub", I".html"); METHOD_ADD(wf, RENDER_FOR_MTID, HTMLWeaving::render_EPUB); METHOD_ADD(wf, BEGIN_WEAVING_FOR_MTID, HTMLWeaving::begin_weaving_EPUB); METHOD_ADD(wf, END_WEAVING_FOR_MTID, HTMLWeaving::end_weaving_EPUB);
- This code is used in §1.
§2. Rendering. To keep track of what we're writing, we store the renderer state in an instance of this:
classdef HTML_render_state { struct text_stream *OUT; struct filename *into_file; struct weave_order *wv; struct colour_scheme *colours; int EPUB_flag; int popup_counter; int slide_number; int slide_of; int max_label_width; struct ls_paragraph *para_to_open; struct asset_rule *copy_rule; } HTML_render_state;
- The structure HTML_render_state is accessed in 5/ts, 5/apacs, 5/tc, 5/twot, 5/wt, 5/fm, 5/ptf, 5/tf, 5/df and here.
HTML_render_state HTMLWeaving::initial_state(text_stream *OUT, weave_order *wv, int EPUB_mode, filename *into) { HTML_render_state hrs; hrs.OUT = OUT; hrs.into_file = into; hrs.wv = wv; hrs.EPUB_flag = EPUB_mode; hrs.popup_counter = 1; hrs.slide_number = -1; hrs.slide_of = -1; hrs.para_to_open = NULL; hrs.copy_rule = Assets::simple_private_copy(); hrs.max_label_width = 0; Swarm::ensure_plugin(wv, I"Base"); hrs.colours = Swarm::ensure_colour_scheme(wv, I"Colours", I""); Swarm::begin_file(wv, into); return hrs; }
void HTMLWeaving::render(weave_format *self, text_stream *OUT, heterogeneous_tree *tree) { weave_document_node *C = RETRIEVE_POINTER_weave_document_node(tree->root->content); HTML::declare_as_HTML(OUT, FALSE); C->wv->current_insertion_points[BODY_WEAVEINSCRIPTION] = Str::len(OUT); HTML_render_state hrs = HTMLWeaving::initial_state(OUT, C->wv, FALSE, C->wv->weave_to); Trees::traverse_from(tree->root, &HTMLWeaving::render_visit, (void *) &hrs, 0); HTML::completed(OUT); if (C->footnotes_present) { text_stream *fn_plugin_name = Patterns::get_footnotes_plugin(C->wv->weave_web, C->wv->pattern); if (Str::len(fn_plugin_name) > 0) Swarm::ensure_plugin(C->wv, fn_plugin_name); } } void HTMLWeaving::render_EPUB(weave_format *self, text_stream *OUT, heterogeneous_tree *tree) { weave_document_node *C = RETRIEVE_POINTER_weave_document_node(tree->root->content); HTML::declare_as_HTML(OUT, TRUE); HTML_render_state hrs = HTMLWeaving::initial_state(OUT, C->wv, TRUE, C->wv->weave_to); Trees::traverse_from(tree->root, &HTMLWeaving::render_visit, (void *) &hrs, 0); Epub::note_page(WeavingDetails::get_as_ebook(C->wv->weave_web), C->wv->weave_to, C->wv->booklet_title, I""); HTML::completed(OUT); }
int HTMLWeaving::render_visit(tree_node *N, void *state, int L) { HTML_render_state *hrs = (HTML_render_state *) state; text_stream *OUT = hrs->OUT; if ((N->type == weave_document_node_type) || (N->type == weave_body_node_type) || (N->type == weave_chapter_header_node_type) || (N->type == weave_chapter_footer_node_type) || (N->type == weave_pagebreak_node_type) || (N->type == weave_chapter_node_type) || (N->type == weave_chapter_title_page_node_type) || (N->type == weave_grammar_index_node_type)) Render nothing5.45 else if (N->type == weave_head_node_type) Render head5.1 else if (N->type == weave_tail_node_type) Render tail5.4 else if (N->type == weave_verbatim_node_type) Render verbatim5.38 else if (N->type == weave_section_header_node_type) Render header5.2 else if (N->type == weave_section_footer_node_type) Render footer5.3 else if (N->type == weave_section_purpose_node_type) Render purpose5.5 else if (N->type == weave_subheading_node_type) Render subheading5.6 else if (N->type == weave_subsubheading_node_type) Render subsubheading5.7 else if (N->type == weave_bar_node_type) Render bar5.8 else if (N->type == weave_paragraph_heading_node_type) Render paragraph heading5.9 else if (N->type == weave_endnote_node_type) Render endnote5.10 else if (N->type == weave_figure_node_type) Render figure5.11 else if (N->type == weave_extract_node_type) Render extract5.12 else if (N->type == weave_audio_node_type) Render audio clip5.13 else if (N->type == weave_video_node_type) Render video clip5.14 else if (N->type == weave_download_node_type) Render download5.15 else if (N->type == weave_material_node_type) Render material5.16 else if (N->type == weave_embed_node_type) Render embed5.17 else if (N->type == weave_holon_usage_node_type) Render holon usage5.18 else if (N->type == weave_tangler_command_node_type) Render tangler command5.19 else if (N->type == weave_vskip_node_type) Render vskip5.20 else if (N->type == weave_section_node_type) Render section5.21 else if (N->type == weave_holon_declaration_node_type) Render holon declaration5.29 else if (N->type == weave_code_line_node_type) Render code line5.22 else if (N->type == weave_function_usage_node_type) Render function usage5.23 else if (N->type == weave_commentary_node_type) Render commentary5.24 else if (N->type == weave_carousel_slide_node_type) Render carousel slide5.25 else if (N->type == weave_toc_node_type) Render toc5.26 else if (N->type == weave_toc_line_node_type) Render toc line5.27 else if (N->type == weave_defn_node_type) Render defn5.28 else if (N->type == weave_source_code_node_type) Render source code5.30 else if (N->type == weave_comment_in_holon_node_type) Render comment in holon5.31 else if (N->type == weave_url_node_type) Render URL5.32 else if (N->type == weave_footnote_cue_node_type) Render footnote cue5.33 else if (N->type == weave_begin_footnote_text_node_type) Render footnote5.34 else if (N->type == weave_display_line_node_type) Render display line5.35 else if (N->type == weave_function_defn_node_type) Render function defn5.36 else if (N->type == weave_item_node_type) Render item5.37 else if (N->type == weave_inline_node_type) Render inline5.39 else if (N->type == weave_locale_node_type) Render locale5.40 else if (N->type == weave_maths_node_type) Render maths5.41 else if (N->type == weave_markdown_node_type) Render Markdown5.42 else if (N->type == weave_linebreak_node_type) Render linebreak5.43 else if (N->type == weave_index_marker_node_type) Render index5.44 else { WRITE_TO(STDERR, "errant node type: %S\n", N->type->node_type_name); internal_error("unable to render unknown node"); } return TRUE; }
weave_head_node *C = RETRIEVE_POINTER_weave_head_node(N->content); HTML::comment(OUT, C->banner);
- This code is used in §5.
if (hrs->EPUB_flag == FALSE) { weave_section_header_node *C = RETRIEVE_POINTER_weave_section_header_node(N->content); Render breadcrumb trail5.2.1; Render search box5.2.2; }
- This code is used in §5.
§5.2.1. Render breadcrumb trail5.2.1 =
Swarm::ensure_plugin(hrs->wv, I"Breadcrumbs"); HTML_OPEN_WITH("div", "class=\"breadcrumbs\""); HTML_OPEN_WITH("ul", "class=\"crumbs\""); Colonies::drop_initial_breadcrumbs(OUT, hrs->wv->weave_colony, hrs->wv->weave_to, hrs->wv->breadcrumbs); text_stream *bct = Bibliographic::get_datum(hrs->wv->weave_web, I"Title"); if (Str::len(Bibliographic::get_datum(hrs->wv->weave_web, I"Short Title")) > 0) bct = Bibliographic::get_datum(hrs->wv->weave_web, I"Short Title"); if (hrs->wv->self_contained == FALSE) { Colonies::write_breadcrumb(OUT, bct, hrs->wv->home_leaf); if (hrs->wv->weave_web->chaptered) { TEMPORARY_TEXT(chapter_link) WRITE_TO(chapter_link, "%S#%s%S", hrs->wv->home_leaf, (WeavingDetails::get_as_ebook(hrs->wv->weave_web))?"C":"", C->sect->owning_chapter->ch_range); Colonies::write_breadcrumb(OUT, C->sect->owning_chapter->ch_title, chapter_link); DISCARD_TEXT(chapter_link) } Colonies::write_breadcrumb(OUT, C->sect->sect_title, NULL); } else { Colonies::write_breadcrumb(OUT, bct, NULL); } HTML_CLOSE("ul"); HTML_CLOSE("div");
- This code is used in §5.2.
Render search box5.2.2 =
hrs->wv->current_insertion_points[SEARCH_BOX_WEAVEINSCRIPTION] = Str::len(OUT);
- This code is used in §5.2.
weave_section_footer_node *C = RETRIEVE_POINTER_weave_section_footer_node(N->content); int count = 0; ls_chapter *Ch; ls_section *next_S = NULL, *prev_S = NULL, *last = NULL; LOOP_OVER_LINKED_LIST(Ch, ls_chapter, hrs->wv->weave_web->chapters) { if (Ch->imported == FALSE) { ls_section *S; LOOP_OVER_LINKED_LIST(S, ls_section, Ch->sections) { count ++; if (S == C->sect) prev_S = last; if (last == C->sect) next_S = S; last = S; } } } if (count >= 2) { HTML_OPEN_WITH("nav", "role=\"progress\""); HTML_OPEN_WITH("div", "class=\"progresscontainer\""); HTML_OPEN_WITH("ul", "class=\"progressbar\""); Insert previous arrow5.3.1; ls_chapter *Ch; LOOP_OVER_LINKED_LIST(Ch, ls_chapter, hrs->wv->weave_web->chapters) { if (Ch->imported == FALSE) { if (Str::ne(Ch->ch_range, I"S")) { if (Ch == C->sect->owning_chapter) { HTML_OPEN_WITH("li", "class=\"progresscurrentchapter\""); HTMLWeaving::progress_popup(OUT, I"current-c-fullname-popup", Ch->ch_title); } else { HTML_OPEN_WITH("li", "class=\"progresschapter\""); HTMLWeaving::progress_popup(OUT, I"c-fullname-popup", Ch->ch_title); } ls_section *S = FIRST_IN_LINKED_LIST(ls_section, Ch->sections); if (S) { TEMPORARY_TEXT(TEMP) Colonies::section_URL(TEMP, S); if (Ch != C->sect->owning_chapter) { HTML::begin_link(OUT, TEMP); } WRITE("%S", Ch->ch_range); if (Ch != C->sect->owning_chapter) { HTML::end_link(OUT); } DISCARD_TEXT(TEMP) } } if (Ch == C->sect->owning_chapter) { ls_section *S; LOOP_OVER_LINKED_LIST(S, ls_section, Ch->sections) { TEMPORARY_TEXT(label) int on = FALSE; text_stream *range = WebRanges::of(S); LOOP_THROUGH_TEXT(pos, range) { if (Str::get(pos) == '/') on = TRUE; else if (on) PUT_TO(label, Str::get(pos)); } if (on == FALSE) Str::copy(label, range); if (Conventions::get_int(hrs->wv->weave_web, SECTIONS_NUMBERED_SEQUENTIALLY_LSCONVENTION)) Str::delete_first_character(label); if (S == C->sect) { HTML_OPEN_WITH("li", "class=\"progresscurrent\""); HTMLWeaving::progress_popup(OUT, I"current-fullname-popup", S->sect_title); WRITE("%S", label); HTML_CLOSE("li"); } else { HTML_OPEN_WITH("li", "class=\"progresssection\""); HTMLWeaving::progress_popup(OUT, I"fullname-popup", S->sect_title); TEMPORARY_TEXT(TEMP) Colonies::section_URL(TEMP, S); HTML::begin_link(OUT, TEMP); WRITE("%S", label); HTML::end_link(OUT); DISCARD_TEXT(TEMP) HTML_CLOSE("li"); } DISCARD_TEXT(label) } } } } Insert next arrow5.3.2; HTML_CLOSE("ul"); HTML_CLOSE("div"); HTML_CLOSE("nav"); }
- This code is used in §5.
§5.3.1. Insert previous arrow5.3.1 =
if (prev_S) { HTML_OPEN_WITH("li", "class=\"progressprev\""); HTMLWeaving::progress_popup(OUT, I"nav-popup", prev_S->sect_title); } else HTML_OPEN_WITH("li", "class=\"progressprevoff\""); TEMPORARY_TEXT(TEMP) if (prev_S) Colonies::section_URL(TEMP, prev_S); if (prev_S) HTML::begin_link(OUT, TEMP); WRITE("❮"); if (prev_S) HTML::end_link(OUT); DISCARD_TEXT(TEMP) HTML_CLOSE("li");
- This code is used in §5.3.
§5.3.2. Insert next arrow5.3.2 =
if (next_S) { HTML_OPEN_WITH("li", "class=\"progressnext\""); HTMLWeaving::progress_popup(OUT, I"nav-popup", next_S->sect_title); } else HTML_OPEN_WITH("li", "class=\"progressnextoff\""); TEMPORARY_TEXT(TEMP) if (next_S) Colonies::section_URL(TEMP, next_S); if (next_S) HTML::begin_link(OUT, TEMP); WRITE("❯"); if (next_S) HTML::end_link(OUT); DISCARD_TEXT(TEMP) HTML_CLOSE("li");
- This code is used in §5.3.
weave_tail_node *C = RETRIEVE_POINTER_weave_tail_node(N->content); HTML::comment(OUT, C->rennab);
- This code is used in §5.
weave_section_purpose_node *C = RETRIEVE_POINTER_weave_section_purpose_node(N->content); HTML_OPEN_WITH("p", "class=\"purpose\""); HTMLWeaving::escape_text(OUT, C->purpose); HTML_CLOSE("p"); WRITE("\n");
- This code is used in §5.
weave_subheading_node *C = RETRIEVE_POINTER_weave_subheading_node(N->content); HTML_OPEN("h3"); HTMLWeaving::escape_text(OUT, C->text); HTML_CLOSE("h3"); WRITE("\n");
- This code is used in §5.
§5.7. Render subsubheading5.7 =
weave_subsubheading_node *C = RETRIEVE_POINTER_weave_subsubheading_node(N->content); HTML_OPEN("h4"); HTMLWeaving::escape_text(OUT, C->text); HTML_CLOSE("h4"); WRITE("\n");
- This code is used in §5.
HTML::hr(OUT, NULL);
- This code is used in §5.
§5.9. Render paragraph heading5.9 =
weave_paragraph_heading_node *C = RETRIEVE_POINTER_weave_paragraph_heading_node(N->content); if (C->para == NULL) internal_error("no para"); if (N->child == NULL) { ls_paragraph *first_in_para = C->para; If no para number yet, render a p just to hold this5.9.1; }
- This code is used in §5.
HTML_OPEN("li"); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("li"); return FALSE;
- This code is used in §5.
weave_figure_node *C = RETRIEVE_POINTER_weave_figure_node(N->content); filename *F = Filenames::in( Pathnames::down(hrs->wv->weave_web->path_to_web, I"Figures"), C->figname); filename *RF = Filenames::from_text(C->figname); HTML_OPEN_WITH("p", "class=\"center-p\""); HTML::image_to_dimensions(OUT, RF, C->alt_text, C->w, C->h); Assets::include_asset(OUT, hrs->copy_rule, F, NULL, hrs->wv); HTML_CLOSE("p"); WRITE("\n");
- This code is used in §5.
weave_extract_node *C = RETRIEVE_POINTER_weave_extract_node(N->content); HTMLWeaving::render_HTML_extract(OUT, hrs->wv, C->extract);
- This code is used in §5.
§5.13. Render audio clip5.13 =
weave_audio_node *C = RETRIEVE_POINTER_weave_audio_node(N->content); HTMLWeaving::render_HTML_player(OUT, hrs->wv, C->audio_name, TRUE, 0, 0);
- This code is used in §5.
§5.14. Render video clip5.14 =
weave_video_node *C = RETRIEVE_POINTER_weave_video_node(N->content); HTMLWeaving::render_HTML_player(OUT, hrs->wv, C->video_name, FALSE, C->w, C->h);
- This code is used in §5.
weave_download_node *C = RETRIEVE_POINTER_weave_download_node(N->content); HTMLWeaving::render_download(OUT, hrs->wv, C->download_name, C->filetype);
- This code is used in §5.
weave_material_node *C = RETRIEVE_POINTER_weave_material_node(N->content); ls_paragraph *first_in_para = NULL; if ((N == N->parent->child) && (N->parent->type == weave_paragraph_heading_node_type)) { weave_paragraph_heading_node *PC = RETRIEVE_POINTER_weave_paragraph_heading_node(N->parent->content); first_in_para = PC->para; } if (C->material_type == COMMENTARY_MATERIAL) Deal with a commentary material node5.16.1 else if (C->material_type == CODE_MATERIAL) Deal with a code material node5.16.2 else if (C->material_type == FOOTNOTES_MATERIAL) Deal with a footnotes material node5.16.3 else if (C->material_type == ENDNOTES_MATERIAL) Deal with a endnotes material node5.16.4 else if (C->material_type == MACRO_MATERIAL) Deal with a macro material node5.16.5 else if (C->material_type == DEFINITION_MATERIAL) Deal with a definition material node5.16.6; return FALSE;
- This code is used in §5.
§5.9.1. If no para number yet, render a p just to hold this5.9.1 =
if (first_in_para) { HTMLWeaving::paragraph_number(OUT, first_in_para); HTML_CLOSE("p"); WRITE("\n"); first_in_para = NULL; }
§5.16.1. Deal with a commentary material node5.16.1 =
int item_depth = 0; for (tree_node *M = N->child; M; M = M->next) { if (M->type == weave_item_node_type) { If no para number yet, render a p just to hold this5.9.1; weave_item_node *C = RETRIEVE_POINTER_weave_item_node(M->content); HTMLWeaving::go_to_depth(hrs, item_depth, C->depth); item_depth = C->depth; Trees::traverse_from(M, &HTMLWeaving::render_visit, (void *) hrs, L+1); continue; } if (HTMLWeaving::interior_material(M)) Render a run of interior matter5.16.1.1; If no para number yet, render a p just to hold this5.9.1; if (item_depth > 0) { HTMLWeaving::go_to_depth(hrs, item_depth, 0); item_depth = 0; } if (M->type == weave_vskip_node_type) continue; Trees::traverse_from(M, &HTMLWeaving::render_visit, (void *) hrs, L+1); } if (item_depth > 0) { HTMLWeaving::go_to_depth(hrs, item_depth, 0); item_depth = 0; }
- This code is used in §5.16.
§5.16.1.1. Render a run of interior matter5.16.1.1 =
int closure_needed = TRUE; if (M->type != weave_markdown_node_type) { if (first_in_para) { HTMLWeaving::paragraph_number(OUT, first_in_para); first_in_para = NULL; } else { if (item_depth == 0) HTML_OPEN_WITH("p", "class=\"commentary\""); } } else { hrs->para_to_open = first_in_para; first_in_para = NULL; closure_needed = FALSE; } while (M) { Trees::traverse_from(M, &HTMLWeaving::render_visit, (void *) hrs, L+1); if (M->type != weave_markdown_node_type) closure_needed = TRUE; if ((M->next == NULL) || (HTMLWeaving::interior_material(M->next) == FALSE)) break; M = M->next; } if ((item_depth == 0) && (closure_needed)) { HTML_CLOSE("p"); WRITE("\n"); } continue;
- This code is used in §5.16.1.
§5.16.2. Deal with a code material node5.16.2 =
If no para number yet, render a p just to hold this5.9.1; if (C->styling) { TEMPORARY_TEXT(csname) WRITE_TO(csname, "%S-Colours", C->styling->language_name); hrs->colours = Swarm::ensure_colour_scheme(hrs->wv, csname, C->styling->language_name); DISCARD_TEXT(csname) } TEMPORARY_TEXT(cl) WRITE_TO(cl, "%S", hrs->colours->prefix); if (C->plainly) WRITE_TO(cl, "undisplayed-code"); else WRITE_TO(cl, "displayed-code"); WRITE("<pre class=\"%S all-displayed-code code-font\">\n", cl); DISCARD_TEXT(cl) hrs->max_label_width = 0; for (tree_node *M = N->child; M; M = M->next) if (M->type == weave_code_line_node_type) { weave_code_line_node *MC = RETRIEVE_POINTER_weave_code_line_node(M->content); if ((MC->line) && (LineLabels::label_width(MC->line) > hrs->max_label_width)) hrs->max_label_width = LineLabels::label_width(MC->line); } Recurse the renderer through children nodes5.10.1; hrs->max_label_width = 0; HTML_CLOSE("pre"); WRITE("\n"); if (Str::len(C->endnote) > 0) { HTML_OPEN_WITH("ul", "class=\"endnotetexts\""); HTML_OPEN("li"); HTMLWeaving::escape_text(OUT, C->endnote); HTML_CLOSE("li"); HTML_CLOSE("ul"); WRITE("\n"); }
- This code is used in §5.16.
§5.16.3. Deal with a footnotes material node5.16.3 =
If no para number yet, render a p just to hold this5.9.1; HTML_OPEN_WITH("ul", "class=\"footnotetexts\""); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("ul"); WRITE("\n");
- This code is used in §5.16.
§5.16.4. Deal with a endnotes material node5.16.4 =
If no para number yet, render a p just to hold this5.9.1; HTML_OPEN_WITH("ul", "class=\"endnotetexts\""); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("ul"); WRITE("\n");
- This code is used in §5.16.
§5.16.5. Deal with a macro material node5.16.5 =
if (first_in_para) { HTMLWeaving::paragraph_number(OUT, first_in_para); } else { HTML_OPEN_WITH("p", "class=\"commentary\""); } Recurse the renderer through children nodes5.10.1; HTML_CLOSE("p"); WRITE("\n");
- This code is used in §5.16.
§5.16.6. Deal with a definition material node5.16.6 =
If no para number yet, render a p just to hold this5.9.1; HTML_OPEN_WITH("pre", "class=\"definitions code-font\""); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("pre"); WRITE("\n");
- This code is used in §5.16.
§5.17. This has to embed some Internet-sourced content. service
here is something like YouTube or Soundcloud, and ID is whatever code
that service uses to identify the video/audio in question.
Render embed5.17 =
weave_embed_node *C = RETRIEVE_POINTER_weave_embed_node(N->content); HTMLWeaving::render_embedding(OUT, hrs->wv, C->ID, C->service, C->w, C->h);
- This code is used in §5.
§5.18. Render holon usage5.18 =
weave_holon_usage_node *C = RETRIEVE_POINTER_weave_holon_usage_node(N->content); HTML_OPEN_WITH("span", "class=\"named-paragraph-container code-font\""); TEMPORARY_TEXT(url) Colonies::paragraph_URL(url, C->holon->corresponding_chunk->owner, NULL, hrs->wv->weave_to, hrs->wv->weave_colony); HTML::begin_link_with_class(OUT, I"named-paragraph-link", url); DISCARD_TEXT(url) HTML_OPEN_WITH("span", "class=\"named-paragraph\""); ls_holon *holon = C->holon; if (holon) { if (holon->holon_name_as_markdown) { HTML_OPEN_WITH("span", "class=\"mathjax_process\""); MDRenderer::render_extended(OUT, (void *) hrs->wv, holon->holon_name_as_markdown, C->variation, 0); HTML_CLOSE("span"); } else HTMLWeaving::escape_text(OUT, holon->holon_name); } HTML_CLOSE("span"); HTML_OPEN_WITH("span", "class=\"named-paragraph-number\""); HTMLWeaving::escape_text(OUT, C->holon->corresponding_chunk->owner->paragraph_number); HTML_CLOSE("span"); HTML::end_link(OUT); HTML_CLOSE("span");
- This code is used in §5.
§5.19. Render tangler command5.19 =
weave_tangler_command_node *C = RETRIEVE_POINTER_weave_tangler_command_node(N->content); HTML_OPEN_WITH("span", "class=\"named-paragraph-container code-font\""); HTML_OPEN_WITH("span", "class=\"named-paragraph\""); HTMLWeaving::escape_text(OUT, I"output from tangler command '"); HTMLWeaving::escape_text(OUT, C->command); HTMLWeaving::escape_text(OUT, I"'"); HTML_CLOSE("span"); HTML_CLOSE("span");
- This code is used in §5.
WRITE("\n");
- This code is used in §5.
weave_section_node *C = RETRIEVE_POINTER_weave_section_node(N->content); LOG("It was %d\n", C->allocation_id);
- This code is used in §5.
weave_code_line_node *C = RETRIEVE_POINTER_weave_code_line_node(N->content); if (hrs->max_label_width > 0) { WRITE("<span class=\"labelmargin\">"); int n = 0; if (LineLabels::labelled(C->line)) { WRITE("<a id=\""); LineLabels::anchor(OUT, C->line); WRITE("\" class=\"labelanchor\"></a><span class=\"linelabel\"><a href=\"#"); LineLabels::anchor(OUT, C->line); WRITE("\">%S</a></span>", LineLabels::label_text(C->line)); n = LineLabels::label_width(C->line); } else { WRITE("<span class=\"nolinelabel\"> </span>"); n = 1; } WRITE("<span class=\"nolinelabel\">"); while (n++ < hrs->max_label_width+1) WRITE(" "); WRITE("</span>"); WRITE("</span>"); } ls_paragraph *par = LiterateSource::par_of_line(C->line); if (par) { WRITE("<a id=\""); Colonies::paragraph_anchor(OUT, par); WRITE("LN%d\" class=\"lineanchor\"></a>", C->line->sequence_number_in_paragraph); } Recurse the renderer through children nodes5.10.1; WRITE("</span>"); WRITE("\n"); return FALSE;
- This code is used in §5.
§5.23. Render function usage5.23 =
weave_function_usage_node *C = RETRIEVE_POINTER_weave_function_usage_node(N->content); HTML::begin_link_with_class(OUT, I"function-link", C->url); HTMLWeaving::change_colour(OUT, FUNCTION_COLOUR, hrs->colours); WRITE("%S", C->fn->function_name); HTMLWeaving::change_colour(OUT, -1, hrs->colours); HTML::end_link(OUT);
- This code is used in §5.
§5.24. Render commentary5.24 =
weave_commentary_node *C = RETRIEVE_POINTER_weave_commentary_node(N->content); if (C->in_code) HTMLWeaving::change_colour(OUT, COMMENT_COLOUR, hrs->colours); for (int i=0; i < Str::len(C->text); i++) { if (Str::get_at(C->text, i) == '&') WRITE("&"); else if (Str::get_at(C->text, i) == '<') WRITE("<"); else if (Str::get_at(C->text, i) == '>') WRITE(">"); else if ((i == 0) && (Str::get_at(C->text, i) == '-') && (Str::get_at(C->text, i+1) == '-') && ((Str::get_at(C->text, i+2) == ' ') || (Str::get_at(C->text, i+2) == 0))) { WRITE("—"); i++; } else if ((Str::get_at(C->text, i) == ' ') && (Str::get_at(C->text, i+1) == '-') && (Str::get_at(C->text, i+2) == '-') && ((Str::get_at(C->text, i+3) == ' ') || (Str::get_at(C->text, i+3) == '\n') || (Str::get_at(C->text, i+3) == 0))) { WRITE(" —"); i+=2; } else PUT(Str::get_at(C->text, i)); } if (C->in_code) HTMLWeaving::change_colour(OUT, -1, hrs->colours);
- This code is used in §5.
§5.25. Render carousel slide5.25 =
weave_carousel_slide_node *C = RETRIEVE_POINTER_weave_carousel_slide_node(N->content); if (hrs->slide_number == -1) { hrs->slide_number = 1; hrs->slide_of = 0; for (tree_node *X = N; (X) && (X->type == N->type); X = X->next) hrs->slide_of++; } else { hrs->slide_number++; if (hrs->slide_number > hrs->slide_of) internal_error("miscounted slides"); } TEMPORARY_TEXT(carousel_id) TEMPORARY_TEXT(carousel_dots_id) HTMLWeaving::render_carousel_top(OUT, hrs->wv, hrs->slide_number, hrs->slide_of, carousel_id, carousel_dots_id, C->caption, C->positioning); Recurse the renderer through children nodes5.10.1; HTMLWeaving::render_carousel_bottom(OUT, hrs->wv, hrs->slide_number, hrs->slide_of, carousel_id, carousel_dots_id, C->caption, C->positioning); DISCARD_TEXT(carousel_id) DISCARD_TEXT(carousel_dots_id) if (hrs->slide_number == hrs->slide_of) { hrs->slide_number = -1; hrs->slide_of = -1; } return FALSE;
- This code is used in §5.
HTML_OPEN_WITH("ul", "class=\"toc\""); for (tree_node *M = N->child; M; M = M->next) { HTML_OPEN("li"); Trees::traverse_from(M, &HTMLWeaving::render_visit, (void *) hrs, L+1); HTML_CLOSE("li"); } HTML_CLOSE("ul"); HTML::hr(OUT, "tocbar"); WRITE("\n"); return FALSE;
- This code is used in §5.
weave_toc_line_node *C = RETRIEVE_POINTER_weave_toc_line_node(N->content); TEMPORARY_TEXT(TEMP) Colonies::paragraph_URL(TEMP, C->para, NULL, hrs->wv->weave_to, hrs->wv->weave_colony); HTML::begin_link(OUT, TEMP); DISCARD_TEXT(TEMP) int depth = LiterateSource::par_depth(C->para); if (depth == -1) HTML_OPEN("b"); if (depth > 0) HTML_OPEN("i"); WRITE("%s%S", (Str::get_first_char(LiterateSource::par_ornament(C->para)) == 'S')?"§":"¶", C->para->paragraph_number); WRITE(". "); HTMLWeaving::escape_text(OUT, C->text2); if (depth > 0) HTML_CLOSE("i"); if (depth == -1) HTML_CLOSE("b"); HTML::end_link(OUT);
- This code is used in §5.
weave_defn_node *C = RETRIEVE_POINTER_weave_defn_node(N->content); HTML_OPEN_WITH("span", "class=\"definition-keyword\""); WRITE("%S", C->keyword); HTML_CLOSE("span"); WRITE(" "); if (Str::len(C->symbol) > 0) { HTML_OPEN_WITH("span", "class=\"identifier-syntax\""); WRITE("%S", C->symbol); HTML_CLOSE("span"); WRITE(" "); }
- This code is used in §5.
§5.29. Render holon declaration5.29 =
weave_holon_declaration_node *C = RETRIEVE_POINTER_weave_holon_declaration_node(N->content); HTML_OPEN_WITH("span", "class=\"named-paragraph-container code-font\""); ls_holon *label_holon = C->holon; if (C->holon->addendum_to) { label_holon = C->holon->addendum_to; TEMPORARY_TEXT(url) Colonies::paragraph_URL(url, label_holon->corresponding_chunk->owner, NULL, hrs->wv->weave_to, hrs->wv->weave_colony); HTML::begin_link_with_class(OUT, I"named-paragraph-link", url); DISCARD_TEXT(url) } HTML_OPEN_WITH("span", "class=\"named-paragraph-defn\""); if (label_holon->file_form) { PUT(0x2192); PUT(0x0020); } if (label_holon->holon_name_as_markdown) MDRenderer::render_extended(OUT, (void *) hrs->wv, label_holon->holon_name_as_markdown, C->variation, 0); else HTMLWeaving::escape_text(OUT, label_holon->holon_name); HTML_CLOSE("span"); HTML_OPEN_WITH("span", "class=\"named-paragraph-number\""); HTMLWeaving::escape_text(OUT, label_holon->corresponding_chunk->owner->paragraph_number); HTML_CLOSE("span"); if (C->holon->addendum_to) HTML::end_link(OUT); HTML_CLOSE("span"); if (C->holon->addendum_to) HTMLWeaving::escape_text(OUT, I" +="); else HTMLWeaving::escape_text(OUT, I" =");
- This code is used in §5.
§5.30. Render source code5.30 =
weave_source_code_node *C = RETRIEVE_POINTER_weave_source_code_node(N->content); HTMLWeaving::render_syntax_coloured(OUT, C->matter, C->colouring, hrs->colours);
- This code is used in §5.
§5.31. Render comment in holon5.31 =
weave_comment_in_holon_node *C = RETRIEVE_POINTER_weave_comment_in_holon_node(N->content); if (C->as_markdown) { HTML_OPEN_WITH("span", "class=\"comment-syntax\""); HTMLWeaving::escape_text(OUT, C->comment_open); for (int i=0; ((i<Str::len(C->raw)) && (Characters::is_whitespace(Str::get_at(C->raw, i)))); i++) PUT(Str::get_at(C->raw, i)); MDRenderer::render_extended(OUT, (void *) hrs->wv, C->as_markdown, C->variation, 0); for (int i=Str::len(C->raw) - 1; ((i>=0) && (Characters::is_whitespace(Str::get_at(C->raw, i)))); i--) PUT(Str::get_at(C->raw, i)); HTMLWeaving::escape_text(OUT, C->comment_close); HTML_CLOSE("span"); } else WRITE("NO-MARKDOWN-AVAILABLE");
- This code is used in §5.
weave_url_node *C = RETRIEVE_POINTER_weave_url_node(N->content); HTML::begin_link_with_class(OUT, (C->external)?I"external":I"internal", C->url); WRITE("%S", C->content); HTML::end_link(OUT);
- This code is used in §5.
§5.33. Render footnote cue5.33 =
weave_footnote_cue_node *C = RETRIEVE_POINTER_weave_footnote_cue_node(N->content); if (hrs->EPUB_flag) { if (N->parent->type != weave_begin_footnote_text_node_type) WRITE("<a id=\"fnref%S\"></a>", C->cue_text); WRITE("<sup><a href=\"#fn%S\" rel=\"footnote\">%S</a></sup>", C->cue_text, C->cue_text); } else WRITE("<sup id=\"fnref:%S\"><a href=\"#fn:%S\" rel=\"footnote\">%S</a></sup>", C->cue_text, C->cue_text, C->cue_text);
- This code is used in §5.
weave_begin_footnote_text_node *C = RETRIEVE_POINTER_weave_begin_footnote_text_node(N->content); if (hrs->EPUB_flag) WRITE("<li class=\"footnote\" id=\"fn%S\"><p class=\"inwebfootnote\">", C->cue_text); else WRITE("<li class=\"footnote\" id=\"fn:%S\"><p class=\"inwebfootnote\">", C->cue_text); Recurse the renderer through children nodes5.10.1; if (hrs->EPUB_flag) WRITE("<a href=\"#fnref%S\"> (return to text)</a></p></li>", C->cue_text); else WRITE("<a href=\"#fnref:%S\" title=\"return to text\"> ↩</a></p></li>", C->cue_text); return FALSE;
- This code is used in §5.
§5.35. Render display line5.35 =
weave_display_line_node *C = RETRIEVE_POINTER_weave_display_line_node(N->content); HTML_OPEN("blockquote"); WRITE("\n"); INDENT; HTML_OPEN("p"); HTMLWeaving::escape_text(OUT, C->text); HTML_CLOSE("p"); OUTDENT; HTML_CLOSE("blockquote"); WRITE("\n");
- This code is used in §5.
§5.36. At one time the Unicode characters 0x2190 (a left arrow), 0x2199 (arrow
pointing in and down), 0x2196 (ditto but up) were used instead of the SVG
images now encoded in the CSS for the buttons.
Render function defn5.36 =
weave_function_defn_node *C = RETRIEVE_POINTER_weave_function_defn_node(N->content); int tot = C->local_usages + C->section_usages + C->external_usages; if ((tot > 0) && (hrs->EPUB_flag == FALSE)) { int use_popup = FALSE; if ((tot > 1) || (C->external_usages == 1)) use_popup = TRUE; Swarm::ensure_plugin(hrs->wv, I"Popups"); HTMLWeaving::change_colour(OUT, FUNCTION_COLOUR, hrs->colours); WRITE("%S", C->fn->function_name); HTMLWeaving::change_colour(OUT, -1, hrs->colours); if (use_popup) { WRITE("<button class=\"popup arrow-short-button\" onclick=\"togglePopup('usagePopup%d')\">", hrs->popup_counter); } else { WRITE("<a href=\""); Colonies::paragraph_URL(OUT, C->hteu->usage_recorded_at, C->hteu->finer_positioning, hrs->wv->weave_to, hrs->wv->weave_colony); WRITE("\">"); if (C->local_direction == -1) WRITE("<button class=\"popup arrow-from-above-button\">"); else WRITE("<button class=\"popup arrow-from-below-button\">"); WRITE(" "); } HTMLWeaving::change_colour(OUT, COMMENT_COLOUR, hrs->colours); if (use_popup) WRITE("%d", tot); // WRITE("(%d, %d, %d, %d)", C->local_usages, C->local_direction, C->section_usages, C->external_usages); HTMLWeaving::change_colour(OUT, -1, hrs->colours); if (use_popup) { WRITE("<span class=\"popuptext\" id=\"usagePopup%d\">", hrs->popup_counter); WRITE("Usage of "); HTML_OPEN_WITH("span", "class=\"code-font\""); HTMLWeaving::change_colour(OUT, FUNCTION_COLOUR, hrs->colours); WRITE("%S", C->fn->function_name); HTMLWeaving::change_colour(OUT, -1, hrs->colours); HTML_CLOSE("span"); WRITE(":<br/>"); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("span"); } WRITE("</button>"); if (use_popup == FALSE) WRITE("</a>"); hrs->popup_counter++; } else { HTMLWeaving::change_colour(OUT, FUNCTION_COLOUR, hrs->colours); WRITE("%S", C->fn->function_name); HTMLWeaving::change_colour(OUT, -1, hrs->colours); } return FALSE;
- This code is used in §5.
weave_item_node *C = RETRIEVE_POINTER_weave_item_node(N->content); if (Str::eq(C->label, I"*")) WRITE("● "); else if (Str::len(C->label) > 0) WRITE("(%S) ", C->label); else WRITE(" ");
- This code is used in §5.
weave_verbatim_node *C = RETRIEVE_POINTER_weave_verbatim_node(N->content); WRITE("%S", C->content);
- This code is used in §5.
HTML_OPEN_WITH("span", "class=\"extract\""); Recurse the renderer through children nodes5.10.1; HTML_CLOSE("span"); return FALSE;
- This code is used in §5.
weave_locale_node *C = RETRIEVE_POINTER_weave_locale_node(N->content); TEMPORARY_TEXT(TEMP) Colonies::paragraph_URL(TEMP, C->par1, C->finer, hrs->wv->weave_to, hrs->wv->weave_colony); HTML::begin_link(OUT, TEMP); DISCARD_TEXT(TEMP) if (C->distant) { if (C->par1->owning_unit->owning_section) WRITE("%S:", C->par1->owning_unit->owning_section->sect_range); else WRITE("external:"); } if (LineLabels::labelled(C->finer)) HTML_OPEN_WITH("span", "class=\"linelabel\""); WRITE("%s%S", (Str::get_first_char(LiterateSource::par_ornament(C->par1)) == 'S')?"§":"¶", C->par1->paragraph_number); if (C->par2) WRITE("-%S", C->par2->paragraph_number); if (LineLabels::labelled(C->finer)) WRITE(" %S", LineLabels::label_text(C->finer)); if (LineLabels::labelled(C->finer)) HTML_CLOSE("span"); HTML::end_link(OUT);
- This code is used in §5.
weave_maths_node *C = RETRIEVE_POINTER_weave_maths_node(N->content); HTMLWeaving::render_maths(OUT, hrs->wv, C->content, hrs->EPUB_flag, C->displayed);
- This code is used in §5.
ls_paragraph *first_in_para = NULL; if ((N == N->parent->child) && (N->parent->type == weave_paragraph_heading_node_type)) { weave_paragraph_heading_node *PC = RETRIEVE_POINTER_weave_paragraph_heading_node(N->parent->content); first_in_para = PC->para; } HTML_OPEN_WITH("div", "class=\"lsmarkdown\""); OUTDENT; int mode = 0; weave_markdown_node *C = RETRIEVE_POINTER_weave_markdown_node(N->content); if ((first_in_para) || (hrs->para_to_open)) { if (hrs->para_to_open) HTMLWeaving::paragraph_number(OUT, hrs->para_to_open); else HTMLWeaving::paragraph_number(OUT, first_in_para); hrs->para_to_open = NULL; if ((C->content) && (C->content->down) && (C->content->down->type == PARAGRAPH_MIT)) { mode = EXISTING_PAR_MDRMODE; WRITE(" "); } else { HTML_CLOSE("p"); } } hrs->wv->current_weave_line = C->nearby_line; MDRenderer::render_extended(OUT, (void *) hrs->wv, C->content, C->variation, mode); INDENT; HTML_CLOSE("div");
- This code is used in §5.
WRITE("<br/>");
- This code is used in §5.
HTML_OPEN_WITH("div", "class=\"lsindex\""); if ((hrs->wv) && (hrs->wv->weave_web)) { ls_index *index = hrs->wv->weave_web->index; if (index->lemmas_sorted == NULL) WebIndexing::sort(index, I"0"); if (index->lemmas_sorted) for (int i=0; i<(int) (index->no_lemmas_sorted); i++) { ls_index_lemma *lemma = index->lemmas_sorted[i]; int d = 0; for (ls_index_lemma *l2 = lemma->parent; l2; l2 = l2->parent) d++; text_stream *pclass = I"lsindexlemma"; if (d == 1) pclass = I"lsindexsublemma"; if (d == 2) pclass = I"lsindexsubsublemma"; if (d >= 3) pclass = I"lsindexsubsubsublemma"; HTML_OPEN_WITH("p", "class=\"%S\"", pclass); switch (lemma->style) { case 1: HTML_OPEN_WITH("span", "class=\"lsindextext\""); break; case 2: HTML_OPEN_WITH("span", "class=\"lsindextexttt\""); break; case 3: HTML_OPEN_WITH("span", "class=\"lsindextextns\""); break; } HTMLWeaving::escape_text(OUT, lemma->text); HTML_CLOSE("span"); ls_index_mark *mark; int c = 0; LOOP_OVER_LINKED_LIST(mark, ls_index_mark, lemma->marks) { if (c++ > 0) WRITE(", "); else WRITE(" "); if (mark->important) HTML_OPEN("b"); HTMLWeaving::escape_text(OUT, mark->at->paragraph_number); if (mark->important) HTML_CLOSE("b"); } HTML_CLOSE("p"); } } HTML_CLOSE("div");
- This code is used in §5.
;
- This code is used in §5.
§5.10.1. Recurse the renderer through children nodes5.10.1 =
for (tree_node *M = N->child; M; M = M->next) Trees::traverse_from(M, &HTMLWeaving::render_visit, (void *) hrs, L+1);
- This code is used in §5.10, §5.16.2, §5.16.3, §5.16.4, §5.16.5, §5.16.6, §5.22, §5.25, §5.34, §5.36 and §5.39.
void HTMLWeaving::notify_image(weave_order *wv, text_stream *image) { if (Str::includes_character(image, '/')) return; if (Str::includes_character(image, '\\')) return; filename *F = Filenames::in( Pathnames::down(wv->weave_web->path_to_web, I"Figures"), image); asset_rule *R = Assets::simple_private_copy(); Assets::include_asset(NULL, R, F, NULL, wv); }
void HTMLWeaving::render_maths(OUTPUT_STREAM, weave_order *wv, text_stream *content, int plain, int displayed) { text_stream *plugin_name = (wv)?(Patterns::get_mathematics_plugin(wv->weave_web, wv->pattern)):NULL; if ((Str::len(plugin_name) == 0) || (plain)) { TEMPORARY_TEXT(R) TeXUtilities::remove_math_mode(R, content); HTMLWeaving::escape_text(OUT, R); DISCARD_TEXT(R) } else { Swarm::ensure_plugin(wv, plugin_name); if (displayed) WRITE("$$"); else WRITE("\\INWEBMATH("); TEMPORARY_TEXT(escaped) HTMLWeaving::escape_text(escaped, content); for (int i=0; i<Str::len(escaped); i++) { if (Str::get_at(escaped, i) == '|') { int found = FALSE; for (int j=i+1; j<Str::len(escaped); j++) { if (Str::get_at(escaped, j) == '|') { WRITE("\\hbox{\\tt "); for (int k=i+1; k<j; k++) PUT(Str::get_at(escaped, k)); WRITE("}"); i = j; found = TRUE; break; } } if (found == FALSE) PUT(Str::get_at(escaped, i)); } else { PUT(Str::get_at(escaped, i)); } } DISCARD_TEXT(escaped) if (displayed) WRITE("$$"); else WRITE("\\INWEBMATH)"); } }
§8. These are the nodes falling under a commentary material node which we will amalgamate into a single HTML paragraph:
int HTMLWeaving::interior_material(tree_node *N) { if (N->type == weave_commentary_node_type) return TRUE; if (N->type == weave_markdown_node_type) return TRUE; if (N->type == weave_url_node_type) return TRUE; if (N->type == weave_inline_node_type) return TRUE; if (N->type == weave_locale_node_type) return TRUE; if (N->type == weave_maths_node_type) return TRUE; if (N->type == weave_footnote_cue_node_type) return TRUE; return FALSE; }
§9. Depth 1 means "inside a list entry"; depth 2, "inside an entry of a list which is itself inside a list entry"; and so on.
void HTMLWeaving::go_to_depth(HTML_render_state *hrs, int from_depth, int to_depth) { text_stream *OUT = hrs->OUT; if (from_depth == to_depth) { HTML_CLOSE("li"); } else { while (from_depth < to_depth) { HTML_OPEN_WITH("ul", "class=\"items\""); from_depth++; } while (from_depth > to_depth) { HTML_CLOSE("li"); HTML_CLOSE("ul"); WRITE("\n"); from_depth--; } } if (to_depth > 0) HTML_OPEN("li"); }
void HTMLWeaving::paragraph_number(text_stream *OUT, ls_paragraph *par) { text_stream *title = LiterateSource::par_title(par); int depth = LiterateSource::par_depth(par); if (depth == -1) { HTML_OPEN("h2"); HTMLWeaving::escape_text(OUT, title); HTML_CLOSE("h2"); } HTML_OPEN_WITH("p", "class=\"commentary firstcommentary\""); TEMPORARY_TEXT(TEMP) Colonies::paragraph_anchor(TEMP, par); HTML::anchor_with_class(OUT, TEMP, I"paragraph-anchor"); DISCARD_TEXT(TEMP) if (LiterateSource::par_has_visible_number(par)) { HTML_OPEN("b"); WRITE("%s%S", (Str::get_first_char(LiterateSource::par_ornament(par)) == 'S')?"§":"¶", par->paragraph_number); WRITE(". "); HTMLWeaving::escape_text(OUT, title); inchar32_t c = LiterateSource::par_title_punctuation(par); if (c != 0) WRITE("%c", c); HTML_CLOSE("b"); WRITE(" "); } }
void HTMLWeaving::change_colour(text_stream *OUT, int col, colour_scheme *cs) { if (col == -1) { HTML_CLOSE("span"); } else { text_stream *cl = Painter::colour_classname(NULL, (inchar32_t) col); if (Str::len(cl) == 0) { PRINT("col: %d\n", col); internal_error("bad colour"); } else { HTML_OPEN_WITH("span", "class=\"%S%S\"", cs->prefix, cl); } } }
void HTMLWeaving::escape_text(text_stream *OUT, text_stream *id) { for (int i=0; i < Str::len(id); i++) { if (Str::get_at(id, i) == '&') WRITE("&"); else if (Str::get_at(id, i) == '<') WRITE("<"); else if (Str::get_at(id, i) == '>') WRITE(">"); else PUT(Str::get_at(id, i)); } }
void HTMLWeaving::render_code_block(OUTPUT_STREAM, int mode, weave_order *wv, text_stream *code, text_stream *language_rendered) { TEMPORARY_TEXT(name) WRITE_TO(name, "%S-Colours", language_rendered); colour_scheme *colours = Assets::find_colour_scheme(wv->weave_web, wv->pattern, name, language_rendered); text_stream *prefix = language_rendered; if (colours) Swarm::ensure_colour_scheme(wv, name, language_rendered); if (colours == NULL) { colours = Assets::find_colour_scheme(wv->weave_web, wv->pattern, I"Colours", I""); prefix = NULL; } if (colours == NULL) internal_error("no colour scheme available"); DISCARD_TEXT(name) if (Str::len(prefix) > 0) { if (mode & TAGS_MDRMODE) HTML_OPEN_WITH("pre", "class=\"%S-displayed-code all-displayed-code code-font\"", prefix); } else { if (mode & TAGS_MDRMODE) HTML_OPEN_WITH("pre", "class=\"displayed-code all-displayed-code code-font\""); } TEMPORARY_TEXT(colouring) programming_language *pl = wv->weave_web->web_language; if (Str::len(language_rendered) > 0) pl = Languages::find(wv->weave_web, language_rendered); if (pl == NULL) { WRITE_TO(STDERR, "warning: no language definition for '%S'\n", language_rendered); if (Str::eq_insensitive(language_rendered, I"plain")) WRITE_TO(STDERR, "(note that 'plain' is not normally a language: use 'none' instead)\n"); pl = Languages::find(wv->weave_web, I"None"); } // WRITE("(%S) ", pl->language_name); Painter::reset_syntax_colouring(pl); TEMPORARY_TEXT(line) TEMPORARY_TEXT(cols) int i = 0; while (i < Str::len(code)) { inchar32_t c = Str::get_at(code, i); if ((c == '\n') || (i+1 == Str::len(code))) { if (c != '\n') PUT_TO(line, c); Painter::syntax_colour(pl, &(pl->built_in_keywords), line, cols, FALSE, TRUE); Str::clear(line); WRITE_TO(colouring, "%S%c", cols, PLAIN_COLOUR); Str::clear(cols); } else { PUT_TO(line, c); } i++; } DISCARD_TEXT(line) DISCARD_TEXT(cols) HTMLWeaving::render_syntax_coloured(OUT, code, colouring, colours); DISCARD_TEXT(colouring) if (mode & TAGS_MDRMODE) HTML_CLOSE("pre"); WRITE("\n"); } void HTMLWeaving::render_syntax_coloured(OUTPUT_STREAM, text_stream *code, text_stream *colouring, colour_scheme *colours) { int current_colour = -1, colour_wanted = PLAIN_COLOUR; for (int i=0; i < Str::len(code); i++) { colour_wanted = (int) Str::get_at(colouring, i); if (colour_wanted != current_colour) { if (current_colour >= 0) HTML_CLOSE("span"); HTMLWeaving::change_colour(OUT, colour_wanted, colours); current_colour = colour_wanted; } if (Str::get_at(code, i) == '<') WRITE("<"); else if (Str::get_at(code, i) == '>') WRITE(">"); else if (Str::get_at(code, i) == '&') WRITE("&"); else WRITE("%c", Str::get_at(code, i)); } if (current_colour >= 0) HTMLWeaving::change_colour(OUT, -1, colours); } int HTMLWeaving::render_text_as_image(OUTPUT_STREAM, int mode, weave_order *wv, text_stream *desc, text_stream *path) { match_results mr = Regexp::create_mr(); text_stream *as = NULL; if (Regexp::match(&mr, desc, U"text as (%c+)")) as = mr.exp[0]; if (Str::eq(desc, I"text")) as = I"None"; if (as) { filename *F = Filenames::from_text_relative(wv->weave_web->path_to_web, path); if (TextFiles::exists(F) == FALSE) { WRITE_TO(STDERR, "warning: text file at '%S' not found\n", path); } else { TEMPORARY_TEXT(code) TextFiles::write_file_contents(code, F); while ((Str::get_last_char(code) == ' ') || (Str::get_last_char(code) == '\t') || (Str::get_last_char(code) == '\n')) Str::delete_last_character(code); HTMLWeaving::render_code_block(OUT, mode, wv, code, as); DISCARD_TEXT(code) } Regexp::dispose_of(&mr); return TRUE; } if (Regexp::match(&mr, desc, U"download: (%c+)")) { HTMLWeaving::render_download(OUT, wv, path, mr.exp[0]); Regexp::dispose_of(&mr); return TRUE; } if (Str::eq_insensitive(desc, I"HTML")) { HTMLWeaving::render_HTML_extract(OUT, wv, path); Regexp::dispose_of(&mr); return TRUE; } if (Str::eq(desc, I"video")) { HTMLWeaving::render_HTML_player(OUT, wv, path, FALSE, 0, 0); Regexp::dispose_of(&mr); return TRUE; } if (Regexp::match(&mr, desc, U"video at (%d+) by (%d+)")) { int w = Str::atoi(mr.exp[0], 0), h = Str::atoi(mr.exp[1], 0); HTMLWeaving::render_HTML_player(OUT, wv, path, FALSE, w, h); Regexp::dispose_of(&mr); return TRUE; } if (Regexp::match(&mr, desc, U"video at width (%d+)")) { int w = Str::atoi(mr.exp[0], 0); HTMLWeaving::render_HTML_player(OUT, wv, path, FALSE, w, 0); Regexp::dispose_of(&mr); return TRUE; } if (Regexp::match(&mr, desc, U"video at height (%d+)")) { int h = Str::atoi(mr.exp[0], 0); HTMLWeaving::render_HTML_player(OUT, wv, path, FALSE, 0, h); Regexp::dispose_of(&mr); return TRUE; } if ((Regexp::match(&mr, desc, U"embedded (%c+) audio")) || (Regexp::match(&mr, desc, U"embedded (%c+) video"))) { HTMLWeaving::render_embedding(OUT, wv, path, mr.exp[0], 0, 0); Regexp::dispose_of(&mr); return TRUE; } if ((Regexp::match(&mr, desc, U"embedded (%c+) audio at (%d+) by (%d+)")) || (Regexp::match(&mr, desc, U"embedded (%c+) video at (%d+) by (%d+)"))) { int w = Str::atoi(mr.exp[1], 0), h = Str::atoi(mr.exp[2], 0); HTMLWeaving::render_embedding(OUT, wv, path, mr.exp[0], w, h); Regexp::dispose_of(&mr); return TRUE; } if ((Regexp::match(&mr, desc, U"embedded (%c+) audio at height (%d+)")) || (Regexp::match(&mr, desc, U"embedded (%c+) video at height (%d+)"))) { int w = 0, h = Str::atoi(mr.exp[1], 0); HTMLWeaving::render_embedding(OUT, wv, path, mr.exp[0], w, h); Regexp::dispose_of(&mr); return TRUE; } if ((Regexp::match(&mr, desc, U"embedded (%c+) audio at width (%d+)")) || (Regexp::match(&mr, desc, U"embedded (%c+) video at width (%d+)"))) { int w = Str::atoi(mr.exp[1], 0), h = 0; HTMLWeaving::render_embedding(OUT, wv, path, mr.exp[0], w, h); Regexp::dispose_of(&mr); return TRUE; } if (Str::eq(desc, I"audio")) { HTMLWeaving::render_HTML_player(OUT, wv, path, TRUE, 0, 0); Regexp::dispose_of(&mr); return TRUE; } Regexp::dispose_of(&mr); return FALSE; } void HTMLWeaving::render_download(OUTPUT_STREAM, weave_order *wv, text_stream *download_name, text_stream *filetype) { pathname *P = Pathnames::down(wv->weave_web->path_to_web, I"Downloads"); filename *F = Filenames::in(P, download_name); filename *TF = Patterns::find_file_in_subdirectory(wv->weave_web, wv->pattern, I"Embedding", I"Download.html"); if (TF == NULL) { WebErrors::issue_at(I"Downloads are not supported", wv->current_weave_line); } else { Swarm::ensure_plugin(wv, I"Downloads"); asset_rule *R = Assets::simple_private_copy(); pathname *TOP = Assets::include_asset(OUT, R, F, NULL, wv); if (TOP == NULL) TOP = Filenames::up(F); TEMPORARY_TEXT(url) TEMPORARY_TEXT(size) Pathnames::relative_URL(url, Filenames::up(wv->weave_to), TOP); WRITE_TO(url, "%S", Filenames::get_leafname(F)); int N = Filenames::size(F); if (N > 0) Describe the file size13.1 else WebErrors::issue_at(I"Download file missing or empty", wv->current_weave_line); filename *D = Filenames::from_text(download_name); Bibliographic::set_datum(wv->weave_web, I"File Name", Filenames::get_leafname(D)); Bibliographic::set_datum(wv->weave_web, I"File URL", url); Bibliographic::set_datum(wv->weave_web, I"File Details", size); Collater::collate(OUT, wv, TF); WRITE("\n"); DISCARD_TEXT(url) DISCARD_TEXT(size) } }
§13.1. Describe the file size13.1 =
WRITE_TO(size, " ("); if (Str::len(filetype) > 0) WRITE_TO(size, "%S, ", filetype); int x = 0, y = 0; text_stream *unit = I" byte"; x = N; y = 0; if (N > 1) { unit = I" bytes"; } if (N >= 1024) { unit = I"kB"; x = 10*N/1024; y = x%10; x = x/10; } if (N >= 1024*1024) { unit = I"MB"; x = 10*N/1024/1024; y = x%10; x = x/10; } if (N >= 1024*1024*1024) { unit = I"GB"; x = 10*N/1024/1024/1024; y = x%10; x = x/10; } WRITE_TO(size, "%d", x); if (y > 0) WRITE_TO(size, ".%d", y); WRITE_TO(size, "%S", unit); WRITE_TO(size, ")");
- This code is used in §13.
void HTMLWeaving::render_HTML_extract(OUTPUT_STREAM, weave_order *wv, text_stream *leafname) { filename *F = Filenames::in( Pathnames::down(wv->weave_web->path_to_web, I"HTML"), leafname); HTML_OPEN_WITH("div", "class=\"inweb-extract\""); FILE *B = BinaryFiles::try_to_open_for_reading(F); if (B == NULL) { WebErrors::issue_at(I"Unable to find this HTML extract", wv->current_weave_line); } else { while (TRUE) { int c = getc(B); if (c == EOF) break; PUT((inchar32_t) c); } BinaryFiles::close(B); } HTML_CLOSE("div"); WRITE("\n"); } void HTMLWeaving::render_HTML_player(OUTPUT_STREAM, weave_order *wv, text_stream *name, int audio, int w, int h) { text_stream *subdir = (audio)?I"Audio":I"Video"; filename *F = Filenames::in(Pathnames::down(wv->weave_web->path_to_web, subdir), name); asset_rule *R = Assets::simple_private_copy(); Assets::include_asset(OUT, R, F, NULL, wv); HTML_OPEN_WITH("p", "class=\"center-p\""); if (audio) { WRITE("<audio controls>\n"); WRITE("<source src=\"%S\" type=\"audio/mpeg\">\n", name); WRITE("Your browser does not support the audio element.\n"); WRITE("</audio>\n"); } else { if ((w > 0) && (h > 0)) WRITE("<video width=\"%d\" height=\"%d\" controls>", w, h); else if (w > 0) WRITE("<video width=\"%d\" controls>", w); else if (h > 0) WRITE("<video height=\"%d\" controls>", h); else WRITE("<video controls>"); WRITE("<source src=\"%S\" type=\"video/mp4\">\n", name); WRITE("Your browser does not support the video tag.\n"); WRITE("</video>\n"); } HTML_CLOSE("p"); WRITE("\n"); } void HTMLWeaving::render_embedding(OUTPUT_STREAM, weave_order *wv, text_stream *ID, text_stream *service, int w, int h) { if (w == 0) w = 720; if (h == 0) h = 405; TEMPORARY_TEXT(CW) TEMPORARY_TEXT(CH) WRITE_TO(CW, "%d", w); WRITE_TO(CH, "%d", h); TEMPORARY_TEXT(embed_leaf) WRITE_TO(embed_leaf, "%S.html", service); filename *F = Patterns::find_file_in_subdirectory(wv->weave_web, wv->pattern, I"Embedding", embed_leaf); DISCARD_TEXT(embed_leaf) if (F == NULL) { WebErrors::issue_at(I"This is not a supported service", wv->current_weave_line); } else { Bibliographic::set_datum(wv->weave_web, I"Content ID", ID); Bibliographic::set_datum(wv->weave_web, I"Content Width", CW); Bibliographic::set_datum(wv->weave_web, I"Content Height", CH); HTML_OPEN_WITH("p", "class=\"center-p\""); Collater::collate(OUT, wv, F); HTML_CLOSE("p"); WRITE("\n"); } DISCARD_TEXT(CW) DISCARD_TEXT(CH) } int HTMLWeaving::caption(match_results *mr, markdown_item *item, int *pos) { if ((item->type == UNORDERED_LIST_ITEM_MIT) && (item->down) && (item->down->type == PARAGRAPH_MIT) && (Regexp::match(mr, item->down->stashed, U"%(carousel%)"))) { if (pos) *pos = 0; return TRUE; } if ((item->type == UNORDERED_LIST_ITEM_MIT) && (item->down) && (item->down->type == PARAGRAPH_MIT) && (Regexp::match(mr, item->down->stashed, U"%(carousel \"(%c+)\"%)"))) { if (pos) *pos = 0; return TRUE; } if ((item->type == UNORDERED_LIST_ITEM_MIT) && (item->down) && (item->down->type == PARAGRAPH_MIT) && (Regexp::match(mr, item->down->stashed, U"%(carousel \"(%c+)\" captioned below%)"))) { if (pos) *pos = -1; return TRUE; } if ((item->type == UNORDERED_LIST_ITEM_MIT) && (item->down) && (item->down->type == PARAGRAPH_MIT) && (Regexp::match(mr, item->down->stashed, U"%(carousel \"(%c+)\" captioned above%)"))) { if (pos) *pos = 1; return TRUE; } return FALSE; } int HTMLWeaving::render_ul_as_carousel(OUTPUT_STREAM, int mode, weave_order *wv, markdown_item *md, markdown_variation *variation) { match_results mr = Regexp::create_mr(); int not = FALSE, of = 0; for (markdown_item *item = md->down; item; item = item->next) { if (HTMLWeaving::caption(&mr, item, NULL) == FALSE) { not = TRUE; break; } of++; } if (not) { Regexp::dispose_of(&mr); return FALSE; } int count = 1; for (markdown_item *item = md->down; item; item = item->next) { int positioning = 0; HTMLWeaving::caption(&mr, item, &positioning); TEMPORARY_TEXT(carousel_id) TEMPORARY_TEXT(carousel_dots_id) HTMLWeaving::render_carousel_top(OUT, wv, count, of, carousel_id, carousel_dots_id, mr.exp[0], positioning); int m = mode | LOOSE_MDRMODE; for (markdown_item *c = item->down->next; c; c = c->next) { MDRenderer::recurse(OUT, (void *) wv, c, m, variation); m = m & (~EXISTING_PAR_MDRMODE); } HTMLWeaving::render_carousel_bottom(OUT, wv, count, of, carousel_id, carousel_dots_id, mr.exp[0], positioning); DISCARD_TEXT(carousel_id) DISCARD_TEXT(carousel_dots_id) count++; } return TRUE; } void HTMLWeaving::render_carousel_top(OUTPUT_STREAM, weave_order *wv, int slide_number, int slide_of, text_stream *carousel_id, text_stream *carousel_dots_id, text_stream *caption, int positioning) { int N = wv->carousel_number; Swarm::ensure_plugin(wv, I"Carousel"); text_stream *caption_class = NULL; if ((Str::len(caption) == 0) || (positioning == 0)) caption_class = I"carousel-caption"; else if (positioning > 0) caption_class = I"carousel-caption-above"; else if (positioning < 0) caption_class = I"carousel-caption-below"; text_stream *slide_count_class = I"carousel-number"; WRITE_TO(carousel_id, "carousel-no-%d", N); WRITE_TO(carousel_dots_id, "carousel-dots-no-%d", N); if (slide_number == 1) { WRITE("<div class=\"carousel-container\" id=\"%S\">\n", carousel_id); } WRITE("<div class=\"carousel-slide fading-slide\""); if (slide_number == 1) WRITE(" style=\"display: block;\""); else WRITE(" style=\"display: none;\""); WRITE(">\n"); if (positioning > 0) Place caption here14.1; WRITE("<div class=\"%S\">%d / %d</div>\n", slide_count_class, slide_number, slide_of); WRITE("<div class=\"carousel-content\">"); } void HTMLWeaving::render_carousel_bottom(OUTPUT_STREAM, weave_order *wv, int slide_number, int slide_of, text_stream *carousel_id, text_stream *carousel_dots_id, text_stream *caption, int positioning) { text_stream *caption_class = NULL; if ((Str::len(caption) == 0) || (positioning == 0)) caption_class = I"carousel-caption"; else if (positioning > 0) caption_class = I"carousel-caption-above"; else if (positioning < 0) caption_class = I"carousel-caption-below"; WRITE("</div>\n"); if (positioning <= 0) Place caption here14.1; WRITE("</div>\n"); if (slide_number == slide_of) { WRITE("<a class=\"carousel-prev-button\" "); WRITE("onclick=\"carouselMoveSlide("%S", "%S", -1)\"", carousel_id, carousel_dots_id); WRITE(">❮</a>\n"); WRITE("<a class=\"carousel-next-button\" "); WRITE("onclick=\"carouselMoveSlide("%S", "%S", 1)\"", carousel_id, carousel_dots_id); WRITE(">❯</a>\n"); WRITE("</div>\n"); WRITE("<div class=\"carousel-dots-container\" id=\"%S\">\n", carousel_dots_id); for (int i=1; i<=slide_of; i++) { if (i == 1) WRITE("<span class=\"carousel-dot carousel-dot-active\" "); else WRITE("<span class=\"carousel-dot\" "); WRITE("onclick=\"carouselSetSlide("%S", "%S", %d)\"", carousel_id, carousel_dots_id, i-1); WRITE("></span>\n"); } WRITE("</div>\n"); wv->carousel_number++; } }
§14.1. Place caption here14.1 =
if (Str::len(caption) > 0) WRITE("<div class=\"%S\">%S</div>\n", caption_class, caption);
- This code is used in §14 (twice).
void HTMLWeaving::progress_popup(OUTPUT_STREAM, text_stream *cl, text_stream *content) { HTML_OPEN_WITH("span", "class=\"%S\"", cl); HTMLWeaving::escape_text(OUT, content); HTML_CLOSE("span"); }
int HTMLWeaving::begin_weaving_EPUB(weave_format *wf, ls_web *W, ls_pattern *pattern) { TEMPORARY_TEXT(T) WRITE_TO(T, "%S", Bibliographic::get_datum(W, I"Title")); WeavingDetails::set_as_ebook(W, Epub::new(T, "P")); filename *CSS = Patterns::find_file_in_subdirectory(W, pattern, I"Base", I"Base.css"); Epub::use_CSS_throughout(WeavingDetails::get_as_ebook(W), CSS); Epub::attach_metadata(WeavingDetails::get_as_ebook(W), U"identifier", T); DISCARD_TEXT(T) pathname *P = WebStructure::woven_folder(W, 2); WeavingDetails::set_redirect_weaves_to(W, Epub::begin_construction(WeavingDetails::get_as_ebook(W), P, NULL)); Shell::copy(CSS, WeavingDetails::get_redirect_weaves_to(W), ""); return SWARM_SECTIONS_SWM; } void HTMLWeaving::end_weaving_EPUB(weave_format *wf, ls_web *W, ls_pattern *pattern) { Epub::end_construction(WeavingDetails::get_as_ebook(W)); }