diff --git a/README.md b/README.md
index f219c4d5a..fb7f3620a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Inform 7
-[Version](notes/versioning.md): 10.2.0-beta+6X03 'Krypton' (18 August 2023)
+[Version](notes/versioning.md): 10.2.0-beta+6X04 'Krypton' (23 August 2023)
## About Inform
diff --git a/build.txt b/build.txt
index 8298805a5..da0768739 100644
--- a/build.txt
+++ b/build.txt
@@ -1,3 +1,3 @@
Prerelease: beta
-Build Date: 18 August 2023
-Build Number: 6X03
+Build Date: 23 August 2023
+Build Number: 6X04
diff --git a/docs/supervisor-module/1-ic.html b/docs/supervisor-module/1-ic.html
index 6d7cbf9b5..69eb2cfc6 100644
--- a/docs/supervisor-module/1-ic.html
+++ b/docs/supervisor-module/1-ic.html
@@ -614,7 +614,7 @@ nests, respectively.
return shared_nest_list ;
}
-inbuild_nest * Supervisor::internal ( void ) {
+inbuild_nest * Supervisor::internal ( void ) {
RUN_ONLY_FROM_PHASE ( NESTED_INBUILD_PHASE )
return shared_internal_nest ;
}
diff --git a/docs/supervisor-module/1-sm.html b/docs/supervisor-module/1-sm.html
index 97dc0368d..e57ba0fa0 100644
--- a/docs/supervisor-module/1-sm.html
+++ b/docs/supervisor-module/1-sm.html
@@ -74,14 +74,7 @@ which use this module:
enum build_skill_CLASS
enum build_step_CLASS
enum build_vertex_CLASS
-enum cdoc_heading_CLASS
enum cdoc_example_CLASS
-enum cdoc_passage_CLASS
-enum cdoc_phrase_defn_CLASS
-enum cdoc_paragraph_CLASS
-enum cdoc_code_sample_CLASS
-enum cdoc_code_line_CLASS
-enum cdoc_source_error_CLASS
enum compiled_documentation_CLASS
enum control_structure_phrase_CLASS
enum copy_error_CLASS
@@ -114,14 +107,7 @@ which use this module:
DECLARE_CLASS ( build_skill )
DECLARE_CLASS ( build_step )
DECLARE_CLASS ( build_vertex )
-DECLARE_CLASS ( cdoc_heading )
DECLARE_CLASS ( cdoc_example )
-DECLARE_CLASS ( cdoc_passage )
-DECLARE_CLASS ( cdoc_phrase_defn )
-DECLARE_CLASS ( cdoc_paragraph )
-DECLARE_CLASS ( cdoc_code_sample )
-DECLARE_CLASS ( cdoc_code_line )
-DECLARE_CLASS ( cdoc_source_error )
DECLARE_CLASS ( control_structure_phrase )
DECLARE_CLASS ( compiled_documentation )
DECLARE_CLASS ( copy_error )
diff --git a/docs/supervisor-module/2-nst.html b/docs/supervisor-module/2-nst.html
index ea9e0867f..e4d737457 100644
--- a/docs/supervisor-module/2-nst.html
+++ b/docs/supervisor-module/2-nst.html
@@ -151,7 +151,7 @@ can't install to a read-only nest.
-pathname * Nests::get_location ( inbuild_nest * N ) {
+pathname * Nests::get_location ( inbuild_nest * N ) {
if ( N == NULL ) return NULL ;
return N -> location ;
}
diff --git a/docs/supervisor-module/2-wrk.html b/docs/supervisor-module/2-wrk.html
index b048d8d21..1d3d481e3 100644
--- a/docs/supervisor-module/2-wrk.html
+++ b/docs/supervisor-module/2-wrk.html
@@ -195,7 +195,7 @@ would both pass, whereas Works::normal
VOID_METHOD_CALL ( work -> genre , GENRE_WRITE_WORK_MTID , OUT , work );
}
-void Works::write_to_HTML_file ( OUTPUT_STREAM , inbuild_work * work , int fancy ) {
+void Works::write_to_HTML_file ( OUTPUT_STREAM , inbuild_work * work , int fancy ) {
WRITE ( "%S" , work -> raw_title );
if ( fancy ) HTML::begin_span ( OUT , I "extensionindexentry" );
WRITE ( " by " );
diff --git a/docs/supervisor-module/3-bg.html b/docs/supervisor-module/3-bg.html
index 4395b4eb3..2da081543 100644
--- a/docs/supervisor-module/3-bg.html
+++ b/docs/supervisor-module/3-bg.html
@@ -111,7 +111,7 @@ compiled, is a file vertex.
CLASS_DEFINITION
} build_vertex ;
-The structure build_vertex is accessed in 1/sm, 3/ib, 3/bs2, 3/is, 3/is3, 3/is4, 4/em, 5/es, 5/ks, 5/ls, 5/ps, 5/ps2, 5/ts, 6/st, 6/hdn, 6/inc, 7/tm, 7/eip, 7/ti, 7/tc, 7/dt, 7/dc, 7/dr and here.
+The structure build_vertex is accessed in 1/sm, 3/ib, 3/bs2, 3/is, 3/is3, 3/is4, 4/em, 5/es, 5/ks, 5/ls, 5/ps, 5/ps2, 5/ts, 6/st, 6/hdn, 6/inc, 7/tm, 7/eip, 7/ti, 7/tc, 7/dc, 7/dr, 7/dim and here.
diff --git a/docs/supervisor-module/3-bs2.html b/docs/supervisor-module/3-bs2.html
index c43512bb0..c62047247 100644
--- a/docs/supervisor-module/3-bs2.html
+++ b/docs/supervisor-module/3-bs2.html
@@ -82,7 +82,7 @@ assimilating a binary for a kit is a skill.
return S ;
}
-The structure build_skill is accessed in 2/gnr, 7/dt, 7/dr and here.
+The structure build_skill is accessed in 2/gnr, 7/dc, 7/dr, 7/dim and here.
This code is used in §12 .
@@ -1058,7 +1058,7 @@ then its sentences will go to the extension's own tree.
void Extensions::document ( inform_extension * E , pathname * dest ) {
SVEXPLAIN (1, "(documenting %X to %p)\n" , E -> as_copy -> edition -> work , dest );
compiled_documentation * cd = Extensions::get_documentation ( E );
- DocumentationRenderer::as_HTML ( dest , cd , NULL );
+ DocumentationRenderer::as_HTML ( dest , cd , NULL );
}
The structure heading is accessed in 1/sm, 3/bs2, 6/inc, 7/dt, 7/dr and here.
+The structure heading is accessed in 1/sm, 3/bs2, 6/inc, 7/dr and here.
diff --git a/docs/supervisor-module/7-dc.html b/docs/supervisor-module/7-dc.html
index 2cd2dbc58..d9db60985 100644
--- a/docs/supervisor-module/7-dc.html
+++ b/docs/supervisor-module/7-dc.html
@@ -60,7 +60,7 @@ function togglePopup(material_id) {
To compile documentation from the textual syntax in an extension into a tree.
@@ -69,7 +69,7 @@ it's really not much more than the tree produced by struct text_stream * original ;
struct inform_extension * associated_extension ;
struct inform_extension * within_extension ;
- struct heterogeneous_tree * tree ;
+ struct markdown_item * alt_tree ;
int total_headings [3];
int total_examples ;
int empty ;
@@ -77,13 +77,13 @@ it's really not much more than the tree produced by CLASS_DEFINITION
} compiled_documentation ;
-compiled_documentation * DocumentationCompiler::new_wrapper ( text_stream * source ) {
+compiled_documentation * DocumentationCompiler::new_wrapper ( text_stream * source ) {
compiled_documentation * cd = CREATE ( compiled_documentation );
cd -> title = Str::new ();
cd -> original = Str::duplicate ( source );
cd -> associated_extension = NULL ;
cd -> within_extension = NULL ;
- cd -> tree = DocumentationTree::new ();
+ cd -> alt_tree = NULL ;
cd -> total_examples = 0 ;
cd -> total_headings [0] = 1 ;
cd -> total_headings [1] = 0 ;
@@ -105,27 +105,52 @@ it's really not much more than the tree produced by } satellite_test_case ;
The structure compiled_documentation is accessed in 2/wrk, 2/edt, 2/cps, 2/rqr, 2/jm, 3/bg, 3/is, 4/ebm, 4/km, 4/lm, 4/pm, 4/pbm, 4/pfm, 4/tm, 5/es, 5/ks, 5/ls, 5/ps2, 6/inc, 7/tm, 7/eip, 7/ti, 7/tc, 7/dr and here. The structure satellite_test_case is accessed in 5/ks and here.
-
-compiled_documentation * DocumentationCompiler::compile_from_path ( pathname * P ,
+typedef struct cdoc_example {
+ struct text_stream * name ;
+ struct text_stream * description ;
+ int star_count ;
+ int number ;
+ char letter ;
+ CLASS_DEFINITION
+} cdoc_example ;
+
+cdoc_example * DocumentationCompiler::new_example_alone ( text_stream * title , text_stream * desc , int star_count , int ecount ) {
+ cdoc_example * E = CREATE ( cdoc_example );
+ E -> name = Str::duplicate ( title );
+ E -> description = Str::duplicate ( desc );
+ E -> star_count = star_count ;
+ E -> number = ecount ;
+ E -> letter = 'A' + ( char ) ecount - 1 ;
+ return E ;
+}
+
+The structure cdoc_example is accessed in 3/bs2, 7/dr, 7/dim and here.
+
+
+
+compiled_documentation * DocumentationCompiler::compile_from_path ( pathname * P ,
inform_extension * associated_extension ) {
filename * F = Filenames::in ( P , I "Documentation.txt" );
if ( TextFiles::exists ( F ) == FALSE ) return NULL ;
compiled_documentation * cd =
- DocumentationCompiler::compile_from_file ( F , associated_extension );
+ DocumentationCompiler::compile_from_file ( F , associated_extension );
if ( cd == NULL ) return NULL ;
pathname * EP = Pathnames::down ( P , I "Examples" );
int egs = TRUE ;
- Scan EP directory for examples 2.1 ;
+ Scan EP directory for examples 3.1 ;
egs = FALSE ;
EP = Pathnames::down ( P , I "Tests" );
- Scan EP directory for examples 2.1 ;
+ Scan EP directory for examples 3.1 ;
return cd ;
}
-
@@ -158,7 +183,7 @@ it's really not much more than the tree produced by if ( TextFiles::exists ( IF )) stc -> ideal_transcript = IF ;
DISCARD_TEXT ( ideal_leafname )
if ( stc -> is_example ) {
- Scan the example for its header and content 2.1.2 ;
+ Scan the example for its header and content 3.1.2 ;
}
ADD_TO_LINKED_LIST ( stc , satellite_test_case , cd -> cases );
}
@@ -166,8 +191,8 @@ it's really not much more than the tree produced by Directories::close ( D );
}
-This code is used in §2 (twice).
-
+This code is used in §3 (twice).
+
typedef struct example_scanning_state {
@@ -176,14 +201,13 @@ it's really not much more than the tree produced by struct text_stream * body_text ;
struct text_stream * placement ;
struct text_stream * desc ;
- struct linked_list * errors ;
- struct heterogeneous_tree * tree ;
+ struct linked_list * errors ;
struct text_stream * scanning ;
int past_header ;
} example_scanning_state ;
-The structure example_scanning_state is accessed in 5/es, 7/tc, 7/dt, 7/dr and here.
-The structure example_scanning_state is accessed in 5/es, 7/tc, 7/dim and here.
+
@@ -193,67 +217,75 @@ it's really not much more than the tree produced by ess . body_text = Str::new ();
ess . placement = NULL ;
ess . desc = NULL ;
- ess . errors = NEW_LINKED_LIST ( tree_node );
- ess . tree = cd -> tree ;
+ ess . errors = NEW_LINKED_LIST ( markdown_item );
ess . past_header = FALSE ;
ess . scanning = Str::new (); WRITE_TO ( ess . scanning , "%S" , Filenames::get_leafname ( stc -> test_file ));
TextFiles::read ( stc -> test_file , FALSE , "unable to read file of example" , TRUE ,
- & DocumentationCompiler::read_example_helper , NULL , & ess );
+ & DocumentationCompiler::read_example_helper , NULL , & ess );
- tree_node * placement_node = NULL ;
+ markdown_item * alt_placement_node = NULL ;
if ( Str::len ( ess . placement ) == 0 ) {
- placement_node = cd -> tree -> root ;
+ ;
} else {
- placement_node = DocumentationTree::find_section ( cd -> tree , ess . placement );
- if ( placement_node == NULL ) {
- DocumentationCompiler::example_error (& ess ,
+ alt_placement_node = DocumentationInMarkdown::find_section ( cd -> alt_tree , ess . placement );
+ LOG ( "Looking for %S.\n" , ess . placement );
+ if ( alt_placement_node == NULL ) {
+ DocumentationCompiler::example_error (& ess ,
I "example gives a Location which is not the name of any section" );
}
}
+
if ( Str::len ( ess . desc ) == 0 ) {
- DocumentationCompiler::example_error (& ess ,
+ DocumentationCompiler::example_error (& ess ,
I "example does not give its Description" );
}
- tree_node * content_node = NULL ;
- if ( Str::len ( ess . body_text ) == 0 ) {
- DocumentationCompiler::example_error (& ess ,
- I "example does not give any actual content" );
- } else {
- compiled_documentation * ecd =
- DocumentationCompiler::compile ( ess . body_text , associated_extension );
- if (( ecd ) && ( ecd -> tree ) && ( ecd -> tree -> root ) &&
- ( ecd -> tree -> root -> child ) &&
- ( ecd -> tree -> root -> child -> type == passage_TNT ))
- content_node = ecd -> tree -> root -> child ;
- else {
- DocumentationCompiler::example_error (& ess ,
- I "example file content is missing or wrongly set out" );
- }
- }
- tree_node * example_node = DocumentationTree::new_example ( cd -> tree ,
+ cdoc_example * eg = DocumentationCompiler::new_example_alone (
ess . long_title , ess . desc , ess . star_count , ++( cd -> total_examples ));
- if ( placement_node ) Trees::make_child ( example_node , placement_node );
- if ( content_node ) Trees::make_child ( content_node , example_node );
- tree_node * E ;
- LOOP_OVER_LINKED_LIST ( E , tree_node , ess . errors )
- Trees::make_child ( E , cd -> tree -> root );
-
-This code is used in §2.1 .
-
+ markdown_item * eg_header = Markdown::new_item ( INFORM_EXAMPLE_HEADING_MIT );
+ eg_header -> user_state = STORE_POINTER_cdoc_example ( eg );
+ markdown_item * md = alt_placement_node ;
+ if ( md == NULL ) {
+ md = cd -> alt_tree -> down ;
+ if ( md == NULL ) cd -> alt_tree -> down = eg_header ;
+ else {
+ while (( md ) && ( md -> next )) md = md -> next ;
+ eg_header -> next = md -> next ; md -> next = eg_header ;
+ }
+ } else {
+ if ( md -> next ) md = md -> next ;
+ while (( md ) && ( md -> next ) && ( md -> next -> type != HEADING_MIT )) md = md -> next ;
+ eg_header -> next = md -> next ; md -> next = eg_header ;
+ }
+ if ( Str::len ( ess . body_text ) > 0 ) {
+ markdown_item * alt_ecd = Markdown::parse_extended ( ess . body_text ,
+ DocumentationInMarkdown::extension_flavoured_Markdown ());
+ eg_header -> down = alt_ecd -> down ;
+ Markdown::debug_subtree ( DL , eg_header );
+ } else {
+ DocumentationCompiler::example_error (& ess ,
+ I "example does not give any actual content" );
+ }
-
-void DocumentationCompiler::example_error ( example_scanning_state * ess , text_stream * text ) {
- text_stream * err = Str::new ();
- WRITE_TO ( err , "Example file '%S': %S" , ess -> scanning , text );
- tree_node * E = DocumentationTree::new_source_error ( ess -> tree , err );
- ADD_TO_LINKED_LIST ( E , tree_node , ess -> errors );
-}
+ markdown_item * E ;
+ LOOP_OVER_LINKED_LIST ( E , markdown_item , ess . errors )
+ Markdown::add_to ( E , cd -> alt_tree );
+This code is used in §3.1 .
-void DocumentationCompiler::read_example_helper ( text_stream * text , text_file_position * tfp ,
+void DocumentationCompiler::example_error ( example_scanning_state * ess , text_stream * text ) {
+ text_stream * err = Str::new ();
+ WRITE_TO ( err , "Example file '%S': %S" , ess -> scanning , text );
+ markdown_item * E = DocumentationInMarkdown::error_item ( err );
+ ADD_TO_LINKED_LIST ( E , markdown_item , ess -> errors );
+}
+
+
+
+
+void DocumentationCompiler::read_example_helper ( text_stream * text , text_file_position * tfp ,
void * v_state ) {
example_scanning_state * ess = ( example_scanning_state *) v_state ;
if ( tfp -> line_count == 1 ) {
@@ -262,18 +294,18 @@ it's really not much more than the tree produced by (Regexp::match (& mr , text , L "Example *- *(%**) *(%c+?)" ))) {
ess -> star_count = Str::len ( mr . exp [0]);
if ( ess -> star_count == 0 ) {
- DocumentationCompiler::example_error ( ess ,
+ DocumentationCompiler::example_error ( ess ,
I "this example should be marked (before the title) '*', '**', '***' or '****' for difficulty" );
ess -> star_count = 1 ;
}
if ( ess -> star_count > 4 ) {
- DocumentationCompiler::example_error ( ess ,
+ DocumentationCompiler::example_error ( ess ,
I "four stars '****' is the maximum difficulty rating allowed" );
ess -> star_count = 4 ;
}
ess -> long_title = Str::duplicate ( mr . exp [1]);
} else {
- DocumentationCompiler::example_error ( ess ,
+ DocumentationCompiler::example_error ( ess ,
I "titling line of example file is malformed" );
}
Regexp::dispose_of (& mr );
@@ -284,11 +316,11 @@ it's really not much more than the tree produced by if ( Str::eq ( mr . exp [0], I "Location" )) ess -> placement = Str::duplicate ( mr . exp [1]);
else if ( Str::eq ( mr . exp [0], I "Description" )) ess -> desc = Str::duplicate ( mr . exp [1]);
else {
- DocumentationCompiler::example_error ( ess ,
+ DocumentationCompiler::example_error ( ess ,
I "unknown datum in header line of example file" );
}
} else {
- DocumentationCompiler::example_error ( ess ,
+ DocumentationCompiler::example_error ( ess ,
I "header line of example file is malformed" );
}
Regexp::dispose_of (& mr );
@@ -297,16 +329,16 @@ it's really not much more than the tree produced by }
}
-
+
-compiled_documentation * DocumentationCompiler::compile_from_file ( filename * F ,
+compiled_documentation * DocumentationCompiler::compile_from_file ( filename * F ,
inform_extension * associated_extension ) {
TEMPORARY_TEXT ( temp )
TextFiles::read ( F , FALSE , "unable to read file of documentation" , TRUE ,
- & DocumentationCompiler::read_file_helper , NULL , temp );
+ & DocumentationCompiler::read_file_helper , NULL , temp );
compiled_documentation * cd =
- DocumentationCompiler::compile ( temp , associated_extension );
+ DocumentationCompiler::compile ( temp , associated_extension );
DISCARD_TEXT ( temp )
return cd ;
}
@@ -317,11 +349,11 @@ it's really not much more than the tree produced by WRITE_TO ( contents , "%S\n" , text );
}
-
-compiled_documentation * DocumentationCompiler::compile ( text_stream * source ,
+compiled_documentation * DocumentationCompiler::compile ( text_stream * source ,
inform_extension * associated_extension ) {
SVEXPLAIN (1, "(compiling documentation: %d chars)\n" , Str::len ( source ));
compiled_documentation * cd = DocumentationCompiler::new_wrapper ( source );
@@ -329,442 +361,15 @@ it's really not much more than the tree produced by if ( cd -> associated_extension )
WRITE_TO ( cd -> title , "%X" , cd -> associated_extension -> as_copy -> edition -> work );
if ( Str::is_whitespace ( source )) cd -> empty = TRUE ;
- else Parse the source 6.1 ;
- if ( cd -> empty ) {
- SVEXPLAIN (1, "(resulting tree is empty)\n" );
- } else {
- SVEXPLAIN (1, "(resulting tree has %d chapter(s), %d section(s) and %d example(s))\n" ,
- cd -> total_headings [1], cd -> total_headings [2], cd -> total_examples );
- }
+ else cd -> alt_tree = Markdown::parse_extended ( source ,
+ DocumentationInMarkdown::extension_flavoured_Markdown ());
return cd ;
}
-
-
-
+
- int chapter_number = 0 , section_number = 0 ;
-
- tree_node * current_headings [4];
- current_headings [0] = cd -> tree -> root ;
- current_headings [1] = NULL ;
- current_headings [2] = NULL ;
- current_headings [3] = NULL ;
-
- tree_node * current_passage = NULL ,
- * current_phrase_defn = NULL ,
- * current_paragraph = NULL ,
- * current_code = NULL ,
- * last_paste_code = NULL ;
-
- int pending_code_sample_blanks = 0 , code_is_tabular = FALSE ;
- programming_language * default_language = DocumentationCompiler::get_language ( I "Inform" );
- programming_language * language = default_language ;
-
- Parse the source linewise 6.1.1 ;
-
-
-
-
-
-
-
- TEMPORARY_TEXT ( line )
- int indentation = 0 , space_count = 0 ;
- for ( int i =0; i < Str::len ( source ); i ++) {
- wchar_t c = Str::get_at ( source , i );
- if ( c == '\n' ) {
- Line read 6.1.1.1 ;
- Str::clear ( line );
- indentation = 0 ; space_count = 0 ;
- } else if (( Str::len ( line ) == 0 ) && ( Characters::is_whitespace ( c ))) {
- if ( c == '\t' ) indentation ++;
- if ( c == ' ' ) space_count ++;
- if ( space_count == 4 ) { indentation ++; space_count = 0 ; }
- } else {
- PUT_TO ( line , c );
- }
- }
- if ( Str::len ( line ) > 0 ) Line read 6.1.1.1 ;
- Check for runaway phrase definitions 6.1.1.2 ;
- Complete passage if in one 6.1.1.3 ;
- DISCARD_TEXT ( line )
-
-This code is used in §6.1 .
-
-
-
-
-
- Chapter: Survey and Prospecting
- Section: Black Gold
- Example: *** Gelignite Anderson - A Tale of the Texas Oilmen
-
-
-
-
-
-
-
-
- Str::trim_white_space ( line );
- if ( Str::len ( line ) == 0 ) {
- if ( current_paragraph ) Complete paragraph or code 6.1.1.1.7 ;
- if ( current_code ) Insert line break in code 6.1.1.1.12 ;
- } else if ( indentation == 0 ) {
- match_results mr = Regexp::create_mr ();
- if (( Regexp::match (& mr , line , L "Section *: *(%c+?)" )) ||
- ( Regexp::match (& mr , line , L "Section *- *(%c+?)" ))) {
- Insert a section heading 6.1.1.1.2 ;
- } else if (( Regexp::match (& mr , line , L "Chapter *: *(%c+?)" )) ||
- ( Regexp::match (& mr , line , L "Chapter *- *(%c+?)" ))) {
- Insert a chapter heading 6.1.1.1.1 ;
- } else if (( Regexp::match (& mr , line , L "Example *: *(%**) *(%c+?)" )) ||
- ( Regexp::match (& mr , line , L "Example *- *(%**) *(%c+?)" ))) {
- Insert an example heading 6.1.1.1.3 ;
- } else if ( Regexp::match (& mr , line , L "{defn *(%c*?)} *(%c+)" )) {
- Begin a phrase definition 6.1.1.1.4 ;
- } else if ( Regexp::match (& mr , line , L "{end}" )) {
- End a phrase definition 6.1.1.1.5 ;
- } else {
- if ( current_paragraph == NULL ) Begin paragraph 6.1.1.1.8 ;
- Insert space in paragraph 6.1.1.1.9 ;
- Insert line in paragraph 6.1.1.1.10 ;
- }
- Regexp::dispose_of (& mr );
- } else {
- if ( current_code == NULL ) {
- if (( Str::get_at ( line , 0 ) == '{' ) && ( Str::get_at ( line , 1 ) == 'a' ) &&
- ( Str::get_at ( line , 2 ) == 's' ) && ( Str::get_at ( line , 3 ) == ' ' ) &&
- ( Str::get_at ( line , Str::len ( line )-1) == '}' )) {
- Str::delete_n_characters ( line , 4 );
- Str::delete_last_character ( line );
- Str::trim_white_space ( line );
- language = DocumentationCompiler::get_language ( line );
- if ( language == NULL ) {
- Complete paragraph or code 6.1.1.1.7 ;
- Begin passage if not already in one 6.1.1.1.6 ;
- TEMPORARY_TEXT ( err )
- WRITE_TO ( err , "cannot find a language called '%S'" , line );
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree , err );
- Trees::make_child ( E , current_passage );
- DISCARD_TEXT ( err )
- }
- } else {
- Begin code 6.1.1.1.11 ;
- Insert line in code sample 6.1.1.1.13 ;
- }
- } else {
- Insert line in code sample 6.1.1.1.13 ;
- }
- }
-
-This code is used in §6.1.1 (twice).
-
-
-
- Complete passage if in one 6.1.1.3 ;
- chapter_number ++;
- section_number = 0 ;
- int level = 1 , id = cd -> total_headings [0] + cd -> total_headings [1] + cd -> total_headings [2];
- cd -> total_headings [1]++;
- tree_node * new_node = DocumentationTree::new_heading ( cd -> tree , mr . exp [0], mr . exp [0], level ,
- id , chapter_number , section_number );
- Place this new structural node in the tree 6.1.1.1.1.1 ;
-
-This code is used in §6.1.1.1 .
-
-
-
- Complete passage if in one 6.1.1.3 ;
- section_number ++;
- int level = 2 , id = cd -> total_headings [0] + cd -> total_headings [1] + cd -> total_headings [2];
- cd -> total_headings [2]++;
- tree_node * new_node = DocumentationTree::new_heading ( cd -> tree , mr . exp [0], mr . exp [0], level ,
- id , chapter_number , section_number );
- Place this new structural node in the tree 6.1.1.1.1.1 ;
-
-This code is used in §6.1.1.1 .
-
-
-
- Complete passage if in one 6.1.1.3 ;
- int level = 3 , star_count = Str::len ( mr . exp [0]);
- tree_node * new_node = DocumentationTree::new_example ( cd -> tree , mr . exp [1], NULL ,
- star_count , ++( cd -> total_examples ));
- Place this new structural node in the tree 6.1.1.1.1.1 ;
- if ( star_count == 0 ) {
- Begin passage if not already in one 6.1.1.1.6 ;
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree ,
- I "this example should be marked (before the title) '*', '**', '***' or '****' for difficulty" );
- Trees::make_child ( E , current_passage );
- }
- if ( star_count > 4 ) {
- Begin passage if not already in one 6.1.1.1.6 ;
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree ,
- I "four stars '****' is the maximum difficulty rating allowed" );
- Trees::make_child ( E , current_passage );
- }
-
-This code is used in §6.1.1.1 .
-
-
-
- Check for runaway phrase definitions 6.1.1.2 ;
- if ( current_phrase_defn == NULL ) {
- Begin passage if not already in one 6.1.1.1.6 ;
- Complete paragraph or code 6.1.1.1.7 ;
- current_phrase_defn =
- DocumentationTree::new_phrase_defn ( cd -> tree , mr . exp [0], mr . exp [1]);
- Trees::make_child ( current_phrase_defn , current_passage );
- Complete passage if in one 6.1.1.3 ;
- }
-
-This code is used in §6.1.1.1 .
-
-
-
- if ( current_phrase_defn ) {
- Complete passage if in one 6.1.1.3 ;
- current_passage = current_phrase_defn -> parent ;
- current_phrase_defn = NULL ;
- } else {
- Begin passage if not already in one 6.1.1.1.6 ;
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree ,
- I "{end} without {defn}" );
- Trees::make_child ( E , current_passage );
- }
- language = default_language ;
-
-This code is used in §6.1.1.1 .
-
-
-
- Check for runaway phrase definitions 6.1.1.2 ;
- for ( int j = level -1; j >=0; j --)
- if ( current_headings [ j ]) {
- Trees::make_child ( new_node , current_headings [ j ]);
- break ;
- }
- current_headings [ level ] = new_node ;
- for ( int j = level +1; j <4; j ++) current_headings [ j ] = NULL ;
- language = default_language ;
-
-
-
-
-
- if ( current_phrase_defn ) {
- Begin passage if not already in one 6.1.1.1.6 ;
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree ,
- I "{defn} has no {end}" );
- Trees::make_child ( E , current_passage );
- current_phrase_defn = NULL ;
- }
-
-
-
-
-
- if ( current_passage == NULL ) {
- current_passage = DocumentationTree::new_passage ( cd -> tree );
- if ( current_phrase_defn )
- Trees::make_child ( current_passage , current_phrase_defn );
- else for ( int j =3; j >=0; j --)
- if ( current_headings [ j ]) {
- Trees::make_child ( current_passage , current_headings [ j ]);
- break ;
- }
- current_paragraph = NULL ;
- }
-
-
-
-
-
- if ( current_passage ) {
- Complete paragraph or code 6.1.1.1.7 ;
- current_passage = NULL ;
- }
-
-
-
-
-
- if ( current_paragraph ) Complete paragraph 6.1.1.1.7.1
- if ( current_code ) Complete code 6.1.1.1.7.2
-
-
-
-
-
-
-
- Complete paragraph or code 6.1.1.1.7 ;
- Begin passage if not already in one 6.1.1.1.6 ;
- current_paragraph = DocumentationTree::new_paragraph ( cd -> tree , NULL );
- Trees::make_child ( current_paragraph , current_passage );
-
-This code is used in §6.1.1.1 .
-
-
-
- cdoc_paragraph * P = RETRIEVE_POINTER_cdoc_paragraph ( current_paragraph -> content );
- if ( Str::len ( P -> content ) > 0 ) WRITE_TO ( P -> content , " " );
-
-This code is used in §6.1.1.1 .
-
-
-
- cdoc_paragraph * P = RETRIEVE_POINTER_cdoc_paragraph ( current_paragraph -> content );
- WRITE_TO ( P -> content , "%S" , line );
-
-This code is used in §6.1.1.1 .
-
-
-
- if ( current_paragraph ) {
- current_paragraph = NULL ;
- }
-
-This code is used in §6.1.1.1.7 .
-
-
-
-
-
- Complete paragraph or code 6.1.1.1.7 ;
- Begin passage if not already in one 6.1.1.1.6 ;
-
- int paste_me = FALSE , continue_me = FALSE ;
- if (( Str::get_at ( line , 0 ) == '*' ) &&
- ( Str::get_at ( line , 1 ) == ':' )) {
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::trim_white_space ( line );
- paste_me = TRUE ;
- } else if (( Str::get_at ( line , 0 ) == '*' ) &&
- ( Str::get_at ( line , 1 ) == '*' ) &&
- ( Str::get_at ( line , 2 ) == ':' )) {
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::trim_white_space ( line );
- continue_me = TRUE ;
- } else if (( Str::get_at ( line , 0 ) == '{' ) && ( Str::get_at ( line , 1 ) == '*' ) &&
- ( Str::get_at ( line , 2 ) == '}' )) {
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::trim_white_space ( line );
- paste_me = TRUE ;
- } else if (( Str::get_at ( line , 0 ) == '{' ) && ( Str::get_at ( line , 1 ) == '*' ) &&
- ( Str::get_at ( line , 2 ) == '*' ) && ( Str::get_at ( line , 3 ) == '}' )) {
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::delete_first_character ( line );
- Str::trim_white_space ( line );
- continue_me = TRUE ;
- }
-
- current_code = DocumentationTree::new_code_sample ( cd -> tree , paste_me , language );
- if ( continue_me ) {
- if ( last_paste_code ) {
- cdoc_code_sample * S = RETRIEVE_POINTER_cdoc_code_sample ( last_paste_code -> content );
- S -> continuation = current_code ;
- } else {
- tree_node * E = DocumentationTree::new_source_error ( cd -> tree , I "cannot continue a paste here" );
- Trees::make_child ( E , current_passage );
- }
- }
- if (( paste_me ) || ( continue_me )) {
- last_paste_code = current_code ;
- } else {
- last_paste_code = NULL ;
- }
- Trees::make_child ( current_code , current_passage );
- pending_code_sample_blanks = 0 ;
- code_is_tabular = FALSE ;
-
-This code is used in §6.1.1.1 .
-
-
-
- if ( current_code -> child ) {
- pending_code_sample_blanks ++;
- code_is_tabular = FALSE ;
- }
-
-This code is used in §6.1.1.1 .
-
-
-
- for ( int i =0; i < pending_code_sample_blanks ; i ++)
- Trees::make_child ( DocumentationTree::new_code_line ( cd -> tree , NULL , 0 , FALSE ), current_code );
- pending_code_sample_blanks = 0 ;
- match_results mr = Regexp::create_mr ();
- if ( Regexp::match (& mr , line , L "Table %c*" )) {
- code_is_tabular = TRUE ;
- }
- Regexp::dispose_of (& mr );
- Trees::make_child ( DocumentationTree::new_code_line ( cd -> tree , line , indentation -1, code_is_tabular ),
- current_code );
-
-This code is used in §6.1.1.1 (twice).
-
-
-
- if ( current_code ) {
- current_code = NULL ;
- code_is_tabular = FALSE ;
- }
-
-This code is used in §6.1.1.1.7 .
-
-
-
-programming_language * DocumentationCompiler::get_language ( text_stream * name ) {
+programming_language * DocumentationCompiler::get_language ( text_stream * name ) {
inbuild_nest * N = Supervisor::internal ();
if ( N == NULL ) return NULL ;
pathname * LP = Pathnames::down ( Nests::get_location ( N ), I "PLs" );
@@ -775,7 +380,7 @@ of a code sample either, since a non-blank indented line is needed to trigger on
}
+
diff --git a/docs/supervisor-module/7-dim.html b/docs/supervisor-module/7-dim.html
new file mode 100644
index 000000000..e9216ee57
--- /dev/null
+++ b/docs/supervisor-module/7-dim.html
@@ -0,0 +1,739 @@
+
+
+
+ Documentation in Markdown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Compiler Other Tools Resources Repository Related Projects
+
+
+
+
+To provide a variation on Markdown for extension documentation.
+
+
+
+enum INFORM_HEADINGS_MARKDOWNFEATURE
+enum PASTE_ICONS_MARKDOWNFEATURE
+
+
+
+enum INFORM_EXAMPLE_HEADING_MIT
+enum INFORM_ERROR_MARKER_MIT
+markdown_variation * extension_flavoured_Markdown = NULL ;
+
+markdown_variation * DocumentationInMarkdown::extension_flavoured_Markdown ( void ) {
+ if ( extension_flavoured_Markdown ) return extension_flavoured_Markdown ;
+ extension_flavoured_Markdown = MarkdownVariations::new ( I "Inform-flavoured Markdown" );
+ MarkdownVariations::remove_feature ( extension_flavoured_Markdown , HTML_BLOCKS_MARKDOWNFEATURE );
+ MarkdownVariations::remove_feature ( extension_flavoured_Markdown , INLINE_HTML_MARKDOWNFEATURE );
+
+ markdown_feature * Inform_headings = MarkdownVariations::new_feature ( I "Inform_headings" , INFORM_HEADINGS_MARKDOWNFEATURE );
+ METHOD_ADD ( Inform_headings , POST_PHASE_I_MARKDOWN_MTID , DocumentationInMarkdown::Inform_headings_intervene_after_Phase_I );
+ MarkdownVariations::add_feature ( extension_flavoured_Markdown , INFORM_HEADINGS_MARKDOWNFEATURE );
+
+ markdown_feature * paste_icons = MarkdownVariations::new_feature ( I "paste icons" , PASTE_ICONS_MARKDOWNFEATURE );
+ METHOD_ADD ( paste_icons , RENDER_MARKDOWN_MTID , DocumentationInMarkdown::paste_icons_renderer );
+ METHOD_ADD ( paste_icons , POST_PHASE_I_MARKDOWN_MTID , DocumentationInMarkdown::paste_icons_intervene_after_Phase_I );
+ MarkdownVariations::add_feature ( extension_flavoured_Markdown , PASTE_ICONS_MARKDOWNFEATURE );
+
+ Markdown::new_container_block_type ( INFORM_EXAMPLE_HEADING_MIT , I "INFORM_EXAMPLE_HEADING" );
+ Markdown::new_leaf_block_type ( INFORM_ERROR_MARKER_MIT , I "INFORM_ERROR_MARKER" );
+
+ return extension_flavoured_Markdown ;
+}
+
+
+
+
+ Chapter: Survey and Prospecting
+ Section: Black Gold
+ Example: *** Gelignite Anderson - A Tale of the Texas Oilmen
+
+
+
+
+void DocumentationInMarkdown::Inform_headings_intervene_after_Phase_I ( markdown_feature * feature ,
+ markdown_item * tree , md_links_dictionary * link_references ) {
+ int example_number = 0 ;
+ DocumentationInMarkdown::Inform_headings_r ( tree , & example_number );
+ DocumentationInMarkdown::regroup_examples_r ( tree , & example_number );
+ int section_number = 0 , chapter_number = 0 ;
+ TEMPORARY_TEXT ( latest )
+ DocumentationInMarkdown::number_headings_r ( tree , & section_number , & chapter_number , latest );
+ DISCARD_TEXT ( latest )
+}
+
+void DocumentationInMarkdown::Inform_headings_r ( markdown_item * md , int * example_number ) {
+ if ( md -> type == PARAGRAPH_MIT ) {
+ text_stream * line = md -> stashed ;
+ match_results mr = Regexp::create_mr ();
+ if (( Regexp::match (& mr , line , L "Section *: *(%c+?)" )) ||
+ ( Regexp::match (& mr , line , L "Section *- *(%c+?)" ))) {
+ MDBlockParser::change_type ( NULL , md , HEADING_MIT );
+ Markdown::set_heading_level ( md , 2 );
+ Str::clear ( line );
+ WRITE_TO ( line , "%S" , mr . exp [0]);
+ } else if (( Regexp::match (& mr , line , L "Chapter *: *(%c+?)" )) ||
+ ( Regexp::match (& mr , line , L "Chapter *- *(%c+?)" ))) {
+ MDBlockParser::change_type ( NULL , md , HEADING_MIT );
+ Markdown::set_heading_level ( md , 1 );
+ Str::clear ( line );
+ WRITE_TO ( line , "%S" , mr . exp [0]);
+ } else if (( Regexp::match (& mr , line , L "Example *: *(%**) *(%c+?)" )) ||
+ ( Regexp::match (& mr , line , L "Example *- *(%**) *(%c+?)" ))) {
+ MDBlockParser::change_type ( NULL , md , INFORM_EXAMPLE_HEADING_MIT );
+ int star_count = Str::len ( mr . exp [0]);
+ cdoc_example * new_eg = DocumentationCompiler::new_example_alone ( mr . exp [1], NULL ,
+ star_count , ++(* example_number ));
+ if ( star_count == 0 ) {
+ markdown_item * E = DocumentationInMarkdown::error_item (
+ I "this example should be marked (before the title) '*', '**', '***' or '****' for difficulty" );
+ E -> next = md -> next ; md -> next = E ;
+ }
+ if ( star_count > 4 ) {
+ markdown_item * E = DocumentationInMarkdown::error_item (
+ I "four stars '****' is the maximum difficulty rating allowed" );
+ E -> next = md -> next ; md -> next = E ;
+ }
+ md -> user_state = STORE_POINTER_cdoc_example ( new_eg );
+ }
+ Regexp::dispose_of (& mr );
+ }
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ DocumentationInMarkdown::Inform_headings_r ( ch , example_number );
+ }
+}
+
+markdown_item * DocumentationInMarkdown::error_item ( text_stream * text ) {
+ markdown_item * E = Markdown::new_item ( INFORM_ERROR_MARKER_MIT );
+ E -> stashed = Str::duplicate ( text );
+ return E ;
+}
+
+
+
+
+void DocumentationInMarkdown::regroup_examples_r ( markdown_item * md , int * example_number ) {
+ if ( md -> type == INFORM_EXAMPLE_HEADING_MIT ) {
+ if ( md -> down == NULL ) {
+ markdown_item * run_from = md -> next ;
+ if ( run_from ) {
+ markdown_item * run_to = run_from , * prev = NULL ;
+ while ( run_to ) {
+ if ( run_to -> type == INFORM_EXAMPLE_HEADING_MIT ) break ;
+ if (( run_to -> type == HEADING_MIT ) && ( Markdown::get_heading_level ( run_to ) <= 2 )) break ;
+ prev = run_to ;
+ run_to = run_to -> next ;
+ }
+ if ( prev ) {
+ md -> down = run_from ; md -> next = run_to ; prev -> next = NULL ;
+ }
+ }
+ }
+ }
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ DocumentationInMarkdown::regroup_examples_r ( ch , example_number );
+ }
+}
+
+
+
+
+void DocumentationInMarkdown::number_headings_r ( markdown_item * md ,
+ int * section_number , int * chapter_number , text_stream * latest ) {
+ if ( md -> type == HEADING_MIT ) {
+ switch ( Markdown::get_heading_level ( md )) {
+ case 1 : {
+ md -> user_state = STORE_POINTER_text_stream ( md -> stashed );
+ (* chapter_number )++;
+ (* section_number ) = 0 ;
+ Str::clear ( latest );
+ WRITE_TO ( latest , "Chapter %d: %S" , * chapter_number , md -> stashed );
+ md -> stashed = Str::duplicate ( latest );
+ text_stream * url = Str::new ();
+ WRITE_TO ( url , "chapter%d.html" , * chapter_number );
+ md -> user_state = STORE_POINTER_text_stream ( url );
+ break ;
+ }
+ case 2 : {
+ md -> user_state = STORE_POINTER_text_stream ( md -> stashed );
+ (* section_number )++;
+ Str::clear ( latest );
+ WRITE_TO ( latest , "Section " );
+ if (* chapter_number > 0 ) WRITE_TO ( latest , "%d." , * chapter_number );
+ WRITE_TO ( latest , "%d: %S" , * section_number , md -> stashed );
+ md -> stashed = Str::duplicate ( latest );
+ text_stream * url = Str::new ();
+ if (* chapter_number > 0 )
+ WRITE_TO ( url , "chapter%d.html" , * chapter_number );
+ WRITE_TO ( url , "#section%d" , * section_number );
+ md -> user_state = STORE_POINTER_text_stream ( url );
+ break ;
+ }
+ }
+ }
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ DocumentationInMarkdown::number_headings_r ( ch , section_number , chapter_number , latest );
+ }
+}
+
+void DocumentationInMarkdown::paste_icons_intervene_after_Phase_I ( markdown_feature * feature ,
+ markdown_item * tree , md_links_dictionary * link_references ) {
+ DocumentationInMarkdown::paiapi_r ( tree );
+}
+
+void DocumentationInMarkdown::paiapi_r ( markdown_item * md ) {
+ markdown_item * current_sample = NULL ;
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ if (( ch -> type == CODE_BLOCK_MIT ) && ( Str::prefix_eq ( ch -> stashed , I "{*}" , 3 ))) {
+ ch -> user_state = STORE_POINTER_markdown_item ( ch );
+ current_sample = ch ;
+ Str::delete_first_character ( ch -> stashed );
+ Str::delete_first_character ( ch -> stashed );
+ Str::delete_first_character ( ch -> stashed );
+ } else if (( ch -> type == CODE_BLOCK_MIT ) &&
+ ( Str::prefix_eq ( ch -> stashed , I "{**}" , 3 )) && ( current_sample )) {
+ ch -> user_state = STORE_POINTER_markdown_item ( current_sample );
+ Str::delete_first_character ( ch -> stashed );
+ Str::delete_first_character ( ch -> stashed );
+ Str::delete_first_character ( ch -> stashed );
+ Str::delete_first_character ( ch -> stashed );
+ }
+ DocumentationInMarkdown::paiapi_r ( ch );
+ if ( ch -> type == CODE_BLOCK_MIT ) {
+ TEMPORARY_TEXT ( detabbed )
+ for ( int i =0, margin =0; i <Str::len(ch-> stashed ); i ++) {
+ wchar_t c = Str::get_at ( ch -> stashed , i );
+ if ( c == '\t' ) {
+ PUT_TO ( detabbed , ' ' ); margin ++;
+ while ( margin % 4 != 0 ) { PUT_TO ( detabbed , ' ' ); margin ++; }
+ } else {
+ PUT_TO ( detabbed , c ); margin ++;
+ if ( c == '\n' ) margin = 0 ;
+ }
+ }
+ Str::clear ( ch -> stashed );
+ WRITE_TO ( ch -> stashed , "%S" , detabbed );
+ DISCARD_TEXT ( detabbed );
+ }
+ }
+}
+
+int DocumentationInMarkdown::paste_icons_renderer ( markdown_feature * feature , text_stream * OUT ,
+ markdown_item * md , int mode ) {
+ if ( md -> type == HEADING_MIT ) {
+ int L = Markdown::get_heading_level ( md );
+ switch ( L ) {
+ case 1 : HTML_OPEN ( "h2" ); break ;
+ case 2 : HTML_OPEN ( "h3" ); break ;
+ case 3 : HTML_OPEN ( "h4" ); break ;
+ case 4 : HTML_OPEN ( "h5" ); break ;
+ default: HTML_OPEN ( "h6" ); break ;
+ }
+ TEMPORARY_TEXT ( anchor )
+ if ( L <= 2 ) {
+ text_stream * url = RETRIEVE_POINTER_text_stream ( md -> user_state );
+ for ( int i =0; i < Str::len ( url ); i ++)
+ if ( Str::get_at ( url , i ) == '#' )
+ for ( i ++; i < Str::len ( url ); i ++)
+ PUT_TO ( anchor , Str::get_at ( url , i ));
+ }
+ if ( Str::len ( anchor ) > 0 ) {
+ HTML_OPEN_WITH ( "span" , "id=%S" , anchor );
+ } else {
+ HTML_OPEN ( "span" );
+ }
+ DISCARD_TEXT ( anchor )
+ Markdown::render_extended ( OUT , md -> down , DocumentationInMarkdown::extension_flavoured_Markdown ());
+ HTML_CLOSE ( "span" );
+ switch ( L ) {
+ case 1 : HTML_CLOSE ( "h2" ); break ;
+ case 2 : HTML_CLOSE ( "h3" ); break ;
+ case 3 : HTML_CLOSE ( "h4" ); break ;
+ case 4 : HTML_CLOSE ( "h5" ); break ;
+ default: HTML_CLOSE ( "h6" ); break ;
+ }
+ return TRUE ;
+ }
+ if ( md -> type == INFORM_EXAMPLE_HEADING_MIT ) {
+ cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( md -> user_state );
+ DocumentationInMarkdown::render_example_heading ( OUT , E , NULL );
+ return TRUE ;
+ }
+ if ( md -> type == CODE_BLOCK_MIT ) {
+ DocumentationInMarkdown::render_code_block ( OUT , md , mode );
+ return TRUE ;
+ }
+ if ( md -> type == INFORM_ERROR_MARKER_MIT ) {
+ HTML_OPEN_WITH ( "p" , "class=\"documentationerrorbox\"" );
+ HTML::begin_span ( OUT , I "documentationerror" );
+ WRITE ( "Error: %S" , md -> stashed );
+ HTML_CLOSE ( "span" );
+ HTML_CLOSE ( "p" );
+ return TRUE ;
+ }
+ return FALSE ;
+}
+
+
+
+
+void DocumentationInMarkdown::render_example_heading ( OUTPUT_STREAM , cdoc_example * E ,
+ markdown_item * passage_node ) {
+ TEMPORARY_TEXT ( link )
+ WRITE_TO ( link , "style=\"text-decoration: none\" href=\"eg%d.html\"" , E -> number );
+
+ HTML_TAG ( "hr" );
+ HTML::begin_plain_html_table ( OUT );
+ HTML_OPEN ( "tr" );
+
+
+ HTML_OPEN_WITH ( "td" , "halign=\"left\" valign=\"top\" cellpadding=0 cellspacing=0 width=38px" );
+ HTML_OPEN_WITH ( "span" , "id=eg%d" , E -> number );
+ Typeset the lettered oval example icon 5.1 ;
+ HTML_CLOSE ( "span" );
+ HTML_CLOSE ( "td" );
+
+
+ HTML_OPEN_WITH ( "td" , "cellpadding=0 cellspacing=0 halign=\"left\" valign=\"top\"" );
+
+ if ( passage_node == NULL ) HTML_OPEN_WITH ( "a" , "%S" , link );
+ for ( int asterisk = 0 ; asterisk < E -> star_count ; asterisk ++)
+ PUT ( 0x2605 );
+
+
+ WRITE ( " " );
+ HTML_OPEN ( "b" );
+ HTML::begin_span ( OUT , I "indexdarkgrey" );
+ WRITE ( " Example " );
+ HTML::end_span ( OUT );
+ HTML::begin_span ( OUT , I "indexblack" );
+ DocumentationRenderer::render_text ( OUT , E -> name );
+ HTML_TAG ( "br" );
+ DocumentationRenderer::render_text ( OUT , E -> description );
+ HTML::end_span ( OUT );
+ HTML_CLOSE ( "b" );
+
+ if ( passage_node == NULL ) HTML_CLOSE ( "a" );
+
+ if ( passage_node ) {
+ while ( passage_node ) {
+ Markdown::render_extended ( OUT , passage_node ,
+ DocumentationInMarkdown::extension_flavoured_Markdown ());
+ passage_node = passage_node -> next ;
+ }
+ }
+
+ HTML_CLOSE ( "td" );
+ HTML_CLOSE ( "tr" );
+ HTML::end_html_table ( OUT );
+
+ DISCARD_TEXT ( link )
+}
+
+
+
+
+
+
+ HTML::begin_plain_html_table ( OUT );
+ HTML_OPEN_WITH ( "tr" , "class=\"oval\"" );
+ HTML_OPEN_WITH ( "td" , "width=38px height=30px align=\"left\" valign=\"center\"" );
+ if ( passage_node == NULL ) HTML_OPEN_WITH ( "a" , "%S" , link );
+ HTML_OPEN_WITH ( "div" ,
+ "class=\"paragraph Body\" style=\"line-height: 1px; margin-bottom: 0px; "
+ "margin-top: 0px; padding-bottom: 0pt; padding-top: 0px; text-align: center;\"" );
+ HTML::begin_span ( OUT , I "extensionexampleletter" );
+ PUT ( E -> letter );
+ HTML::end_span ( OUT );
+ HTML_CLOSE ( "div" );
+ if ( passage_node == NULL ) HTML_CLOSE ( "a" );
+ HTML_CLOSE ( "td" );
+ HTML_CLOSE ( "tr" );
+ HTML::end_html_table ( OUT );
+
+
+
+
+
+markdown_item * DocumentationInMarkdown::find_section ( markdown_item * tree , text_stream * name ) {
+ if ( Str::len ( name ) == 0 ) return NULL ;
+ markdown_item * result = NULL ;
+ DocumentationInMarkdown::find ( tree , name , & result );
+ return result ;
+}
+
+void DocumentationInMarkdown::find ( markdown_item * md , text_stream * name , markdown_item ** result ) {
+ if ( md -> type == HEADING_MIT ) {
+ switch ( Markdown::get_heading_level ( md )) {
+ case 1 :
+ case 2 : {
+ int i =0;
+ for (; i <Str::len(md-> stashed ); i ++)
+ if ( Str::get_at ( md -> stashed , i ) == ':' ) { i +=2; break ; }
+ if ( i + Str::len ( name ) == Str::len ( md -> stashed )) {
+ int fail = FALSE ;
+ for ( int j =0; j < Str::len ( name ); j ++, i ++)
+ if ( Str::get_at ( name , j ) != Str::get_at ( md -> stashed , i )) { fail = TRUE ; break ; }
+ if (( fail == FALSE ) && (* result == NULL )) * result = md ;
+ }
+ break ;
+ }
+ }
+ }
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ DocumentationInMarkdown::find ( ch , name , result );
+ }
+}
+
+
+
+
+markdown_item * DocumentationInMarkdown::find_example ( markdown_item * tree , int eg ) {
+ if ( eg <= 0 ) return NULL ;
+ markdown_item * result = NULL ;
+ int counter = 0 ;
+ DocumentationInMarkdown::find_e ( tree , eg , & result , & counter );
+ return result ;
+}
+
+void DocumentationInMarkdown::find_e ( markdown_item * md , int eg , markdown_item ** result , int * counter ) {
+ if ( md -> type == INFORM_EXAMPLE_HEADING_MIT ) {
+ (* counter )++;
+ if (* counter == eg ) * result = md ;
+ }
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next ) {
+ DocumentationInMarkdown::find_e ( ch , eg , result , counter );
+ }
+}
+
+void DocumentationInMarkdown::render_code_block ( OUTPUT_STREAM , markdown_item * md , int mode ) {
+ if (( Str::eq_insensitive ( md -> info_string , I "inform" )) ||
+ ( Str::eq_insensitive ( md -> info_string , I "inform7" )) ||
+ ( Str::len ( md -> info_string ) == 0 )) {
+ Render as Inform 7 source text 7.2 ;
+ } else {
+ programming_language * pl = NULL ;
+
+ if ( mode & TAGS_MDRMODE ) HTML_OPEN ( "pre" );
+ TEMPORARY_TEXT ( language )
+ for ( int i =0; i <Str::len(md-> info_string ); i ++) {
+ wchar_t c = Str::get_at ( md -> info_string , i );
+ if (( c == ' ' ) || ( c == '\t' )) break ;
+ PUT_TO ( language , c );
+ }
+ if ( Str::len ( language ) > 0 ) {
+ TEMPORARY_TEXT ( language_rendered )
+ md -> sliced_from = language ;
+ md -> from = 0 ; md -> to = Str::len ( language ) - 1 ;
+ MDRenderer::slice ( language_rendered , md , mode | ENTITIES_MDRMODE );
+ if ( mode & TAGS_MDRMODE )
+ HTML_OPEN_WITH ( "code" , "class=\"language-%S\"" , language_rendered );
+ pl = DocumentationCompiler::get_language ( language_rendered );
+ if ( pl == NULL ) LOG ( "Unable to find language <%S>\n" , language_rendered );
+ DISCARD_TEXT ( language_rendered )
+ } else {
+ if ( mode & TAGS_MDRMODE ) HTML_OPEN ( "code" );
+ }
+ DISCARD_TEXT ( language )
+
+ Painter::reset_syntax_colouring ( pl );
+ TEMPORARY_TEXT ( line )
+ TEMPORARY_TEXT ( line_colouring )
+ for ( int k =0; k <Str::len(md-> stashed ); k ++) {
+ if ( Str::get_at ( md -> stashed , k ) == '\n' ) {
+ Render line as code 7.1 ;
+ Str::clear ( line );
+ Str::clear ( line_colouring );
+ } else {
+ PUT_TO ( line , Str::get_at ( md -> stashed , k ));
+ }
+ if (( k == Str::len ( md -> stashed ) - 1 ) && ( Str::len ( line ) > 0 )) Render line as code 7.1 ;
+ }
+ HTML_CLOSE ( "span" );
+ DISCARD_TEXT ( line )
+ DISCARD_TEXT ( line_colouring )
+ if ( mode & TAGS_MDRMODE ) HTML_CLOSE ( "code" );
+ if ( mode & TAGS_MDRMODE ) HTML_CLOSE ( "pre" );
+ }
+}
+
+
+
+
+ if ( pl ) Painter::syntax_colour ( pl , NULL , line , line_colouring , FALSE );
+ DocumentationInMarkdown::syntax_coloured_code ( OUT , line , line_colouring ,
+ 0 , Str::len ( line ), mode );
+ if ( mode & TAGS_MDRMODE ) WRITE ( "<br>" ); else WRITE ( " " );
+
+This code is used in §7 (twice).
+
+
+
+ HTML_OPEN ( "blockquote" );
+ if ( GENERAL_POINTER_IS_NULL ( md -> user_state ) == FALSE ) {
+ markdown_item * first = RETRIEVE_POINTER_markdown_item ( md -> user_state );
+ TEMPORARY_TEXT ( accumulated )
+ for ( markdown_item * ch = md ; ch ; ch = ch -> next ) {
+ if ( ch -> type == CODE_BLOCK_MIT ) {
+ if ( GENERAL_POINTER_IS_NULL ( ch -> user_state ) == FALSE ) {
+ markdown_item * latest = RETRIEVE_POINTER_markdown_item ( ch -> user_state );
+ if ( first == latest ) WRITE_TO ( accumulated , "%S" , ch -> stashed );
+ }
+ }
+ }
+ ExtensionWebsite::paste_button ( OUT , accumulated );
+ }
+ TEMPORARY_TEXT ( colouring )
+ programming_language * default_language = DocumentationCompiler::get_language ( I "Inform" );
+ programming_language * pl = default_language ;
+ if ( pl ) {
+ Painter::reset_syntax_colouring ( pl );
+ Painter::syntax_colour ( pl , NULL , md -> stashed , colouring , FALSE );
+ if ( Str::eq ( pl -> language_name , I "Inform" )) {
+ int ts = FALSE ;
+ for ( int i =0; i < Str::len ( colouring ); i ++) {
+ if ( Str::get_at ( colouring , i ) == STRING_COLOUR ) {
+ wchar_t c = Str::get_at ( md -> stashed , i );
+ if ( c == '[' ) ts = TRUE ;
+ if ( ts ) Str::put_at ( colouring , i , EXTRACT_COLOUR );
+ if ( c == ']' ) ts = FALSE ;
+ } else ts = FALSE ;
+ }
+ }
+ }
+ HTML::begin_span ( OUT , I "indexdullblue" );
+ int tabulating = FALSE , tabular = FALSE , line_count = 0 ;
+ TEMPORARY_TEXT ( line )
+ TEMPORARY_TEXT ( line_colouring )
+ for ( int k =0; k <Str::len(md-> stashed ); k ++) {
+ if ( Str::get_at ( md -> stashed , k ) == '\n' ) {
+ Render line 7.2.1 ;
+ Str::clear ( line );
+ Str::clear ( line_colouring );
+ } else {
+ PUT_TO ( line , Str::get_at ( md -> stashed , k ));
+ PUT_TO ( line_colouring , Str::get_at ( colouring , k ));
+ }
+ if ( k == Str::len ( md -> stashed ) - 1 ) Render line 7.2.1 ;
+ }
+ HTML_CLOSE ( "span" );
+ if ( tabulating ) End I7 table in extension documentation 7.2.2 ;
+ HTML_CLOSE ( "blockquote" );
+ DISCARD_TEXT ( line )
+ DISCARD_TEXT ( line_colouring )
+
+
+
+
+
+ line_count ++;
+ if ( Str::is_whitespace ( line )) tabular = FALSE ;
+ match_results mr = Regexp::create_mr ();
+ if ( Regexp::match (& mr , line , L "Table %c*" )) tabular = TRUE ;
+ Regexp::dispose_of (& mr );
+ if ( tabular ) {
+ if ( tabulating ) {
+ Begin new row of I7 table in extension documentation 7.2.1.4 ;
+ } else {
+ Begin I7 table in extension documentation 7.2.1.1 ;
+ tabulating = TRUE ;
+ }
+ int cell_from = 0 , cell_to = 0 , i = 0 ;
+ Begin table cell for I7 table in extension documentation 7.2.1.3 ;
+ for (; i < Str::len ( line ); i ++) {
+ if ( Str::get_at ( line , i ) == '\t' ) {
+ End table cell for I7 table in extension documentation 7.2.1.2 ;
+ while ( Str::get_at ( line , i ) == '\t' ) i ++;
+ Begin table cell for I7 table in extension documentation 7.2.1.3 ;
+ i --;
+ } else {
+ cell_to ++;
+ }
+ }
+ End table cell for I7 table in extension documentation 7.2.1.2 ;
+ End row of I7 table in extension documentation 7.2.1.5 ;
+ } else {
+ if ( line_count > 1 ) HTML_TAG ( "br" );
+ if ( tabulating ) {
+ End I7 table in extension documentation 7.2.2 ;
+ tabulating = FALSE ;
+ }
+ int indentation = 1 ;
+ int z =0, spaces = 0 ;
+ for (; z < Str::len ( line ); z ++)
+ if ( Str::get_at ( line , z ) == ' ' ) { spaces ++; if ( spaces == 4 ) { indentation ++; spaces = 0 ; } }
+ else if ( Str::get_at ( line , z ) == '\t' ) { indentation ++; spaces = 0 ; }
+ else break ;
+ for ( int n =0; n < indentation ; n ++) WRITE ( " " );
+ DocumentationInMarkdown::syntax_coloured_code ( OUT , line , line_colouring ,
+ z , Str::len ( line ), mode );
+ }
+ WRITE ( "\n" );
+
+This code is used in §7.2 (twice).
+
+
+
+
+
+ HTML::end_span ( OUT );
+ HTML_TAG ( "br" );
+ HTML::begin_plain_html_table ( OUT );
+ HTML::first_html_column ( OUT , 0 );
+
+This code is used in §7.2.1 .
+
+
+
+ DocumentationInMarkdown::syntax_coloured_code ( OUT , line , line_colouring ,
+ cell_from , cell_to , mode );
+ HTML::end_span ( OUT );
+ HTML::next_html_column ( OUT , 0 );
+
+This code is used in §7.2.1 (twice).
+
+
+
+ cell_from = i ; cell_to = cell_from ;
+ HTML::begin_span ( OUT , I "indexdullblue" );
+
+This code is used in §7.2.1 (twice).
+
+
+
+ HTML::first_html_column ( OUT , 0 );
+
+This code is used in §7.2.1 .
+
+
+
+ HTML::end_html_row ( OUT );
+
+This code is used in §7.2.1 .
+
+
+
+ HTML::end_html_table ( OUT );
+ HTML::begin_span ( OUT , I "indexdullblue" );
+
+This code is used in §7.2 , §7.2.1 .
+
+
+
+void DocumentationInMarkdown::syntax_coloured_code ( OUTPUT_STREAM , text_stream * text ,
+ text_stream * colouring , int from , int to , int mode ) {
+ wchar_t current_col = 0 ;
+ for ( int i = from ; i < to ; i ++) {
+ wchar_t c = Str::get_at ( text , i );
+ wchar_t col = Str::get_at ( colouring , i );
+ if ( col != current_col ) {
+ if ( current_col ) HTML_CLOSE ( "span" );
+ text_stream * span_class = NULL ;
+ switch ( col ) {
+ case DEFINITION_COLOUR: span_class = I "syntaxdefinition" ; break ;
+ case FUNCTION_COLOUR: span_class = I "syntaxfunction" ; break ;
+ case RESERVED_COLOUR: span_class = I "syntaxreserved" ; break ;
+ case ELEMENT_COLOUR: span_class = I "syntaxelement" ; break ;
+ case IDENTIFIER_COLOUR: span_class = I "syntaxidentifier" ; break ;
+ case CHARACTER_COLOUR: span_class = I "syntaxcharacter" ; break ;
+ case CONSTANT_COLOUR: span_class = I "syntaxconstant" ; break ;
+ case STRING_COLOUR: span_class = I "syntaxstring" ; break ;
+ case PLAIN_COLOUR: span_class = I "syntaxplain" ; break ;
+ case EXTRACT_COLOUR: span_class = I "syntaxextract" ; break ;
+ case COMMENT_COLOUR: span_class = I "syntaxcomment" ; break ;
+ }
+ HTML_OPEN_WITH ( "span" , "class=\"%S\"" , span_class );
+ current_col = col ;
+ }
+ MDRenderer::char ( OUT , c , mode );
+ }
+ if ( current_col ) HTML_CLOSE ( "span" );
+}
+
+
+
+
+
+
+
+
diff --git a/docs/supervisor-module/7-dr.html b/docs/supervisor-module/7-dr.html
index e11e33290..f76475b09 100644
--- a/docs/supervisor-module/7-dr.html
+++ b/docs/supervisor-module/7-dr.html
@@ -59,60 +59,16 @@ function togglePopup(material_id) {
To render a passage of extension documentation as HTML.
-
+
-
-
-
-void DocumentationRenderer::as_plain_text ( text_stream * OUT , heterogeneous_tree * T ) {
- WRITE ( "%S\n" , T -> type -> name );
- WRITE ( "--------\n" );
- INDENT ;
- Trees::traverse_from ( T -> root , & DocumentationRenderer::textual_visit , ( void *) DL , 0 );
- OUTDENT ;
- WRITE ( "--------\n" );
-}
-
-int DocumentationRenderer::textual_visit ( tree_node * N , void * state , int L ) {
- text_stream * OUT = ( text_stream *) state ;
- for ( int i =0; i < L ; i ++) WRITE ( " " );
- if ( N -> type == heading_TNT ) {
- cdoc_heading * H = RETRIEVE_POINTER_cdoc_heading ( N -> content );
- WRITE ( "Heading H%d level %d: '%S - %S'\n" , H -> ID , H -> level , H -> count , H -> name );
- } else if ( N -> type == example_TNT ) {
- cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( N -> content );
- WRITE ( "Example %c: '%S' (%d star(s))\n" , E -> letter , E -> name , E -> star_count );
- } else if ( N -> type == phrase_defn_TNT ) {
- cdoc_phrase_defn * E = RETRIEVE_POINTER_cdoc_phrase_defn ( N -> content );
- WRITE ( "Phrase definition (tag '%S') [ %S ]\n" , E -> tag , E -> prototype );
- } else if ( N -> type == passage_TNT ) {
- WRITE ( "Passage\n" );
- } else if ( N -> type == paragraph_TNT ) {
- cdoc_paragraph * E = RETRIEVE_POINTER_cdoc_paragraph ( N -> content );
- WRITE ( "Paragraph: %d chars\n" , Str::len ( E -> content ));
- for ( int i =0; i < L +1; i ++) { INDENT ; }
- WRITE ( "%S\n" , E -> content );
- for ( int i =0; i < L +1; i ++) { OUTDENT ; }
- } else if ( N -> type == code_sample_TNT ) {
- WRITE ( "Code sample\n" );
- } else if ( N -> type == code_line_TNT ) {
- cdoc_code_line * E = RETRIEVE_POINTER_cdoc_code_line ( N -> content );
- WRITE ( "Code line: " );
- for ( int i =0; i <E-> indentation ; i ++) WRITE ( " " );
- WRITE ( "%S\n" , E -> content );
- } else WRITE ( "Unknown node\n" );
- return TRUE ;
-}
-
-
text_stream DOCF_struct ;
text_stream * DOCF = NULL ;
-text_stream * DocumentationRenderer::open_subpage ( pathname * P , text_stream * leaf ) {
+text_stream * DocumentationRenderer::open_subpage ( pathname * P , text_stream * leaf ) {
if ( P == NULL ) return STDOUT ;
if ( DOCF ) internal_error ( "nested DC writes" );
filename * F = Filenames::in ( P , leaf );
@@ -126,74 +82,73 @@ function togglePopup(material_id) {
return DOCF ;
}
-void DocumentationRenderer::close_subpage ( void ) {
+void DocumentationRenderer::close_subpage ( void ) {
if ( DOCF == NULL ) internal_error ( "no DC page open" );
if ( DOCF != STDOUT ) STREAM_CLOSE ( DOCF );
DOCF = NULL ;
}
-
void DocumentationRenderer::as_HTML ( pathname * P , compiled_documentation * cd , text_stream * extras ) {
if ( cd ) {
- text_stream * OUT = DocumentationRenderer::open_subpage ( P , I "index.html" );
+ text_stream * OUT = DocumentationRenderer::open_subpage ( P , I "index.html" );
if ( OUT ) {
- DocumentationRenderer::render_index_page ( OUT , cd , extras );
- DocumentationRenderer::close_subpage ();
+ DocumentationRenderer::render_index_page ( OUT , cd , extras );
+ DocumentationRenderer::close_subpage ();
}
for ( int eg =1; eg <=cd-> total_examples ; eg ++) {
TEMPORARY_TEXT ( leaf )
WRITE_TO ( leaf , "eg%d.html" , eg );
- OUT = DocumentationRenderer::open_subpage ( P , leaf );
+ OUT = DocumentationRenderer::open_subpage ( P , leaf );
if ( OUT ) {
- DocumentationRenderer::render_example_page ( OUT , cd , eg );
- DocumentationRenderer::close_subpage ();
+ DocumentationRenderer::render_example_page ( OUT , cd , eg );
+ DocumentationRenderer::close_subpage ();
}
DISCARD_TEXT ( leaf )
}
for ( int ch =1; ch <=cd-> total_headings [1]; ch ++) {
TEMPORARY_TEXT ( leaf )
WRITE_TO ( leaf , "chapter%d.html" , ch );
- OUT = DocumentationRenderer::open_subpage ( P , leaf );
+ OUT = DocumentationRenderer::open_subpage ( P , leaf );
if ( OUT ) {
- DocumentationRenderer::render_chapter_page ( OUT , cd , ch );
- DocumentationRenderer::close_subpage ();
+ DocumentationRenderer::render_chapter_page ( OUT , cd , ch );
+ DocumentationRenderer::close_subpage ();
}
DISCARD_TEXT ( leaf )
}
}
}
-
+
-void DocumentationRenderer::render_index_page ( OUTPUT_STREAM , compiled_documentation * cd ,
+void DocumentationRenderer::render_index_page ( OUTPUT_STREAM , compiled_documentation * cd ,
text_stream * extras ) {
- DocumentationRenderer::render_header ( OUT , cd -> title , NULL , cd -> within_extension );
+ DocumentationRenderer::render_header ( OUT , cd -> title , NULL , cd -> within_extension );
if ( cd -> associated_extension ) {
- DocumentationRenderer::render_extension_details ( OUT , cd -> associated_extension );
+ DocumentationRenderer::render_extension_details ( OUT , cd -> associated_extension );
}
HTML_TAG ( "hr" );
if ( cd -> total_headings [1] > 0 ) {
- DocumentationRenderer::render_toc ( OUT , cd );
+ DocumentationRenderer::render_toc ( OUT , cd );
HTML_OPEN ( "em" );
- DocumentationRenderer::render_text ( OUT , I "Click on Chapter, Section or Example numbers to read" );
+ DocumentationRenderer::render_text ( OUT , I "Click on Chapter, Section or Example numbers to read" );
HTML_CLOSE ( "em" );
- if ( cd -> tree -> root -> child -> type == passage_TNT ) {
+ markdown_item * md = cd -> alt_tree -> down ;
+ if (( md ) && (( md -> type != HEADING_MIT ) || ( Markdown::get_heading_level ( md ) > 1 ))) {
HTML_TAG ( "hr" );
HTML_OPEN_WITH ( "p" , "class=\"extensionsubheading\"" );
WRITE ( "introduction" );
HTML_CLOSE ( "p" );
- for ( tree_node * C = cd -> tree -> root -> child ; C ; C = C -> next ) {
- if ( C -> type == heading_TNT ) {
- cdoc_heading * E = RETRIEVE_POINTER_cdoc_heading ( C -> content );
- if ( E -> level == 1 ) break ;
- }
- DocumentationRenderer::render_body ( OUT , cd , C );
+ for ( markdown_item * md = cd -> alt_tree -> down ; md ; md = md -> next ) {
+ if (( md -> type == HEADING_MIT ) && ( Markdown::get_heading_level ( md ) == 1 ))
+ break ;
+ Markdown::render_extended ( OUT , md , DocumentationInMarkdown::extension_flavoured_Markdown ());
}
}
} else {
@@ -202,22 +157,25 @@ except the examples, and then up to 26 pages holding the content of examples A t
HTML_CLOSE ( "p" );
if ( cd -> empty ) {
HTML_OPEN ( "p" );
- DocumentationRenderer::render_text ( OUT , I "None is provided." );
+ DocumentationRenderer::render_text ( OUT , I "None is provided." );
HTML_CLOSE ( "p" );
} else {
- DocumentationRenderer::render_body ( OUT , cd , cd -> tree -> root );
+ HTML_OPEN_WITH ( "div" , "class=\"markdowncontent\"" );
+ Markdown::render_extended ( OUT , cd -> alt_tree ,
+ DocumentationInMarkdown::extension_flavoured_Markdown ());
+ HTML_CLOSE ( "div" );
}
}
WRITE ( "%S" , extras );
- Enter the small print 4.1 ;
+ Enter the small print 3.1 ;
WRITE ( "These documentation pages are first generated when an extension is "
"installed, and refreshed each time the project successfully translates." );
- Exit the small print 4.2 ;
- DocumentationRenderer::render_footer ( OUT );
+ Exit the small print 3.2 ;
+ DocumentationRenderer::render_footer ( OUT );
}
-
@@ -225,34 +183,34 @@ except the examples, and then up to 26 pages holding the content of examples A t
HTML_OPEN ( "p" )
HTML_OPEN ( "em" );
-This code is used in §4 , §5 , §8 .
-This code is used in §3 , §4 , §7 .
+
HTML_CLOSE ( "em" );
HTML_CLOSE ( "p" );
-This code is used in §4 , §5 , §8 .
-
+This code is used in §3 , §4 , §7 .
+
-void DocumentationRenderer::render_example_page ( OUTPUT_STREAM , compiled_documentation * cd , int eg ) {
+void DocumentationRenderer::render_example_page ( OUTPUT_STREAM , compiled_documentation * cd , int eg ) {
TEMPORARY_TEXT ( title )
WRITE_TO ( title , "Example %c" , 'A' + eg - 1 );
- DocumentationRenderer::render_header ( OUT , cd -> title , title , cd -> within_extension );
+ DocumentationRenderer::render_header ( OUT , cd -> title , title , cd -> within_extension );
DISCARD_TEXT ( title )
- DocumentationRenderer::render_example ( OUT , cd , eg );
- DocumentationRenderer::render_footer ( OUT );
+ DocumentationRenderer::render_example ( OUT , cd , eg );
+ DocumentationRenderer::render_footer ( OUT );
}
-void DocumentationRenderer::render_chapter_page ( OUTPUT_STREAM , compiled_documentation * cd , int ch ) {
+void DocumentationRenderer::render_chapter_page ( OUTPUT_STREAM , compiled_documentation * cd , int ch ) {
TEMPORARY_TEXT ( title )
WRITE_TO ( title , "Chapter %d" , ch );
- DocumentationRenderer::render_header ( OUT , cd -> title , title , cd -> within_extension );
+ DocumentationRenderer::render_header ( OUT , cd -> title , title , cd -> within_extension );
DISCARD_TEXT ( title )
- DocumentationRenderer::render_chapter ( OUT , cd , ch );
- Enter the small print 4.1 ;
+ DocumentationRenderer::render_chapter ( OUT , cd , ch );
+ Enter the small print 3.1 ;
WRITE ( "This is Chapter %d of %d" , ch , cd -> total_headings [1]);
if ( ch > 1 ) {
WRITE ( " • " );
@@ -266,15 +224,15 @@ except the examples, and then up to 26 pages holding the content of examples A t
WRITE ( "Chapter %d" , ch +1);
HTML_CLOSE ( "a" );
}
- Exit the small print 4.2 ;
- DocumentationRenderer::render_footer ( OUT );
+ Exit the small print 3.2 ;
+ DocumentationRenderer::render_footer ( OUT );
}
-
-void DocumentationRenderer::render_header ( OUTPUT_STREAM , text_stream * title , text_stream * ptitle ,
+void DocumentationRenderer::render_header ( OUTPUT_STREAM , text_stream * title , text_stream * ptitle ,
inform_extension * within ) {
InformPages::header ( OUT , title , JAVASCRIPT_FOR_ONE_EXTENSION_IRES , NULL );
ExtensionWebsite::add_home_breadcrumb ( NULL );
@@ -288,16 +246,16 @@ except the examples, and then up to 26 pages holding the content of examples A t
I "Documentation provided by the extension author" );
}
-void DocumentationRenderer::render_footer ( OUTPUT_STREAM ) {
+void DocumentationRenderer::render_footer ( OUTPUT_STREAM ) {
InformPages::footer ( OUT );
}
-
-void DocumentationRenderer::render_extension_details ( OUTPUT_STREAM , inform_extension * E ) {
+void DocumentationRenderer::render_extension_details ( OUTPUT_STREAM , inform_extension * E ) {
inbuild_edition * edition = E -> as_copy -> edition ;
inbuild_work * work = edition -> work ;
@@ -316,14 +274,14 @@ extension.
if ( Str::len ( E -> rubric_as_lexed ) > 0 ) {
HTML_OPEN ( "p" );
- DocumentationRenderer::render_text ( OUT , E -> rubric_as_lexed );
+ DocumentationRenderer::render_text ( OUT , E -> rubric_as_lexed );
HTML_CLOSE ( "p" );
}
if ( Str::len ( E -> extra_credit_as_lexed ) > 0 ) {
HTML_OPEN ( "p" );
HTML_OPEN ( "em" );
- DocumentationRenderer::render_text ( OUT , E -> extra_credit_as_lexed );
+ DocumentationRenderer::render_text ( OUT , E -> extra_credit_as_lexed );
HTML_CLOSE ( "em" );
HTML_CLOSE ( "p" );
}
@@ -333,111 +291,88 @@ extension.
WRITE ( "compatibility" );
HTML_CLOSE ( "p" );
HTML_OPEN ( "p" );
- DocumentationRenderer::render_text ( OUT , C -> parsed_from );
+ DocumentationRenderer::render_text ( OUT , C -> parsed_from );
HTML_CLOSE ( "p" );
}
}
-
-void DocumentationRenderer::render_toc ( OUTPUT_STREAM , compiled_documentation * cd ) {
+void DocumentationRenderer::render_toc ( OUTPUT_STREAM , compiled_documentation * cd ) {
HTML_OPEN ( "div" );
HTML_OPEN_WITH ( "p" , "class=\"extensionsubheading\"" );
WRITE ( "contents" );
HTML_CLOSE ( "p" );
HTML_OPEN_WITH ( "ul" , "class=\"extensioncontents\"" );
- Trees::traverse_from ( cd -> tree -> root , & DocumentationRenderer::toc_visitor , ( void *) OUT , 0 );
+ DocumentationRenderer::render_toc_r ( OUT , cd -> alt_tree , 0 );
HTML_CLOSE ( "ul" );
HTML_CLOSE ( "div" );
}
-void DocumentationRenderer::link_to ( OUTPUT_STREAM , cdoc_heading * H ) {
- TEMPORARY_TEXT ( ch )
- if ( H -> level == 1 ) {
- WRITE_TO ( ch , "chapter%S.html" , H -> count );
- } else if ( H -> level == 2 ) {
- for ( int i =0; i <Str::len(H-> count ); i ++) {
- wchar_t c = Str::get_at ( H -> count , i );
- if ( c == '.' ) {
- WRITE_TO ( ch , "chapter" );
- for ( int j =0; j < i ; j ++)
- PUT_TO ( ch , Str::get_at ( H -> count , j ));
- WRITE_TO ( ch , ".html" );
- break ;
- }
- }
- WRITE_TO ( ch , "#section%d" , H -> ID );
- }
+void DocumentationRenderer::link_to ( OUTPUT_STREAM , markdown_item * md ) {
+ if ( md -> type != HEADING_MIT ) internal_error ( "not a heading" );
+ text_stream * ch = RETRIEVE_POINTER_text_stream ( md -> user_state );
HTML_OPEN_WITH ( "a" , "style=\"text-decoration: none\" href=%S" , ch );
- DISCARD_TEXT ( ch )
}
-int DocumentationRenderer::toc_visitor ( tree_node * N , void * state , int L ) {
- text_stream * OUT = ( text_stream *) state ;
- if ( N -> type == heading_TNT ) {
- cdoc_heading * H = RETRIEVE_POINTER_cdoc_heading ( N -> content );
+void DocumentationRenderer::render_toc_r ( OUTPUT_STREAM , markdown_item * md , int L ) {
+ if ( md -> type == HEADING_MIT ) {
if ( L > 0 ) {
HTML_OPEN_WITH ( "li" , "class=\"exco%d\"" , L );
HTML::begin_span ( OUT , I "indexblack" );
HTML_OPEN ( "b" );
- DocumentationRenderer::link_to ( OUT , H );
- if ( H -> level == 1 ) WRITE ( "Chapter %S: " , H -> count );
- else WRITE ( "Section %S: " , H -> count );
+ DocumentationRenderer::link_to ( OUT , md );
+ Markdown::render_extended ( OUT , md -> down ,
+ DocumentationInMarkdown::extension_flavoured_Markdown ());
HTML_CLOSE ( "a" );
HTML_CLOSE ( "b" );
HTML::end_span ( OUT );
- DocumentationRenderer::render_text ( OUT , H -> name );
HTML_CLOSE ( "li" );
}
}
- if ( N -> type == example_TNT ) {
+ if ( md -> type == INFORM_EXAMPLE_HEADING_MIT ) {
HTML_OPEN_WITH ( "li" , "class=\"exco%d\"" , L );
- cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( N -> content );
+ cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( md -> user_state );
TEMPORARY_TEXT ( link )
WRITE_TO ( link , "style=\"text-decoration: none\" href=\"eg%d.html#eg%d\"" ,
E -> number , E -> number );
HTML::begin_span ( OUT , I "indexblack" );
HTML_OPEN_WITH ( "a" , "%S" , link );
WRITE ( "Example %c — " , E -> letter );
- DocumentationRenderer::render_text ( OUT , E -> name );
+ DocumentationRenderer::render_text ( OUT , E -> name );
HTML_CLOSE ( "a" );
HTML::end_span ( OUT );
DISCARD_TEXT ( link )
HTML_CLOSE ( "li" );
}
- return TRUE ;
+ for ( markdown_item * ch = md -> down ; ch ; ch = ch -> next )
+ DocumentationRenderer::render_toc_r ( OUT , ch , L +1);
}
-void DocumentationRenderer::render_body ( OUTPUT_STREAM , compiled_documentation * cd ,
- tree_node * from ) {
- HTML_OPEN_WITH ( "div" , "class=\"documentation\"" );
- Trees::traverse_from ( from , & DocumentationRenderer::body_visitor , ( void *) OUT , 0 );
- HTML_CLOSE ( "div" );
-}
-
-void DocumentationRenderer::render_example ( OUTPUT_STREAM , compiled_documentation * cd , int eg ) {
+void DocumentationRenderer::render_example ( OUTPUT_STREAM , compiled_documentation * cd , int eg ) {
HTML_OPEN ( "div" );
- tree_node * EN = DocumentationTree::find_example ( cd -> tree , eg );
- if ( EN == NULL ) {
+ markdown_item * alt_EN = DocumentationInMarkdown::find_example ( cd -> alt_tree , eg );
+ if ( alt_EN == NULL ) {
WRITE ( "Example %d is missing" , eg );
} else {
- DocumentationRenderer::render_example_heading ( OUT , EN , EN -> child );
+ cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( alt_EN -> user_state );
+ DocumentationInMarkdown::render_example_heading ( OUT , E , alt_EN -> down );
HTML_CLOSE ( "div" );
- Enter the small print 4.1 ;
- WRITE ( "This example is drawn from " );
+ Enter the small print 3.1 ;
+
tree_node * H = EN -> parent ;
if ( H -> type == heading_TNT ) {
- cdoc_heading * E = RETRIEVE_POINTER_cdoc_heading ( H -> content );
+ cdoc_heading * E = RETRIEVE_POINTER_cdoc_heading ( H -> content );
if ( E -> level == 1 ) {
- DocumentationRenderer::link_to ( OUT , E );
- WRITE ( "Chapter %S" , E -> count );
+ DocumentationRenderer::link_to ( OUT , E );
+ WRITE ( "Chapter %S" , E -> count );
HTML_CLOSE ( "a" );
} else if ( E -> level == 2 ) {
- DocumentationRenderer::link_to ( OUT , E );
- WRITE ( "Section %S" , E -> count );
+ DocumentationRenderer::link_to ( OUT , E );
+ WRITE ( "Section %S" , E -> count );
HTML_CLOSE ( "a" );
} else {
HTML_OPEN_WITH ( "a" , "href=\"index.html\"" );
@@ -445,374 +380,43 @@ in a hierarchical fashion.
HTML_CLOSE ( "a" );
}
}
- Exit the small print 4.2 ;
+*/
+ Exit the small print 3.2 ;
}
}
-void DocumentationRenderer::render_chapter ( OUTPUT_STREAM , compiled_documentation * cd , int ch ) {
+void DocumentationRenderer::render_chapter ( OUTPUT_STREAM , compiled_documentation * cd , int ch ) {
HTML_OPEN ( "div" );
- tree_node * CN = DocumentationTree::find_chapter ( cd -> tree , ch );
- if ( CN == NULL ) {
- WRITE ( "Chapter %d is missing" , ch );
- } else {
- DocumentationRenderer::render_body ( OUT , cd , CN );
+ int found = FALSE ;
+ TEMPORARY_TEXT ( wanted )
+ WRITE_TO ( wanted , "Chapter %d:" , ch );
+ markdown_item * md = cd -> alt_tree -> down ;
+ int rendering = FALSE ;
+ while ( md ) {
+ if (( md -> type == HEADING_MIT ) && ( Markdown::get_heading_level ( md ) == 1 )) {
+ text_stream * S = md -> stashed ;
+ if ( Str::begins_with ( S , wanted )) { rendering = TRUE ; found = TRUE ; }
+ else rendering = FALSE ;
+ }
+ if ( rendering ) Markdown::render_extended ( OUT , md , DocumentationInMarkdown::extension_flavoured_Markdown ());
+ md = md -> next ;
}
+ if ( found == FALSE ) WRITE ( "Chapter %d is missing" , ch );
HTML_CLOSE ( "div" );
}
-
-int DocumentationRenderer::body_visitor ( tree_node * N , void * state , int L ) {
- text_stream * OUT = ( text_stream *) state ;
- if ( N == NULL ) return FALSE ;
- if ( N -> type == heading_TNT ) {
- cdoc_heading * H = RETRIEVE_POINTER_cdoc_heading ( N -> content );
- if ( H -> level > 0 ) Typeset the heading of this chapter or section 8.1 ;
- }
- if ( N -> type == example_TNT ) {
- DocumentationRenderer::render_example_heading ( OUT , N , NULL );
- return FALSE ;
- }
- if ( N -> type == source_error_TNT ) {
- cdoc_source_error * E = RETRIEVE_POINTER_cdoc_source_error ( N -> content );
- HTML_OPEN_WITH ( "p" , "class=\"documentationerrorbox\"" );
- HTML::begin_span ( OUT , I "documentationerror" );
- WRITE ( "Error: " ); DocumentationRenderer::render_text ( OUT , E -> error_message );
- HTML_CLOSE ( "span" );
- HTML_CLOSE ( "p" );
- return TRUE ;
- }
- if ( N -> type == phrase_defn_TNT ) {
- HTML_OPEN_WITH ( "div" , "class=\"definition\"" );
- HTML_OPEN_WITH ( "p" , "class=\"defnprototype\"" );
- cdoc_phrase_defn * P = RETRIEVE_POINTER_cdoc_phrase_defn ( N -> content );
- HTML_OPEN ( "b" );
- int bl = 0 ;
- for ( int i =0; i <Str::len(P-> prototype ); i ++) {
- wchar_t c = Str::get_at ( P -> prototype , i );
- if ( c == '(' ) { bl ++; if ( bl == 1 ) HTML_CLOSE ( "b" ); }
- PUT ( c );
- if ( c == ')' ) { bl --; if ( bl == 0 ) HTML_OPEN ( "b" ); }
- }
- if ( bl <= 0 ) HTML_CLOSE ( "b" );
- HTML_CLOSE ( "p" );
- Trees::traverse_from ( N -> child , & DocumentationRenderer::body_visitor , state , L );
- HTML_CLOSE ( "div" );
- return FALSE ;
- }
- if ( N -> type == paragraph_TNT ) {
- cdoc_paragraph * P = RETRIEVE_POINTER_cdoc_paragraph ( N -> content );
- HTML_OPEN ( "p" );
- DocumentationRenderer::render_text ( OUT , P -> content );
- HTML_CLOSE ( "p" );
- }
- if ( N -> type == code_sample_TNT ) {
- cdoc_code_sample * S = RETRIEVE_POINTER_cdoc_code_sample ( N -> content );
- HTML_OPEN ( "blockquote" );
- if ( S -> with_paste_marker ) Render the paste icon 8.2 ;
- Render the body of the code sample 8.3 ;
- HTML_CLOSE ( "blockquote" );
- return FALSE ;
- }
- return TRUE ;
-}
-
+
- HTML_TAG ( "hr" );
- if ( H -> level == 1 ) {
- HTML_OPEN ( "h2" );
- HTML::begin_span ( OUT , I "indexdullred" );
- }
- if ( H -> level == 2 ) {
- HTML_OPEN ( "h3" );
- HTML_OPEN ( "span" );
- }
- HTML_OPEN_WITH ( "span" , "id=docsec%d" , H -> ID );
- if ( H -> level == 1 ) WRITE ( "Chapter %S: " , H -> count );
- else WRITE ( "Section %S: " , H -> count );
- DocumentationRenderer::render_text ( OUT , H -> name );
- HTML_CLOSE ( "span" );
- HTML_CLOSE ( "span" );
- if ( H -> level == 1 ) HTML_CLOSE ( "h2" );
- if ( H -> level == 2 ) HTML_CLOSE ( "h3" );
-
-
-
-
-
- TEMPORARY_TEXT ( matter )
- for ( tree_node * M = N ; M ; ) {
- if ( M -> type == code_sample_TNT ) {
- cdoc_code_sample * S = RETRIEVE_POINTER_cdoc_code_sample ( M -> content );
- for ( tree_node * C = M -> child ; C ; C = C -> next ) {
- cdoc_code_line * L = RETRIEVE_POINTER_cdoc_code_line ( C -> content );
- for ( int i =0; i <L-> indentation ; i ++) WRITE_TO ( matter , "\t" );
- DocumentationRenderer::render_text ( matter , L -> content );
- if ( C -> next ) WRITE_TO ( matter , "\n" );
- }
- M = S -> continuation ;
- if ( M ) WRITE_TO ( matter , "\n\n" );
- } else break ;
- }
- ExtensionWebsite::paste_button ( OUT , matter );
- DISCARD_TEXT ( matter )
-
-
-
-
-
- programming_language * pl = S -> language ;
- if ( pl ) {
- Painter::reset_syntax_colouring ( pl );
- for ( tree_node * C = N -> child ; C ; C = C -> next ) {
- cdoc_code_line * L = RETRIEVE_POINTER_cdoc_code_line ( C -> content );
- Painter::syntax_colour ( pl , NULL , L -> content , L -> colouring , FALSE );
- }
- if ( Str::eq ( pl -> language_name , I "Inform" )) {
- int ts = FALSE ;
- for ( tree_node * C = N -> child ; C ; C = C -> next ) {
- cdoc_code_line * L = RETRIEVE_POINTER_cdoc_code_line ( C -> content );
- for ( int i =0; i <Str::len(L-> colouring ); i ++) {
- if ( Str::get_at ( L -> colouring , i ) == STRING_COLOUR ) {
- wchar_t c = Str::get_at ( L -> content , i );
- if ( c == '[' ) ts = TRUE ;
- if ( ts ) Str::put_at ( L -> colouring , i , EXTRACT_COLOUR );
- if ( c == ']' ) ts = FALSE ;
- } else ts = FALSE ;
- }
- }
- }
- }
- HTML::begin_span ( OUT , I "indexdullblue" );
- int tabulating = FALSE ;
- for ( tree_node * C = N -> child ; C ; C = C -> next ) {
- cdoc_code_line * L = RETRIEVE_POINTER_cdoc_code_line ( C -> content );
- if ( L -> tabular ) {
- if ( tabulating ) {
- Begin new row of I7 table in extension documentation 8.3.4 ;
- } else {
- Begin I7 table in extension documentation 8.3.1 ;
- tabulating = TRUE ;
- }
- int cell_from = 0 , cell_to = 0 , i = 0 ;
- Begin table cell for I7 table in extension documentation 8.3.3 ;
- for (; i <Str::len(L-> content ); i ++) {
- if ( Str::get_at ( L -> content , i ) == '\t' ) {
- End table cell for I7 table in extension documentation 8.3.2 ;
- while ( Str::get_at ( L -> content , i ) == '\t' ) i ++;
- Begin table cell for I7 table in extension documentation 8.3.3 ;
- i --;
- } else {
- cell_to ++;
- }
- }
- End table cell for I7 table in extension documentation 8.3.2 ;
- End row of I7 table in extension documentation 8.3.5 ;
- } else {
- if ( tabulating ) {
- End I7 table in extension documentation 8.3.6 ;
- tabulating = FALSE ;
- }
- for ( int i =0; i <L-> indentation ; i ++) WRITE ( " " );
- DocumentationRenderer::syntax_coloured_code ( OUT , L -> content , L -> colouring ,
- 0 , Str::len ( L -> content ));
- if (( C -> next ) && ( RETRIEVE_POINTER_cdoc_code_line ( C -> next -> content )-> tabular == FALSE )) HTML_TAG ( "br" );
- }
- WRITE ( "\n" );
- }
- if ( tabulating ) End I7 table in extension documentation 8.3.6 ;
- HTML_CLOSE ( "span" );
-
-
-
-
-
-
-
- HTML::end_span ( OUT );
- HTML_TAG ( "br" );
- HTML::begin_plain_html_table ( OUT );
- HTML::first_html_column ( OUT , 0 );
-
-This code is used in §8.3 .
-
-
-
- DocumentationRenderer::syntax_coloured_code ( OUT , L -> content , L -> colouring ,
- cell_from , cell_to );
- HTML::end_span ( OUT );
- HTML::next_html_column ( OUT , 0 );
-
-This code is used in §8.3 (twice).
-
-
-
- cell_from = i ; cell_to = cell_from ;
- HTML::begin_span ( OUT , I "indexdullblue" );
-
-This code is used in §8.3 (twice).
-
-
-
- HTML::first_html_column ( OUT , 0 );
-
-This code is used in §8.3 .
-
-
-
- HTML::end_html_row ( OUT );
-
-This code is used in §8.3 .
-
-
-
- HTML::end_html_table ( OUT );
- HTML::begin_span ( OUT , I "indexdullblue" );
-
-This code is used in §8.3 (twice).
-
-
-
-void DocumentationRenderer::render_example_heading ( OUTPUT_STREAM , tree_node * EN ,
- tree_node * passage_node ) {
- cdoc_example * E = RETRIEVE_POINTER_cdoc_example ( EN -> content );
- TEMPORARY_TEXT ( link )
- WRITE_TO ( link , "style=\"text-decoration: none\" href=\"eg%d.html\"" , E -> number );
-
- HTML_TAG ( "hr" );
- HTML::begin_plain_html_table ( OUT );
- HTML_OPEN ( "tr" );
-
-
- HTML_OPEN_WITH ( "td" , "halign=\"left\" valign=\"top\" cellpadding=0 cellspacing=0 width=38px" );
- HTML_OPEN_WITH ( "span" , "id=eg%d" , E -> number );
- Typeset the lettered oval example icon 9.1 ;
- HTML_CLOSE ( "span" );
- HTML_CLOSE ( "td" );
-
-
- HTML_OPEN_WITH ( "td" , "cellpadding=0 cellspacing=0 halign=\"left\" valign=\"top\"" );
-
- if ( passage_node == NULL ) HTML_OPEN_WITH ( "a" , "%S" , link );
- for ( int asterisk = 0 ; asterisk < E -> star_count ; asterisk ++)
- PUT ( 0x2605 );
-
-
- WRITE ( " " );
- HTML_OPEN ( "b" );
- HTML::begin_span ( OUT , I "indexdarkgrey" );
- WRITE ( " Example " );
- HTML::end_span ( OUT );
- HTML::begin_span ( OUT , I "indexblack" );
- DocumentationRenderer::render_text ( OUT , E -> name );
- HTML_TAG ( "br" );
- DocumentationRenderer::render_text ( OUT , E -> description );
- HTML::end_span ( OUT );
- HTML_CLOSE ( "b" );
-
- if ( passage_node == NULL ) HTML_CLOSE ( "a" );
-
- if ( passage_node )
- Trees::traverse_from ( passage_node , & DocumentationRenderer::body_visitor , ( void *) OUT , 0 );
-
- HTML_CLOSE ( "td" );
- HTML_CLOSE ( "tr" );
- HTML::end_html_table ( OUT );
-
- DISCARD_TEXT ( link )
-}
-
-
-
-
-
-
- HTML::begin_plain_html_table ( OUT );
- HTML_OPEN_WITH ( "tr" , "class=\"oval\"" );
- HTML_OPEN_WITH ( "td" , "width=38px height=30px align=\"left\" valign=\"center\"" );
- if ( passage_node == NULL ) HTML_OPEN_WITH ( "a" , "%S" , link );
- HTML_OPEN_WITH ( "div" ,
- "class=\"paragraph Body\" style=\"line-height: 1px; margin-bottom: 0px; "
- "margin-top: 0px; padding-bottom: 0pt; padding-top: 0px; text-align: center;\"" );
- HTML::begin_span ( OUT , I "extensionexampleletter" );
- PUT ( E -> letter );
- HTML::end_span ( OUT );
- HTML_CLOSE ( "div" );
- if ( passage_node == NULL ) HTML_CLOSE ( "a" );
- HTML_CLOSE ( "td" );
- HTML_CLOSE ( "tr" );
- HTML::end_html_table ( OUT );
-
-
-
-
-
-void DocumentationRenderer::render_text ( OUTPUT_STREAM , text_stream * text ) {
+void DocumentationRenderer::render_text ( OUTPUT_STREAM , text_stream * text ) {
markdown_item * md = Markdown::parse_inline ( text );
HTML_OPEN_WITH ( "span" , "class=\"markdowncontent\"" );
Markdown::render ( OUT , md );
HTML_CLOSE ( "span" );
}
-
-
-
-void DocumentationRenderer::syntax_coloured_code ( OUTPUT_STREAM , text_stream * text ,
- text_stream * colouring , int from , int to ) {
- wchar_t current_col = 0 ;
- for ( int i = from ; i < to ; i ++) {
- wchar_t c = Str::get_at ( text , i );
- wchar_t col = Str::get_at ( colouring , i );
- if ( col != current_col ) {
- if ( current_col ) HTML_CLOSE ( "span" );
- text_stream * span_class = NULL ;
- switch ( col ) {
- case DEFINITION_COLOUR: span_class = I "syntaxdefinition" ; break ;
- case FUNCTION_COLOUR: span_class = I "syntaxfunction" ; break ;
- case RESERVED_COLOUR: span_class = I "syntaxreserved" ; break ;
- case ELEMENT_COLOUR: span_class = I "syntaxelement" ; break ;
- case IDENTIFIER_COLOUR: span_class = I "syntaxidentifier" ; break ;
- case CHARACTER_COLOUR: span_class = I "syntaxcharacter" ; break ;
- case CONSTANT_COLOUR: span_class = I "syntaxconstant" ; break ;
- case STRING_COLOUR: span_class = I "syntaxstring" ; break ;
- case PLAIN_COLOUR: span_class = I "syntaxplain" ; break ;
- case EXTRACT_COLOUR: span_class = I "syntaxextract" ; break ;
- case COMMENT_COLOUR: span_class = I "syntaxcomment" ; break ;
- }
- HTML_OPEN_WITH ( "span" , "class=\"%S\"" , span_class );
- current_col = col ;
- }
- PUT ( c );
- }
- if ( current_col ) HTML_CLOSE ( "span" );
-}
-
+
diff --git a/docs/supervisor-module/7-eip.html b/docs/supervisor-module/7-eip.html
index c3fad657f..21ae3db8e 100644
--- a/docs/supervisor-module/7-eip.html
+++ b/docs/supervisor-module/7-eip.html
@@ -874,7 +874,7 @@ handed to
}
+
diff --git a/docs/supervisor-module/7-tc.html b/docs/supervisor-module/7-tc.html
index bb04cbb00..7e161e999 100644
--- a/docs/supervisor-module/7-tc.html
+++ b/docs/supervisor-module/7-tc.html
@@ -330,7 +330,7 @@ are legal.
}
+
diff --git a/docs/supervisor-module/7-ti.html b/docs/supervisor-module/7-ti.html
index 89fca9fa9..05e10c6cd 100644
--- a/docs/supervisor-module/7-ti.html
+++ b/docs/supervisor-module/7-ti.html
@@ -877,7 +877,7 @@ produces a second report.
This code is used in §7 (twice).
+
diff --git a/docs/supervisor-module/7-tm.html b/docs/supervisor-module/7-tm.html
index ed00459d3..97d286e98 100644
--- a/docs/supervisor-module/7-tm.html
+++ b/docs/supervisor-module/7-tm.html
@@ -237,7 +237,7 @@ examples provided in the extension.
Add internals 7.1 ;
DISCARD_TEXT ( details )
# endif
- DocumentationRenderer::as_HTML ( P , doc , OUT );
+ DocumentationRenderer::as_HTML ( P , doc , OUT );
DISCARD_TEXT ( OUT )
}
E -> documented_on_this_run = TRUE ;
@@ -257,10 +257,10 @@ examples provided in the extension.
WRITE ( "can be read here" );
HTML_CLOSE ( "a" );
WRITE ( "." );
- text_stream * MD = DocumentationRenderer::open_subpage ( P , I "metadata.html" );
+ text_stream * MD = DocumentationRenderer::open_subpage ( P , I "metadata.html" );
TEMPORARY_TEXT ( title )
WRITE_TO ( title , "%X" , E -> as_copy -> edition -> work );
- DocumentationRenderer::render_header ( MD , title , I "Metadata" , NULL );
+ DocumentationRenderer::render_header ( MD , title , I "Metadata" , NULL );
DISCARD_TEXT ( title )
ExtensionWebsite::write_metadata_page ( MD , E );
linked_list * L = NEW_LINKED_LIST ( inbuild_nest );
@@ -272,7 +272,7 @@ examples provided in the extension.
if ( K ) Link to documentation on K 7.1.1 ;
}
HTML_CLOSE ( "p" );
- DocumentationRenderer::close_subpage ();
+ DocumentationRenderer::close_subpage ();
LOOP_OVER_LINKED_LIST ( req , inbuild_requirement , E -> kits ) {
inform_kit * K = Kits::find_by_name ( req -> work -> raw_title , L , NULL );
if ( K ) Create documentation on K 7.1.2 ;
@@ -299,18 +299,18 @@ examples provided in the extension.
if ( Pathnames::create_in_file_system ( KP )) {
pathname * KD = Pathnames::down ( K -> as_copy -> location_if_path , I "Documentation" );
compiled_documentation * doc =
- DocumentationCompiler::compile_from_path ( KD , NULL );
+ DocumentationCompiler::compile_from_path ( KD , NULL );
if ( doc == NULL ) {
- text_stream * OUT = DocumentationRenderer::open_subpage ( KP , I "index.html" );
- DocumentationRenderer::render_header ( OUT , K -> as_copy -> edition -> work -> title , NULL , E );
+ text_stream * OUT = DocumentationRenderer::open_subpage ( KP , I "index.html" );
+ DocumentationRenderer::render_header ( OUT , K -> as_copy -> edition -> work -> title , NULL , E );
HTML_OPEN ( "p" );
WRITE ( "The kit %S does not provide any internal documentation." ,
K -> as_copy -> edition -> work -> title );
HTML_CLOSE ( "p" );
- DocumentationRenderer::close_subpage ();
+ DocumentationRenderer::close_subpage ();
} else {
doc -> within_extension = E ;
- DocumentationRenderer::as_HTML ( KP , doc , NULL );
+ DocumentationRenderer::as_HTML ( KP , doc , NULL );
}
}
@@ -339,20 +339,20 @@ examples provided in the extension.
text_stream * EXW_breakcrumb_URLs [5] = { NULL , NULL , NULL , NULL , NULL };
int no_EXW_breadcrumbs = 0 ;
-void ExtensionWebsite::add_home_breadcrumb ( text_stream * title ) {
+void ExtensionWebsite::add_home_breadcrumb ( text_stream * title ) {
if ( title == NULL ) title = I "Extensions" ;
ExtensionWebsite::add_breadcrumb ( title ,
I "inform:/Extensions/Reserved/Documentation/Extensions.html" );
}
-void ExtensionWebsite::add_breadcrumb ( text_stream * title , text_stream * URL ) {
+void ExtensionWebsite::add_breadcrumb ( text_stream * title , text_stream * URL ) {
if ( no_EXW_breadcrumbs >= 5 ) internal_error ( "too many breadcrumbs" );
EXW_breadcrumb_titles [ no_EXW_breadcrumbs ] = Str::duplicate ( title );
EXW_breakcrumb_URLs [ no_EXW_breadcrumbs ] = Str::duplicate ( URL );
no_EXW_breadcrumbs ++;
}
-void ExtensionWebsite::titling_and_navigation ( OUTPUT_STREAM , text_stream * subtitle ) {
+void ExtensionWebsite::titling_and_navigation ( OUTPUT_STREAM , text_stream * subtitle ) {
HTML_OPEN_WITH ( "div" , "class=\"headingpanellayout headingpanelalt\"" );
HTML_OPEN_WITH ( "div" , "class=\"headingtext\"" );
HTML::begin_span ( OUT , I "headingpaneltextalt" );
@@ -361,7 +361,7 @@ examples provided in the extension.
if (( i != no_EXW_breadcrumbs -1) && ( Str::len ( EXW_breakcrumb_URLs [ i ]) > 0 )) {
HTML_OPEN_WITH ( "a" , "href=\"%S\" class=\"registrycontentslink\"" , EXW_breakcrumb_URLs [ i ]);
}
- DocumentationRenderer::render_text ( OUT , EXW_breadcrumb_titles [ i ]);
+ DocumentationRenderer::render_text ( OUT , EXW_breadcrumb_titles [ i ]);
if (( i != no_EXW_breadcrumbs -1) && ( Str::len ( EXW_breakcrumb_URLs [ i ]) > 0 )) {
HTML_CLOSE ( "a" );
}
@@ -370,7 +370,7 @@ examples provided in the extension.
HTML_CLOSE ( "div" );
HTML_OPEN_WITH ( "div" , "class=\"headingrubric\"" );
HTML::begin_span ( OUT , I "headingpanelrubricalt" );
- DocumentationRenderer::render_text ( OUT , subtitle );
+ DocumentationRenderer::render_text ( OUT , subtitle );
HTML::end_span ( OUT );
HTML_CLOSE ( "div" );
HTML_CLOSE ( "div" );
@@ -382,7 +382,7 @@ a somewhat enigmatic icon.
-void ExtensionWebsite::paste_button ( OUTPUT_STREAM , text_stream * matter ) {
+void ExtensionWebsite::paste_button ( OUTPUT_STREAM , text_stream * matter ) {
TEMPORARY_TEXT ( paste )
ExtensionWebsite::paste_ideograph ( paste );
PasteButtons::paste_text_using ( OUT , matter , paste );
@@ -395,7 +395,7 @@ a somewhat enigmatic icon.
}
+
diff --git a/docs/supervisor-module/index.html b/docs/supervisor-module/index.html
index b5c191812..5b711e3dc 100644
--- a/docs/supervisor-module/index.html
+++ b/docs/supervisor-module/index.html
@@ -320,11 +320,6 @@
The Converter -
To convert an extension from the traditional one-file format to the more modern directory-based format.
-
-
- Documentation Tree -
- A data structure to hold segments of Inform resource documentation.
-
Documentation Compiler -
@@ -335,6 +330,11 @@
Documentation Renderer -
To render a passage of extension documentation as HTML.
+
+
+ Documentation in Markdown -
+ To provide a variation on Markdown for extension documentation.
+
diff --git a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
index 3533367a5..2a16cfaed 100644
--- a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
+++ b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
@@ -15,14 +15,7 @@ which use this module:
@e build_skill_CLASS
@e build_step_CLASS
@e build_vertex_CLASS
-@e cdoc_heading_CLASS
@e cdoc_example_CLASS
-@e cdoc_passage_CLASS
-@e cdoc_phrase_defn_CLASS
-@e cdoc_paragraph_CLASS
-@e cdoc_code_sample_CLASS
-@e cdoc_code_line_CLASS
-@e cdoc_source_error_CLASS
@e compiled_documentation_CLASS
@e control_structure_phrase_CLASS
@e copy_error_CLASS
@@ -55,14 +48,7 @@ DECLARE_CLASS(build_script)
DECLARE_CLASS(build_skill)
DECLARE_CLASS(build_step)
DECLARE_CLASS(build_vertex)
-DECLARE_CLASS(cdoc_heading)
DECLARE_CLASS(cdoc_example)
-DECLARE_CLASS(cdoc_passage)
-DECLARE_CLASS(cdoc_phrase_defn)
-DECLARE_CLASS(cdoc_paragraph)
-DECLARE_CLASS(cdoc_code_sample)
-DECLARE_CLASS(cdoc_code_line)
-DECLARE_CLASS(cdoc_source_error)
DECLARE_CLASS(control_structure_phrase)
DECLARE_CLASS(compiled_documentation)
DECLARE_CLASS(copy_error)
diff --git a/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w b/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w
index 6f631b2d8..c68421bc3 100644
--- a/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w
+++ b/inbuild/supervisor-module/Chapter 7/Documentation Compiler.w
@@ -3,7 +3,7 @@
To compile documentation from the textual syntax in an extension into a tree.
@ We will actually wrap the result in the following structure, but
-it's really not much more than the tree produced by //Documentation Tree//:
+it's really not much more than a tree of Markdown:
=
typedef struct compiled_documentation {
@@ -11,7 +11,7 @@ typedef struct compiled_documentation {
struct text_stream *original;
struct inform_extension *associated_extension;
struct inform_extension *within_extension;
- struct heterogeneous_tree *tree;
+ struct markdown_item *alt_tree;
int total_headings[3];
int total_examples;
int empty;
@@ -25,7 +25,7 @@ compiled_documentation *DocumentationCompiler::new_wrapper(text_stream *source)
cd->original = Str::duplicate(source);
cd->associated_extension = NULL;
cd->within_extension = NULL;
- cd->tree = DocumentationTree::new();
+ cd->alt_tree = NULL;
cd->total_examples = 0;
cd->total_headings[0] = 1;
cd->total_headings[1] = 0;
@@ -46,6 +46,29 @@ typedef struct satellite_test_case {
CLASS_DEFINITION
} satellite_test_case;
+@ Lettered examples have a "difficulty rating" in stars, 0 to 4. Numbers are unique
+from 1, 2, ...; letters are unique from A, B, C, ...
+
+=
+typedef struct cdoc_example {
+ struct text_stream *name;
+ struct text_stream *description;
+ int star_count;
+ int number;
+ char letter;
+ CLASS_DEFINITION
+} cdoc_example;
+
+cdoc_example *DocumentationCompiler::new_example_alone(text_stream *title, text_stream *desc, int star_count, int ecount) {
+ cdoc_example *E = CREATE(cdoc_example);
+ E->name = Str::duplicate(title);
+ E->description = Str::duplicate(desc);
+ E->star_count = star_count;
+ E->number = ecount;
+ E->letter = 'A' + (char) ecount - 1;
+ return E;
+}
+
@ We can compile either from a file...
=
@@ -112,8 +135,7 @@ typedef struct example_scanning_state {
struct text_stream *body_text;
struct text_stream *placement;
struct text_stream *desc;
- struct linked_list *errors;
- struct heterogeneous_tree *tree;
+ struct linked_list *errors; /* of |markdown_item| */
struct text_stream *scanning;
int past_header;
} example_scanning_state;
@@ -125,58 +147,66 @@ typedef struct example_scanning_state {
ess.body_text = Str::new();
ess.placement = NULL;
ess.desc = NULL;
- ess.errors = NEW_LINKED_LIST(tree_node);
- ess.tree = cd->tree;
+ ess.errors = NEW_LINKED_LIST(markdown_item);
ess.past_header = FALSE;
ess.scanning = Str::new(); WRITE_TO(ess.scanning, "%S", Filenames::get_leafname(stc->test_file));
TextFiles::read(stc->test_file, FALSE, "unable to read file of example", TRUE,
&DocumentationCompiler::read_example_helper, NULL, &ess);
- tree_node *placement_node = NULL;
+ markdown_item *alt_placement_node = NULL;
if (Str::len(ess.placement) == 0) {
- placement_node = cd->tree->root;
+ ;
} else {
- placement_node = DocumentationTree::find_section(cd->tree, ess.placement);
- if (placement_node == NULL) {
+ alt_placement_node = DocumentationInMarkdown::find_section(cd->alt_tree, ess.placement);
+ LOG("Looking for %S.\n", ess.placement);
+ if (alt_placement_node == NULL) {
DocumentationCompiler::example_error(&ess,
I"example gives a Location which is not the name of any section");
}
}
+
if (Str::len(ess.desc) == 0) {
DocumentationCompiler::example_error(&ess,
I"example does not give its Description");
}
- tree_node *content_node = NULL;
- if (Str::len(ess.body_text) == 0) {
+ cdoc_example *eg = DocumentationCompiler::new_example_alone(
+ ess.long_title, ess.desc, ess.star_count, ++(cd->total_examples));
+
+ markdown_item *eg_header = Markdown::new_item(INFORM_EXAMPLE_HEADING_MIT);
+ eg_header->user_state = STORE_POINTER_cdoc_example(eg);
+ markdown_item *md = alt_placement_node;
+ if (md == NULL) {
+ md = cd->alt_tree->down;
+ if (md == NULL) cd->alt_tree->down = eg_header;
+ else {
+ while ((md) && (md->next)) md = md->next;
+ eg_header->next = md->next; md->next = eg_header;
+ }
+ } else {
+ if (md->next) md = md->next;
+ while ((md) && (md->next) && (md->next->type != HEADING_MIT)) md = md->next;
+ eg_header->next = md->next; md->next = eg_header;
+ }
+ if (Str::len(ess.body_text) > 0) {
+ markdown_item *alt_ecd = Markdown::parse_extended(ess.body_text,
+ DocumentationInMarkdown::extension_flavoured_Markdown());
+ eg_header->down = alt_ecd->down;
+ Markdown::debug_subtree(DL, eg_header);
+ } else {
DocumentationCompiler::example_error(&ess,
I"example does not give any actual content");
- } else {
- compiled_documentation *ecd =
- DocumentationCompiler::compile(ess.body_text, associated_extension);
- if ((ecd) && (ecd->tree) && (ecd->tree->root) &&
- (ecd->tree->root->child) &&
- (ecd->tree->root->child->type == passage_TNT))
- content_node = ecd->tree->root->child;
- else {
- DocumentationCompiler::example_error(&ess,
- I"example file content is missing or wrongly set out");
- }
- }
- tree_node *example_node = DocumentationTree::new_example(cd->tree,
- ess.long_title, ess.desc, ess.star_count, ++(cd->total_examples));
- if (placement_node) Trees::make_child(example_node, placement_node);
- if (content_node) Trees::make_child(content_node, example_node);
+ }
- tree_node *E;
- LOOP_OVER_LINKED_LIST(E, tree_node, ess.errors)
- Trees::make_child(E, cd->tree->root);
+ markdown_item *E;
+ LOOP_OVER_LINKED_LIST(E, markdown_item, ess.errors)
+ Markdown::add_to(E, cd->alt_tree);
@ =
void DocumentationCompiler::example_error(example_scanning_state *ess, text_stream *text) {
text_stream *err = Str::new();
WRITE_TO(err, "Example file '%S': %S", ess->scanning, text);
- tree_node *E = DocumentationTree::new_source_error(ess->tree, err);
- ADD_TO_LINKED_LIST(E, tree_node, ess->errors);
+ markdown_item *E = DocumentationInMarkdown::error_item(err);
+ ADD_TO_LINKED_LIST(E, markdown_item, ess->errors);
}
@ =
@@ -255,345 +285,11 @@ compiled_documentation *DocumentationCompiler::compile(text_stream *source,
if (cd->associated_extension)
WRITE_TO(cd->title, "%X", cd->associated_extension->as_copy->edition->work);
if (Str::is_whitespace(source)) cd->empty = TRUE;
- else @;
- if (cd->empty) {
- SVEXPLAIN(1, "(resulting tree is empty)\n");
- } else {
- SVEXPLAIN(1, "(resulting tree has %d chapter(s), %d section(s) and %d example(s))\n",
- cd->total_headings[1], cd->total_headings[2], cd->total_examples);
- }
+ else cd->alt_tree = Markdown::parse_extended(source,
+ DocumentationInMarkdown::extension_flavoured_Markdown());
return cd;
}
-@ The source material is line-based, with semantic content sometimes spreading
-across multiple lines, so we'll need to keep track of some state as we read
-one line at a time:
-
-@ =
- int chapter_number = 0, section_number = 0;
-
- tree_node *current_headings[4]; /* Most recent headings of levels 0, 1, 2 */
- current_headings[0] = cd->tree->root; /* This will never change */
- current_headings[1] = NULL; /* Latest chapter, if any */
- current_headings[2] = NULL; /* Latest section in most recent thing of lower level */
- current_headings[3] = NULL; /* Latest example in most recent thing of lower level */
-
- tree_node *current_passage = NULL, /* passage being assembled, if any */
- *current_phrase_defn = NULL, /* again, if any */
- *current_paragraph = NULL,
- *current_code = NULL,
- *last_paste_code = NULL; /* last code sample with a paste button */
-
- int pending_code_sample_blanks = 0, code_is_tabular = FALSE; /* used only when assembling code samples */
- programming_language *default_language = DocumentationCompiler::get_language(I"Inform");
- programming_language *language = default_language;
-
- @;
-
-@ Leading space on a line is removed but not ignored: it is converted into an
-indentation level, measured as a tab count, using the exchange rate 4 spaces
-to 1 tab.
-
-@ =
- TEMPORARY_TEXT(line)
- int indentation = 0, space_count = 0;
- for (int i=0; i;
- Str::clear(line);
- indentation = 0; space_count = 0;
- } else if ((Str::len(line) == 0) && (Characters::is_whitespace(c))) {
- if (c == '\t') indentation++;
- if (c == ' ') space_count++;
- if (space_count == 4) { indentation++; space_count = 0; }
- } else {
- PUT_TO(line, c);
- }
- }
- if (Str::len(line) > 0) @;
- @;
- @;
- DISCARD_TEXT(line)
-
-@ Trailing space is ignored and removed.
-
-Lines which are unindented and take the following shapes are headings:
-= (text)
- Chapter: Survey and Prospecting
- Section: Black Gold
- Example: *** Gelignite Anderson - A Tale of the Texas Oilmen
-=
-where in each case the colon can equally be a hyphen, and with optional
-space either side.
-
-Otherwise, lines are divided into blanks, which always end paragraphs but
-may either end or continue code samples; unindented lines, which are always
-part of paragraphs; or indented ones, which are always part of code samples.
-
-@ =
- Str::trim_white_space(line);
- if (Str::len(line) == 0) {
- if (current_paragraph) @;
- if (current_code) @;
- } else if (indentation == 0) {
- match_results mr = Regexp::create_mr();
- if ((Regexp::match(&mr, line, L"Section *: *(%c+?)")) ||
- (Regexp::match(&mr, line, L"Section *- *(%c+?)"))) {
- @;
- } else if ((Regexp::match(&mr, line, L"Chapter *: *(%c+?)")) ||
- (Regexp::match(&mr, line, L"Chapter *- *(%c+?)"))) {
- @;
- } else if ((Regexp::match(&mr, line, L"Example *: *(%**) *(%c+?)")) ||
- (Regexp::match(&mr, line, L"Example *- *(%**) *(%c+?)"))) {
- @;
- } else if (Regexp::match(&mr, line, L"{defn *(%c*?)} *(%c+)")) {
- @;
- } else if (Regexp::match(&mr, line, L"{end}")) {
- @;
- } else {
- if (current_paragraph == NULL) @;
- @;
- @;
- }
- Regexp::dispose_of(&mr);
- } else {
- if (current_code == NULL) {
- if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == 'a') &&
- (Str::get_at(line, 2) == 's') && (Str::get_at(line, 3) == ' ') &&
- (Str::get_at(line, Str::len(line)-1) == '}')) {
- Str::delete_n_characters(line, 4);
- Str::delete_last_character(line);
- Str::trim_white_space(line);
- language = DocumentationCompiler::get_language(line);
- if (language == NULL) {
- @;
- @;
- TEMPORARY_TEXT(err)
- WRITE_TO(err, "cannot find a language called '%S'", line);
- tree_node *E = DocumentationTree::new_source_error(cd->tree, err);
- Trees::make_child(E, current_passage);
- DISCARD_TEXT(err)
- }
- } else {
- @;
- @;
- }
- } else {
- @;
- }
- }
-
-@ =
- @;
- chapter_number++;
- section_number = 0;
- int level = 1, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2];
- cd->total_headings[1]++;
- tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level,
- id, chapter_number, section_number);
- @;
-
-@ =
- @;
- section_number++;
- int level = 2, id = cd->total_headings[0] + cd->total_headings[1] + cd->total_headings[2];
- cd->total_headings[2]++;
- tree_node *new_node = DocumentationTree::new_heading(cd->tree, mr.exp[0], mr.exp[0], level,
- id, chapter_number, section_number);
- @;
-
-@ =
- @;
- int level = 3, star_count = Str::len(mr.exp[0]);
- tree_node *new_node = DocumentationTree::new_example(cd->tree, mr.exp[1], NULL,
- star_count, ++(cd->total_examples));
- @;
- if (star_count == 0) {
- @;
- tree_node *E = DocumentationTree::new_source_error(cd->tree,
- I"this example should be marked (before the title) '*', '**', '***' or '****' for difficulty");
- Trees::make_child(E, current_passage);
- }
- if (star_count > 4) {
- @;
- tree_node *E = DocumentationTree::new_source_error(cd->tree,
- I"four stars '****' is the maximum difficulty rating allowed");
- Trees::make_child(E, current_passage);
- }
-
-@ =
- @;
- if (current_phrase_defn == NULL) {
- @;
- @;
- current_phrase_defn =
- DocumentationTree::new_phrase_defn(cd->tree, mr.exp[0], mr.exp[1]);
- Trees::make_child(current_phrase_defn, current_passage);
- @;
- }
-
-@ =
- if (current_phrase_defn) {
- @;
- current_passage = current_phrase_defn->parent;
- current_phrase_defn = NULL;
- } else {
- @;
- tree_node *E = DocumentationTree::new_source_error(cd->tree,
- I"{end} without {defn}");
- Trees::make_child(E, current_passage);
- }
- language = default_language;
-
-@ =
- @;
- for (int j=level-1; j>=0; j--)
- if (current_headings[j]) {
- Trees::make_child(new_node, current_headings[j]);
- break;
- }
- current_headings[level] = new_node;
- for (int j=level+1; j<4; j++) current_headings[j] = NULL;
- language = default_language;
-
-@ =
- if (current_phrase_defn) {
- @;
- tree_node *E = DocumentationTree::new_source_error(cd->tree,
- I"{defn} has no {end}");
- Trees::make_child(E, current_passage);
- current_phrase_defn = NULL;
- }
-
-@ =
- if (current_passage == NULL) {
- current_passage = DocumentationTree::new_passage(cd->tree);
- if (current_phrase_defn)
- Trees::make_child(current_passage, current_phrase_defn);
- else for (int j=3; j>=0; j--)
- if (current_headings[j]) {
- Trees::make_child(current_passage, current_headings[j]);
- break;
- }
- current_paragraph = NULL;
- }
-
-@ =
- if (current_passage) {
- @;
- current_passage = NULL;
- }
-
-@ =
- if (current_paragraph) @
- if (current_code) @
-
-@ Line breaks are treated as spaces in the content of a paragraph, so that
-|P->content| here can be a long text but one which contains no line breaks.
-
-@ =
- @;
- @;
- current_paragraph = DocumentationTree::new_paragraph(cd->tree, NULL);
- Trees::make_child(current_paragraph, current_passage);
-
-@ =
- cdoc_paragraph *P = RETRIEVE_POINTER_cdoc_paragraph(current_paragraph->content);
- if (Str::len(P->content) > 0) WRITE_TO(P->content, " ");
-
-@ =
- cdoc_paragraph *P = RETRIEVE_POINTER_cdoc_paragraph(current_paragraph->content);
- WRITE_TO(P->content, "%S", line);
-
-@ =
- if (current_paragraph) {
- current_paragraph = NULL;
- }
-
-@ Line breaks are more significant in code samples, of course. Blank lines
-at the end of a code sample are stripped out; and they cannot appear at the start
-of a code sample either, since a non-blank indented line is needed to trigger one.
-
-@ =
- @;
- @;
-
- int paste_me = FALSE, continue_me = FALSE;
- if ((Str::get_at(line, 0) == '*') &&
- (Str::get_at(line, 1) == ':')) {
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::trim_white_space(line);
- paste_me = TRUE;
- } else if ((Str::get_at(line, 0) == '*') &&
- (Str::get_at(line, 1) == '*') &&
- (Str::get_at(line, 2) == ':')) {
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::trim_white_space(line);
- continue_me = TRUE;
- } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') &&
- (Str::get_at(line, 2) == '}')) {
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::trim_white_space(line);
- paste_me = TRUE;
- } else if ((Str::get_at(line, 0) == '{') && (Str::get_at(line, 1) == '*') &&
- (Str::get_at(line, 2) == '*') && (Str::get_at(line, 3) == '}')) {
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::delete_first_character(line);
- Str::trim_white_space(line);
- continue_me = TRUE;
- }
-
- current_code = DocumentationTree::new_code_sample(cd->tree, paste_me, language);
- if (continue_me) {
- if (last_paste_code) {
- cdoc_code_sample *S = RETRIEVE_POINTER_cdoc_code_sample(last_paste_code->content);
- S->continuation = current_code;
- } else {
- tree_node *E = DocumentationTree::new_source_error(cd->tree, I"cannot continue a paste here");
- Trees::make_child(E, current_passage);
- }
- }
- if ((paste_me) || (continue_me)) {
- last_paste_code = current_code;
- } else {
- last_paste_code = NULL;
- }
- Trees::make_child(current_code, current_passage);
- pending_code_sample_blanks = 0;
- code_is_tabular = FALSE;
-
-@ =
- if (current_code->child) {
- pending_code_sample_blanks++;
- code_is_tabular = FALSE;
- }
-
-@ =
- for (int i=0; itree, NULL, 0, FALSE), current_code);
- pending_code_sample_blanks = 0;
- match_results mr = Regexp::create_mr();
- if (Regexp::match(&mr, line, L"Table %c*")) {
- code_is_tabular = TRUE;
- }
- Regexp::dispose_of(&mr);
- Trees::make_child(DocumentationTree::new_code_line(cd->tree, line, indentation-1, code_is_tabular),
- current_code);
-
-@ =
- if (current_code) {
- current_code = NULL;
- code_is_tabular = FALSE;
- }
-
@
=
diff --git a/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w b/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w
index e9b1079ce..5695ae332 100644
--- a/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w
+++ b/inbuild/supervisor-module/Chapter 7/Documentation Renderer.w
@@ -2,50 +2,6 @@
To render a passage of extension documentation as HTML.
-@h Textual renderer.
-This very cheap renderer can be used to debug trees for logging purposes:
-
-=
-void DocumentationRenderer::as_plain_text(text_stream *OUT, heterogeneous_tree *T) {
- WRITE("%S\n", T->type->name);
- WRITE("--------\n");
- INDENT;
- Trees::traverse_from(T->root, &DocumentationRenderer::textual_visit, (void *) DL, 0);
- OUTDENT;
- WRITE("--------\n");
-}
-
-int DocumentationRenderer::textual_visit(tree_node *N, void *state, int L) {
- text_stream *OUT = (text_stream *) state;
- for (int i=0; itype == heading_TNT) {
- cdoc_heading *H = RETRIEVE_POINTER_cdoc_heading(N->content);
- WRITE("Heading H%d level %d: '%S - %S'\n", H->ID, H->level, H->count, H->name);
- } else if (N->type == example_TNT) {
- cdoc_example *E = RETRIEVE_POINTER_cdoc_example(N->content);
- WRITE("Example %c: '%S' (%d star(s))\n", E->letter, E->name, E->star_count);
- } else if (N->type == phrase_defn_TNT) {
- cdoc_phrase_defn *E = RETRIEVE_POINTER_cdoc_phrase_defn(N->content);
- WRITE("Phrase definition (tag '%S') [ %S ]\n", E->tag, E->prototype);
- } else if (N->type == passage_TNT) {
- WRITE("Passage\n");
- } else if (N->type == paragraph_TNT) {
- cdoc_paragraph *E = RETRIEVE_POINTER_cdoc_paragraph(N->content);
- WRITE("Paragraph: %d chars\n", Str::len(E->content));
- for (int i=0; icontent);
- for (int i=0; itype == code_sample_TNT) {
- WRITE("Code sample\n");
- } else if (N->type == code_line_TNT) {
- cdoc_code_line *E = RETRIEVE_POINTER_cdoc_code_line(N->content);
- WRITE("Code line: ");
- for (int i=0; iindentation; i++) WRITE(" ");
- WRITE("%S\n", E->content);
- } else WRITE("Unknown node\n");
- return TRUE;
-}
-
@h Website renderer.
We will make several HTML files, but only one at a time:
@@ -121,17 +77,16 @@ void DocumentationRenderer::render_index_page(OUTPUT_STREAM, compiled_documentat
HTML_OPEN("em");
DocumentationRenderer::render_text(OUT, I"Click on Chapter, Section or Example numbers to read");
HTML_CLOSE("em");
- if (cd->tree->root->child->type == passage_TNT) {
+ markdown_item *md = cd->alt_tree->down;
+ if ((md) && ((md->type != HEADING_MIT) || (Markdown::get_heading_level(md) > 1))) {
HTML_TAG("hr");
HTML_OPEN_WITH("p", "class=\"extensionsubheading\"");
WRITE("introduction");
HTML_CLOSE("p");
- for (tree_node *C = cd->tree->root->child; C; C = C->next) {
- if (C->type == heading_TNT) {
- cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(C->content);
- if (E->level == 1) break;
- }
- DocumentationRenderer::render_body(OUT, cd, C);
+ for (markdown_item *md = cd->alt_tree->down; md; md = md->next) {
+ if ((md->type == HEADING_MIT) && (Markdown::get_heading_level(md) == 1))
+ break;
+ Markdown::render_extended(OUT, md, DocumentationInMarkdown::extension_flavoured_Markdown());
}
}
} else { /* there are only sections and examples, or not even that */
@@ -143,7 +98,10 @@ void DocumentationRenderer::render_index_page(OUTPUT_STREAM, compiled_documentat
DocumentationRenderer::render_text(OUT, I"None is provided.");
HTML_CLOSE("p");
} else {
- DocumentationRenderer::render_body(OUT, cd, cd->tree->root);
+ HTML_OPEN_WITH("div", "class=\"markdowncontent\"");
+ Markdown::render_extended(OUT, cd->alt_tree,
+ DocumentationInMarkdown::extension_flavoured_Markdown());
+ HTML_CLOSE("div");
}
}
WRITE("%S", extras);
@@ -276,53 +234,35 @@ void DocumentationRenderer::render_toc(OUTPUT_STREAM, compiled_documentation *cd
WRITE("contents");
HTML_CLOSE("p");
HTML_OPEN_WITH("ul", "class=\"extensioncontents\"");
- Trees::traverse_from(cd->tree->root, &DocumentationRenderer::toc_visitor, (void *) OUT, 0);
+ DocumentationRenderer::render_toc_r(OUT, cd->alt_tree, 0);
HTML_CLOSE("ul");
HTML_CLOSE("div");
}
-void DocumentationRenderer::link_to(OUTPUT_STREAM, cdoc_heading *H) {
- TEMPORARY_TEXT(ch)
- if (H->level == 1) {
- WRITE_TO(ch, "chapter%S.html", H->count);
- } else if (H->level == 2) {
- for (int i=0; icount); i++) {
- wchar_t c = Str::get_at(H->count, i);
- if (c == '.') {
- WRITE_TO(ch, "chapter");
- for (int j=0; jcount, j));
- WRITE_TO(ch, ".html");
- break;
- }
- }
- WRITE_TO(ch, "#section%d", H->ID);
- }
+void DocumentationRenderer::link_to(OUTPUT_STREAM, markdown_item *md) {
+ if (md->type != HEADING_MIT) internal_error("not a heading");
+ text_stream *ch = RETRIEVE_POINTER_text_stream(md->user_state);
HTML_OPEN_WITH("a", "style=\"text-decoration: none\" href=%S", ch);
- DISCARD_TEXT(ch)
}
-int DocumentationRenderer::toc_visitor(tree_node *N, void *state, int L) {
- text_stream *OUT = (text_stream *) state;
- if (N->type == heading_TNT) {
- cdoc_heading *H = RETRIEVE_POINTER_cdoc_heading(N->content);
+void DocumentationRenderer::render_toc_r(OUTPUT_STREAM, markdown_item *md, int L) {
+ if (md->type == HEADING_MIT) {
if (L > 0) {
HTML_OPEN_WITH("li", "class=\"exco%d\"", L);
HTML::begin_span(OUT, I"indexblack");
HTML_OPEN("b");
- DocumentationRenderer::link_to(OUT, H);
- if (H->level == 1) WRITE("Chapter %S: ", H->count);
- else WRITE("Section %S: ", H->count);
+ DocumentationRenderer::link_to(OUT, md);
+ Markdown::render_extended(OUT, md->down,
+ DocumentationInMarkdown::extension_flavoured_Markdown());
HTML_CLOSE("a");
HTML_CLOSE("b");
HTML::end_span(OUT);
- DocumentationRenderer::render_text(OUT, H->name);
HTML_CLOSE("li");
}
}
- if (N->type == example_TNT) {
+ if (md->type == INFORM_EXAMPLE_HEADING_MIT) {
HTML_OPEN_WITH("li", "class=\"exco%d\"", L);
- cdoc_example *E = RETRIEVE_POINTER_cdoc_example(N->content);
+ cdoc_example *E = RETRIEVE_POINTER_cdoc_example(md->user_state);
TEMPORARY_TEXT(link)
WRITE_TO(link, "style=\"text-decoration: none\" href=\"eg%d.html#eg%d\"",
E->number, E->number);
@@ -335,26 +275,21 @@ int DocumentationRenderer::toc_visitor(tree_node *N, void *state, int L) {
DISCARD_TEXT(link)
HTML_CLOSE("li");
}
- return TRUE;
-}
-
-void DocumentationRenderer::render_body(OUTPUT_STREAM, compiled_documentation *cd,
- tree_node *from) {
- HTML_OPEN_WITH("div", "class=\"documentation\"");
- Trees::traverse_from(from, &DocumentationRenderer::body_visitor, (void *) OUT, 0);
- HTML_CLOSE("div");
+ for (markdown_item *ch = md->down; ch; ch = ch->next)
+ DocumentationRenderer::render_toc_r(OUT, ch, L+1);
}
void DocumentationRenderer::render_example(OUTPUT_STREAM, compiled_documentation *cd, int eg) {
HTML_OPEN("div");
- tree_node *EN = DocumentationTree::find_example(cd->tree, eg);
- if (EN == NULL) {
+ markdown_item *alt_EN = DocumentationInMarkdown::find_example(cd->alt_tree, eg);
+ if (alt_EN == NULL) {
WRITE("Example %d is missing", eg);
} else {
- DocumentationRenderer::render_example_heading(OUT, EN, EN->child);
+ cdoc_example *E = RETRIEVE_POINTER_cdoc_example(alt_EN->user_state);
+ DocumentationInMarkdown::render_example_heading(OUT, E, alt_EN->down);
HTML_CLOSE("div");
@;
- WRITE("This example is drawn from ");
+/* WRITE("This example is drawn from ");
tree_node *H = EN->parent;
if (H->type == heading_TNT) {
cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(H->content);
@@ -372,286 +307,31 @@ void DocumentationRenderer::render_example(OUTPUT_STREAM, compiled_documentation
HTML_CLOSE("a");
}
}
+*/
@;
}
}
void DocumentationRenderer::render_chapter(OUTPUT_STREAM, compiled_documentation *cd, int ch) {
HTML_OPEN("div");
- tree_node *CN = DocumentationTree::find_chapter(cd->tree, ch);
- if (CN == NULL) {
- WRITE("Chapter %d is missing", ch);
- } else {
- DocumentationRenderer::render_body(OUT, cd, CN);
+ int found = FALSE;
+ TEMPORARY_TEXT(wanted)
+ WRITE_TO(wanted, "Chapter %d:", ch);
+ markdown_item *md = cd->alt_tree->down;
+ int rendering = FALSE;
+ while (md) {
+ if ((md->type == HEADING_MIT) && (Markdown::get_heading_level(md) == 1)) {
+ text_stream *S = md->stashed;
+ if (Str::begins_with(S, wanted)) { rendering = TRUE; found = TRUE; }
+ else rendering = FALSE;
+ }
+ if (rendering) Markdown::render_extended(OUT, md, DocumentationInMarkdown::extension_flavoured_Markdown());
+ md = md->next;
}
+ if (found == FALSE) WRITE("Chapter %d is missing", ch);
HTML_CLOSE("div");
}
-int DocumentationRenderer::body_visitor(tree_node *N, void *state, int L) {
- text_stream *OUT = (text_stream *) state;
- if (N == NULL) return FALSE;
- if (N->type == heading_TNT) {
- cdoc_heading *H = RETRIEVE_POINTER_cdoc_heading(N->content);
- if (H->level > 0) @;
- }
- if (N->type == example_TNT) {
- DocumentationRenderer::render_example_heading(OUT, N, NULL);
- return FALSE;
- }
- if (N->type == source_error_TNT) {
- cdoc_source_error *E = RETRIEVE_POINTER_cdoc_source_error(N->content);
- HTML_OPEN_WITH("p", "class=\"documentationerrorbox\"");
- HTML::begin_span(OUT, I"documentationerror");
- WRITE("Error: "); DocumentationRenderer::render_text(OUT, E->error_message);
- HTML_CLOSE("span");
- HTML_CLOSE("p");
- return TRUE;
- }
- if (N->type == phrase_defn_TNT) {
- HTML_OPEN_WITH("div", "class=\"definition\"");
- HTML_OPEN_WITH("p", "class=\"defnprototype\"");
- cdoc_phrase_defn *P = RETRIEVE_POINTER_cdoc_phrase_defn(N->content);
- HTML_OPEN("b");
- int bl = 0;
- for (int i=0; iprototype); i++) {
- wchar_t c = Str::get_at(P->prototype, i);
- if (c == '(') { bl++; if (bl == 1) HTML_CLOSE("b"); }
- PUT(c);
- if (c == ')') { bl--; if (bl == 0) HTML_OPEN("b"); }
- }
- if (bl <= 0) HTML_CLOSE("b");
- HTML_CLOSE("p");
- Trees::traverse_from(N->child, &DocumentationRenderer::body_visitor, state, L);
- HTML_CLOSE("div");
- return FALSE;
- }
- if (N->type == paragraph_TNT) {
- cdoc_paragraph *P = RETRIEVE_POINTER_cdoc_paragraph(N->content);
- HTML_OPEN("p");
- DocumentationRenderer::render_text(OUT, P->content);
- HTML_CLOSE("p");
- }
- if (N->type == code_sample_TNT) {
- cdoc_code_sample *S = RETRIEVE_POINTER_cdoc_code_sample(N->content);
- HTML_OPEN("blockquote");
- if (S->with_paste_marker) @;
- @;
- HTML_CLOSE("blockquote");
- return FALSE;
- }
- return TRUE;
-}
-
-@ =
- HTML_TAG("hr");
- if (H->level == 1) {
- HTML_OPEN("h2");
- HTML::begin_span(OUT, I"indexdullred");
- }
- if (H->level == 2) {
- HTML_OPEN("h3");
- HTML_OPEN("span");
- }
- HTML_OPEN_WITH("span", "id=docsec%d", H->ID);
- if (H->level == 1) WRITE("Chapter %S: ", H->count);
- else WRITE("Section %S: ", H->count);
- DocumentationRenderer::render_text(OUT, H->name);
- HTML_CLOSE("span");
- HTML_CLOSE("span");
- if (H->level == 1) HTML_CLOSE("h2");
- if (H->level == 2) HTML_CLOSE("h3");
-
-@ =
- TEMPORARY_TEXT(matter)
- for (tree_node *M = N; M; ) {
- if (M->type == code_sample_TNT) {
- cdoc_code_sample *S = RETRIEVE_POINTER_cdoc_code_sample(M->content);
- for (tree_node *C = M->child; C; C = C->next) {
- cdoc_code_line *L = RETRIEVE_POINTER_cdoc_code_line(C->content);
- for (int i=0; iindentation; i++) WRITE_TO(matter, "\t");
- DocumentationRenderer::render_text(matter, L->content);
- if (C->next) WRITE_TO(matter, "\n");
- }
- M = S->continuation;
- if (M) WRITE_TO(matter, "\n\n");
- } else break;
- }
- ExtensionWebsite::paste_button(OUT, matter);
- DISCARD_TEXT(matter)
-
-@ =
- programming_language *pl = S->language;
- if (pl) {
- Painter::reset_syntax_colouring(pl);
- for (tree_node *C = N->child; C; C = C->next) {
- cdoc_code_line *L = RETRIEVE_POINTER_cdoc_code_line(C->content);
- Painter::syntax_colour(pl, NULL, L->content, L->colouring, FALSE);
- }
- if (Str::eq(pl->language_name, I"Inform")) {
- int ts = FALSE;
- for (tree_node *C = N->child; C; C = C->next) {
- cdoc_code_line *L = RETRIEVE_POINTER_cdoc_code_line(C->content);
- for (int i=0; icolouring); i++) {
- if (Str::get_at(L->colouring, i) == STRING_COLOUR) {
- wchar_t c = Str::get_at(L->content, i);
- if (c == '[') ts = TRUE;
- if (ts) Str::put_at(L->colouring, i, EXTRACT_COLOUR);
- if (c == ']') ts = FALSE;
- } else ts = FALSE;
- }
- }
- }
- }
- HTML::begin_span(OUT, I"indexdullblue");
- int tabulating = FALSE;
- for (tree_node *C = N->child; C; C = C->next) {
- cdoc_code_line *L = RETRIEVE_POINTER_cdoc_code_line(C->content);
- if (L->tabular) {
- if (tabulating) {
- @;
- } else {
- @;
- tabulating = TRUE;
- }
- int cell_from = 0, cell_to = 0, i = 0;
- @;
- for (; icontent); i++) {
- if (Str::get_at(L->content, i) == '\t') {
- @;
- while (Str::get_at(L->content, i) == '\t') i++;
- @;
- i--;
- } else {
- cell_to++;
- }
- }
- @;
- @;
- } else {
- if (tabulating) {
- @;
- tabulating = FALSE;
- }
- for (int i=0; iindentation; i++) WRITE(" ");
- DocumentationRenderer::syntax_coloured_code(OUT, L->content, L->colouring,
- 0, Str::len(L->content));
- if ((C->next) && (RETRIEVE_POINTER_cdoc_code_line(C->next->content)->tabular == FALSE)) HTML_TAG("br");
- }
- WRITE("\n");
- }
- if (tabulating) @;
- HTML_CLOSE("span");
-
-@ Unsurprisingly, I7 tables are set (after their titling lines) as HTML tables,
-and this is fiddly but elementary in the usual way of HTML tables:
-
-@ =
- HTML::end_span(OUT);
- HTML_TAG("br");
- HTML::begin_plain_html_table(OUT);
- HTML::first_html_column(OUT, 0);
-
-@ =
- DocumentationRenderer::syntax_coloured_code(OUT, L->content, L->colouring,
- cell_from, cell_to);
- HTML::end_span(OUT);
- HTML::next_html_column(OUT, 0);
-
-@ =
- cell_from = i; cell_to = cell_from;
- HTML::begin_span(OUT, I"indexdullblue");
-
-@ =
- HTML::first_html_column(OUT, 0);
-
-@ =
- HTML::end_html_row(OUT);
-
-@ =
- HTML::end_html_table(OUT);
- HTML::begin_span(OUT, I"indexdullblue");
-
-@ An example is set with a two-table header, and followed optionally by a
-table of its inset copy, shaded to distinguish it from the rest of the
-page. The heading is constructed with a main table of one row of two cells,
-in the following section. The left-hand cell then contains a further table,
-in the next section.
-
-=
-void DocumentationRenderer::render_example_heading(OUTPUT_STREAM, tree_node *EN,
- tree_node *passage_node) {
- cdoc_example *E = RETRIEVE_POINTER_cdoc_example(EN->content);
- TEMPORARY_TEXT(link)
- WRITE_TO(link, "style=\"text-decoration: none\" href=\"eg%d.html\"", E->number);
-
- HTML_TAG("hr"); /* rule a line before the example heading */
- HTML::begin_plain_html_table(OUT);
- HTML_OPEN("tr");
-
- /* Left hand cell: the oval icon */
- HTML_OPEN_WITH("td", "halign=\"left\" valign=\"top\" cellpadding=0 cellspacing=0 width=38px");
- HTML_OPEN_WITH("span", "id=eg%d", E->number); /* provide the anchor point */
- @;
- HTML_CLOSE("span"); /* end the textual link */
- HTML_CLOSE("td");
-
- /* Right hand cell: the asterisks and title, with rubric underneath */
- HTML_OPEN_WITH("td", "cellpadding=0 cellspacing=0 halign=\"left\" valign=\"top\"");
-
- if (passage_node == NULL) HTML_OPEN_WITH("a", "%S", link);
- for (int asterisk = 0; asterisk < E->star_count; asterisk++)
- PUT(0x2605); /* the Unicode for "black star" emoji */
- /* or 0x2B50 is the Unicode for "star" emoji */
- /* or again, could use the asterisk.png image in the app */
- WRITE(" ");
- HTML_OPEN("b");
- HTML::begin_span(OUT, I"indexdarkgrey");
- WRITE(" Example ");
- HTML::end_span(OUT);
- HTML::begin_span(OUT, I"indexblack");
- DocumentationRenderer::render_text(OUT, E->name);
- HTML_TAG("br");
- DocumentationRenderer::render_text(OUT, E->description);
- HTML::end_span(OUT);
- HTML_CLOSE("b");
-
- if (passage_node == NULL) HTML_CLOSE("a"); /* Link does not cover body, only heading */
-
- if (passage_node)
- Trees::traverse_from(passage_node, &DocumentationRenderer::body_visitor, (void *) OUT, 0);
-
- HTML_CLOSE("td");
- HTML_CLOSE("tr");
- HTML::end_html_table(OUT);
-
- DISCARD_TEXT(link)
-}
-
-@ The little oval icon with its superimposed boldface letter is much harder to
-get right on all browsers than it looks, and the following is the result of
-some pretty grim experimentation. Basically, we make a tight, borderless,
-one-cell-in-one-row table, use CSS to make a transparent PNG image of an oval
-the background image for the table, then put a boldface letter in the centre
-of its one and only cell. (Things were even worse when IE6 for Windows still
-had its infamous PNG transparency bug.)
-
-@ =
- HTML::begin_plain_html_table(OUT);
- HTML_OPEN_WITH("tr", "class=\"oval\"");
- HTML_OPEN_WITH("td", "width=38px height=30px align=\"left\" valign=\"center\"");
- if (passage_node == NULL) HTML_OPEN_WITH("a", "%S", link);
- HTML_OPEN_WITH("div",
- "class=\"paragraph Body\" style=\"line-height: 1px; margin-bottom: 0px; "
- "margin-top: 0px; padding-bottom: 0pt; padding-top: 0px; text-align: center;\"");
- HTML::begin_span(OUT, I"extensionexampleletter");
- PUT(E->letter);
- HTML::end_span(OUT);
- HTML_CLOSE("div");
- if (passage_node == NULL) HTML_CLOSE("a");
- HTML_CLOSE("td");
- HTML_CLOSE("tr");
- HTML::end_html_table(OUT);
-
@
=
@@ -661,34 +341,3 @@ void DocumentationRenderer::render_text(OUTPUT_STREAM, text_stream *text) {
Markdown::render(OUT, md);
HTML_CLOSE("span");
}
-
-@ =
-void DocumentationRenderer::syntax_coloured_code(OUTPUT_STREAM, text_stream *text,
- text_stream *colouring, int from, int to) {
- wchar_t current_col = 0;
- for (int i=from; itype != heading_TNT) || (N->next))
- return FALSE;
- return TRUE;
-}
-
-@ Heading nodes are used for the root (which has ID 0 and level 0) and then for
-all chapter and section headings (which have levels 1 and 2 respectively). All
-ID numbers are unique. The root heading is the only one with an empty "count",
-which is otherwise something like |5| (chapter 5) or |3.4| (section 4 in chapter 3).
-
-=
-typedef struct cdoc_heading {
- struct text_stream *count;
- struct text_stream *name;
- struct text_stream *recognition_name;
- int level; /* 0 = root, 1 = chapter, 2 = section */
- int ID;
- CLASS_DEFINITION
-} cdoc_heading;
-
-tree_node *DocumentationTree::new_heading(heterogeneous_tree *tree,
- text_stream *title, text_stream *recognise_as, int level, int ID, int cc, int sc) {
- cdoc_heading *H = CREATE(cdoc_heading);
- H->count = Str::new();
- if (cc > 0) WRITE_TO(H->count, "%d", cc);
- if ((cc > 0) && (sc > 0)) WRITE_TO(H->count, ".");
- if (sc > 0) WRITE_TO(H->count, "%d", sc);
- H->name = Str::duplicate(title);
- H->recognition_name = Str::duplicate(recognise_as);
- H->level = level;
- H->ID = ID;
- return Trees::new_node(tree, heading_TNT, STORE_POINTER_cdoc_heading(H));
-}
-
-@ A heading node can only have headings or examples as children, except that
-it can have a single passage node as its first child. If so, this is introductory
-text.
-
-=
-int DocumentationTree::heading_verifier(tree_node *N) {
- for (tree_node *C = N->child; C; C = C->next) {
- if ((C->type != heading_TNT) && (C->type != example_TNT) && (C->type != passage_TNT))
- return FALSE;
- if ((C->type == passage_TNT) && (C->next)) return FALSE;
- }
- return TRUE;
-}
-
-@ Example nodes are used for the lettered examples in a documentation segment.
-They have a "difficulty rating" in stars, 0 to 4. Numbers are unique from 1, 2, ...;
-letters are unique from A, B, C, ...
-
-=
-typedef struct cdoc_example {
- struct text_stream *name;
- struct text_stream *description;
- int star_count;
- int number;
- char letter;
- CLASS_DEFINITION
-} cdoc_example;
-
-tree_node *DocumentationTree::new_example(heterogeneous_tree *tree,
- text_stream *title, text_stream *desc, int star_count, int ecount) {
- cdoc_example *E = CREATE(cdoc_example);
- E->name = Str::duplicate(title);
- E->description = Str::duplicate(desc);
- E->star_count = star_count;
- E->number = ecount;
- E->letter = 'A' + (char) ecount - 1;
- return Trees::new_node(tree, example_TNT, STORE_POINTER_cdoc_example(E));
-}
-
-@ An example node always has a single child: the passage containing its content.
-
-=
-int DocumentationTree::example_verifier(tree_node *N) {
- if ((N->child == NULL) || (N->child->type != passage_TNT) || (N->child->next))
- return FALSE;
- return TRUE;
-}
-
-@ Passage nodes contain passages of documentation which fall under examples
-or headings.
-
-=
-typedef struct cdoc_passage {
- CLASS_DEFINITION
-} cdoc_passage;
-
-tree_node *DocumentationTree::new_passage(heterogeneous_tree *tree) {
- cdoc_passage *P = CREATE(cdoc_passage);
- return Trees::new_node(tree, passage_TNT, STORE_POINTER_cdoc_passage(P));
-}
-
-@ A passage node is essentially a holder for a mixed list of paragraphs,
-indented code samples and phrase definitions.
-
-=
-int DocumentationTree::passage_verifier(tree_node *N) {
- for (tree_node *C = N->child; C; C = C->next)
- if ((C->type != paragraph_TNT) &&
- (C->type != code_sample_TNT) &&
- (C->type != phrase_defn_TNT) &&
- (C->type != source_error_TNT))
- return FALSE;
- return TRUE;
-}
-
-@ Phrase definition nodes contain little dashed inset boxes formally describing
-phrases. The "tag" is optional and is for potential cross-referencing; the
-"prototype" is the Inform source text for the phrase definition.
-
-=
-typedef struct cdoc_phrase_defn {
- struct text_stream *tag;
- struct text_stream *prototype;
- CLASS_DEFINITION
-} cdoc_phrase_defn;
-
-tree_node *DocumentationTree::new_phrase_defn(heterogeneous_tree *tree,
- text_stream *tag, text_stream *prototype) {
- cdoc_phrase_defn *P = CREATE(cdoc_phrase_defn);
- P->tag = Str::duplicate(tag);
- P->prototype = Str::duplicate(prototype);
- return Trees::new_node(tree, phrase_defn_TNT, STORE_POINTER_cdoc_phrase_defn(P));
-}
-
-@ An phrase defn node always has a single child: the passage containing its content.
-
-=
-int DocumentationTree::phrase_defn_verifier(tree_node *N) {
- if ((N->child == NULL) || (N->child->type != passage_TNT) || (N->child->next))
- return FALSE;
- return TRUE;
-}
-
-@ A paragraph node holds a body paragraph of text. It has no children.
-
-=
-typedef struct cdoc_paragraph {
- struct text_stream *content;
- CLASS_DEFINITION
-} cdoc_paragraph;
-
-tree_node *DocumentationTree::new_paragraph(heterogeneous_tree *tree,
- text_stream *content) {
- cdoc_paragraph *P = CREATE(cdoc_paragraph);
- P->content = Str::duplicate(content);
- return Trees::new_node(tree, paragraph_TNT, STORE_POINTER_cdoc_paragraph(P));
-}
-
-int DocumentationTree::paragraph_verifier(tree_node *N) {
- if (N->child) return FALSE; /* This must be a leaf node */
- return TRUE;
-}
-
-@ A code sample node holds a single code sample.
-
-=
-typedef struct cdoc_code_sample {
- CLASS_DEFINITION
- int with_paste_marker;
- struct tree_node *continuation;
- struct programming_language *language;
-} cdoc_code_sample;
-
-tree_node *DocumentationTree::new_code_sample(heterogeneous_tree *tree, int paste_me,
- programming_language *language) {
- cdoc_code_sample *C = CREATE(cdoc_code_sample);
- C->with_paste_marker = paste_me;
- C->continuation = NULL;
- C->language = language;
- return Trees::new_node(tree, code_sample_TNT, STORE_POINTER_cdoc_code_sample(C));
-}
-
-@ A code sample's children form a list of code lines.
-
-=
-int DocumentationTree::code_sample_verifier(tree_node *N) {
- for (tree_node *C = N->child; C; C = C->next)
- if (C->type != code_line_TNT)
- return FALSE;
- if (N->child == NULL) return FALSE;
- return TRUE;
-}
-
-@ A code line node holds a single line of code, and has no children. The
-indentation is relative to the start of the code sample, so usually starts
-at 0, and is measured in tab stops.
-
-=
-typedef struct cdoc_code_line {
- struct text_stream *content;
- struct text_stream *colouring;
- int indentation;
- int tabular;
- CLASS_DEFINITION
-} cdoc_code_line;
-
-tree_node *DocumentationTree::new_code_line(heterogeneous_tree *tree,
- text_stream *content, int indentation, int tabular) {
- cdoc_code_line *C = CREATE(cdoc_code_line);
- C->content = Str::duplicate(content);
- C->colouring = Str::new();
- C->indentation = indentation;
- C->tabular = tabular;
- return Trees::new_node(tree, code_line_TNT, STORE_POINTER_cdoc_code_line(C));
-}
-
-int DocumentationTree::code_line_verifier(tree_node *N) {
- if (N->child) return FALSE; /* This must be a leaf node */
- return TRUE;
-}
-
-@ An error node holds a single error message, and has no children.
-
-=
-typedef struct cdoc_source_error {
- struct text_stream *error_message;
- CLASS_DEFINITION
-} cdoc_source_error;
-
-tree_node *DocumentationTree::new_source_error(heterogeneous_tree *tree,
- text_stream *content) {
- cdoc_source_error *E = CREATE(cdoc_source_error);
- E->error_message = Str::duplicate(content);
- return Trees::new_node(tree, source_error_TNT, STORE_POINTER_cdoc_source_error(E));
-}
-
-int DocumentationTree::source_error_verifier(tree_node *N) {
- if (N->child) return FALSE; /* This must be a leaf node */
- return TRUE;
-}
-
-@ This utility function returns the |eg|th example node, if it exists, and |NULL|
-if not.
-
-=
-tree_node *DocumentationTree::find_example(heterogeneous_tree *T, int eg) {
- if (eg < 1) return NULL;
- dc_find_example_task task;
- task.to_find_example = eg;
- task.to_find_heading = NULL;
- task.to_find_section = NULL;
- task.result = NULL;
- Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0);
- return task.result;
-}
-
-tree_node *DocumentationTree::find_chapter(heterogeneous_tree *T, int ch) {
- if (ch < 1) return NULL;
- dc_find_example_task task;
- task.to_find_example = 0;
- task.to_find_heading = Str::new(); WRITE_TO(task.to_find_heading, "%d", ch);
- task.to_find_section = NULL;
- task.result = NULL;
- Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0);
- return task.result;
-}
-
-tree_node *DocumentationTree::find_section(heterogeneous_tree *T, text_stream *name) {
- if (Str::len(name) == 0) return NULL;
- dc_find_example_task task;
- task.to_find_example = 0;
- task.to_find_heading = NULL;
- task.to_find_section = name;
- task.result = NULL;
- Trees::traverse_from(T->root, &DocumentationTree::find_visit, (void *) &task, 0);
- return task.result;
-}
-
-typedef struct dc_find_example_task {
- int to_find_example;
- struct text_stream *to_find_heading;
- struct text_stream *to_find_section;
- struct tree_node *result;
-} dc_find_example_task;
-
-int DocumentationTree::find_visit(tree_node *N, void *state, int L) {
- dc_find_example_task *task = (dc_find_example_task *) state;
- if (task->result) return FALSE;
- if ((task->to_find_example > 0) && (N->type == example_TNT)) {
- cdoc_example *E = RETRIEVE_POINTER_cdoc_example(N->content);
- if (E->number == task->to_find_example) {
- task->result = N;
- return FALSE;
- }
- }
- if ((task->to_find_heading) && (N->type == heading_TNT)) {
- cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(N->content);
- if ((E->level == 1) && (Str::eq(E->count, task->to_find_heading))) {
- task->result = N;
- return FALSE;
- }
- }
- if ((task->to_find_section) && (N->type == heading_TNT)) {
- cdoc_heading *E = RETRIEVE_POINTER_cdoc_heading(N->content);
- if ((E->level == 2) && (Str::eq_insensitive(E->recognition_name, task->to_find_section))) {
- task->result = N;
- return FALSE;
- }
- }
- return TRUE;
-}
diff --git a/inbuild/supervisor-module/Chapter 7/Documentation in Markdown.w b/inbuild/supervisor-module/Chapter 7/Documentation in Markdown.w
new file mode 100644
index 000000000..e1f3b2b78
--- /dev/null
+++ b/inbuild/supervisor-module/Chapter 7/Documentation in Markdown.w
@@ -0,0 +1,616 @@
+[DocumentationInMarkdown::] Documentation in Markdown.
+
+To provide a variation on Markdown for extension documentation.
+
+@ Plain CommonMark would not give us the bells and whistles we want, and would
+also allow rather more HTML liberty than is a good idea here. So:
+
+@e INFORM_HEADINGS_MARKDOWNFEATURE
+@e PASTE_ICONS_MARKDOWNFEATURE
+
+@e INFORM_EXAMPLE_HEADING_MIT
+@e INFORM_ERROR_MARKER_MIT
+
+=
+markdown_variation *extension_flavoured_Markdown = NULL;
+
+markdown_variation *DocumentationInMarkdown::extension_flavoured_Markdown(void) {
+ if (extension_flavoured_Markdown) return extension_flavoured_Markdown;
+ extension_flavoured_Markdown = MarkdownVariations::new(I"Inform-flavoured Markdown");
+ MarkdownVariations::remove_feature(extension_flavoured_Markdown, HTML_BLOCKS_MARKDOWNFEATURE);
+ MarkdownVariations::remove_feature(extension_flavoured_Markdown, INLINE_HTML_MARKDOWNFEATURE);
+
+ markdown_feature *Inform_headings = MarkdownVariations::new_feature(I"Inform_headings", INFORM_HEADINGS_MARKDOWNFEATURE);
+ METHOD_ADD(Inform_headings, POST_PHASE_I_MARKDOWN_MTID, DocumentationInMarkdown::Inform_headings_intervene_after_Phase_I);
+ MarkdownVariations::add_feature(extension_flavoured_Markdown, INFORM_HEADINGS_MARKDOWNFEATURE);
+
+ markdown_feature *paste_icons = MarkdownVariations::new_feature(I"paste icons", PASTE_ICONS_MARKDOWNFEATURE);
+ METHOD_ADD(paste_icons, RENDER_MARKDOWN_MTID, DocumentationInMarkdown::paste_icons_renderer);
+ METHOD_ADD(paste_icons, POST_PHASE_I_MARKDOWN_MTID, DocumentationInMarkdown::paste_icons_intervene_after_Phase_I);
+ MarkdownVariations::add_feature(extension_flavoured_Markdown, PASTE_ICONS_MARKDOWNFEATURE);
+
+ Markdown::new_container_block_type(INFORM_EXAMPLE_HEADING_MIT, I"INFORM_EXAMPLE_HEADING");
+ Markdown::new_leaf_block_type(INFORM_ERROR_MARKER_MIT, I"INFORM_ERROR_MARKER");
+
+ return extension_flavoured_Markdown;
+}
+
+@ Markdown paragraphs which take the following shapes are to be headings:
+= (text)
+ Chapter: Survey and Prospecting
+ Section: Black Gold
+ Example: *** Gelignite Anderson - A Tale of the Texas Oilmen
+=
+where in each case the colon can equally be a hyphen, and with optional
+space either side.
+
+=
+void DocumentationInMarkdown::Inform_headings_intervene_after_Phase_I(markdown_feature *feature,
+ markdown_item *tree, md_links_dictionary *link_references) {
+ int example_number = 0;
+ DocumentationInMarkdown::Inform_headings_r(tree, &example_number);
+ DocumentationInMarkdown::regroup_examples_r(tree, &example_number);
+ int section_number = 0, chapter_number = 0;
+ TEMPORARY_TEXT(latest)
+ DocumentationInMarkdown::number_headings_r(tree, §ion_number, &chapter_number, latest);
+ DISCARD_TEXT(latest)
+}
+
+void DocumentationInMarkdown::Inform_headings_r(markdown_item *md, int *example_number) {
+ if (md->type == PARAGRAPH_MIT) {
+ text_stream *line = md->stashed;
+ match_results mr = Regexp::create_mr();
+ if ((Regexp::match(&mr, line, L"Section *: *(%c+?)")) ||
+ (Regexp::match(&mr, line, L"Section *- *(%c+?)"))) {
+ MDBlockParser::change_type(NULL, md, HEADING_MIT);
+ Markdown::set_heading_level(md, 2);
+ Str::clear(line);
+ WRITE_TO(line, "%S", mr.exp[0]);
+ } else if ((Regexp::match(&mr, line, L"Chapter *: *(%c+?)")) ||
+ (Regexp::match(&mr, line, L"Chapter *- *(%c+?)"))) {
+ MDBlockParser::change_type(NULL, md, HEADING_MIT);
+ Markdown::set_heading_level(md, 1);
+ Str::clear(line);
+ WRITE_TO(line, "%S", mr.exp[0]);
+ } else if ((Regexp::match(&mr, line, L"Example *: *(%**) *(%c+?)")) ||
+ (Regexp::match(&mr, line, L"Example *- *(%**) *(%c+?)"))) {
+ MDBlockParser::change_type(NULL, md, INFORM_EXAMPLE_HEADING_MIT);
+ int star_count = Str::len(mr.exp[0]);
+ cdoc_example *new_eg = DocumentationCompiler::new_example_alone(mr.exp[1], NULL,
+ star_count, ++(*example_number));
+ if (star_count == 0) {
+ markdown_item *E = DocumentationInMarkdown::error_item(
+ I"this example should be marked (before the title) '*', '**', '***' or '****' for difficulty");
+ E->next = md->next; md->next = E;
+ }
+ if (star_count > 4) {
+ markdown_item *E = DocumentationInMarkdown::error_item(
+ I"four stars '****' is the maximum difficulty rating allowed");
+ E->next = md->next; md->next = E;
+ }
+ md->user_state = STORE_POINTER_cdoc_example(new_eg);
+ }
+ Regexp::dispose_of(&mr);
+ }
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ DocumentationInMarkdown::Inform_headings_r(ch, example_number);
+ }
+}
+
+markdown_item *DocumentationInMarkdown::error_item(text_stream *text) {
+ markdown_item *E = Markdown::new_item(INFORM_ERROR_MARKER_MIT);
+ E->stashed = Str::duplicate(text);
+ return E;
+}
+
+@ =
+void DocumentationInMarkdown::regroup_examples_r(markdown_item *md, int *example_number) {
+ if (md->type == INFORM_EXAMPLE_HEADING_MIT) {
+ if (md->down == NULL) {
+ markdown_item *run_from = md->next;
+ if (run_from) {
+ markdown_item *run_to = run_from, *prev = NULL;
+ while (run_to) {
+ if (run_to->type == INFORM_EXAMPLE_HEADING_MIT) break;
+ if ((run_to->type == HEADING_MIT) && (Markdown::get_heading_level(run_to) <= 2)) break;
+ prev = run_to;
+ run_to = run_to->next;
+ }
+ if (prev) {
+ md->down = run_from; md->next = run_to; prev->next = NULL;
+ }
+ }
+ }
+ }
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ DocumentationInMarkdown::regroup_examples_r(ch, example_number);
+ }
+}
+
+@ =
+void DocumentationInMarkdown::number_headings_r(markdown_item *md,
+ int *section_number, int *chapter_number, text_stream *latest) {
+ if (md->type == HEADING_MIT) {
+ switch (Markdown::get_heading_level(md)) {
+ case 1: {
+ md->user_state = STORE_POINTER_text_stream(md->stashed);
+ (*chapter_number)++;
+ (*section_number) = 0;
+ Str::clear(latest);
+ WRITE_TO(latest, "Chapter %d: %S", *chapter_number, md->stashed);
+ md->stashed = Str::duplicate(latest);
+ text_stream *url = Str::new();
+ WRITE_TO(url, "chapter%d.html", *chapter_number);
+ md->user_state = STORE_POINTER_text_stream(url);
+ break;
+ }
+ case 2: {
+ md->user_state = STORE_POINTER_text_stream(md->stashed);
+ (*section_number)++;
+ Str::clear(latest);
+ WRITE_TO(latest, "Section ");
+ if (*chapter_number > 0) WRITE_TO(latest, "%d.", *chapter_number);
+ WRITE_TO(latest, "%d: %S", *section_number, md->stashed);
+ md->stashed = Str::duplicate(latest);
+ text_stream *url = Str::new();
+ if (*chapter_number > 0)
+ WRITE_TO(url, "chapter%d.html", *chapter_number);
+ WRITE_TO(url, "#section%d", *section_number);
+ md->user_state = STORE_POINTER_text_stream(url);
+ break;
+ }
+ }
+ }
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ DocumentationInMarkdown::number_headings_r(ch, section_number, chapter_number, latest);
+ }
+}
+
+void DocumentationInMarkdown::paste_icons_intervene_after_Phase_I(markdown_feature *feature,
+ markdown_item *tree, md_links_dictionary *link_references) {
+ DocumentationInMarkdown::paiapi_r(tree);
+}
+
+void DocumentationInMarkdown::paiapi_r(markdown_item *md) {
+ markdown_item *current_sample = NULL;
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ if ((ch->type == CODE_BLOCK_MIT) && (Str::prefix_eq(ch->stashed, I"{*}", 3))) {
+ ch->user_state = STORE_POINTER_markdown_item(ch);
+ current_sample = ch;
+ Str::delete_first_character(ch->stashed);
+ Str::delete_first_character(ch->stashed);
+ Str::delete_first_character(ch->stashed);
+ } else if ((ch->type == CODE_BLOCK_MIT) &&
+ (Str::prefix_eq(ch->stashed, I"{**}", 3)) && (current_sample)) {
+ ch->user_state = STORE_POINTER_markdown_item(current_sample);
+ Str::delete_first_character(ch->stashed);
+ Str::delete_first_character(ch->stashed);
+ Str::delete_first_character(ch->stashed);
+ Str::delete_first_character(ch->stashed);
+ }
+ DocumentationInMarkdown::paiapi_r(ch);
+ if (ch->type == CODE_BLOCK_MIT) {
+ TEMPORARY_TEXT(detabbed)
+ for (int i=0, margin=0; istashed); i++) {
+ wchar_t c = Str::get_at(ch->stashed, i);
+ if (c == '\t') {
+ PUT_TO(detabbed, ' '); margin++;
+ while (margin % 4 != 0) { PUT_TO(detabbed, ' '); margin++; }
+ } else {
+ PUT_TO(detabbed, c); margin++;
+ if (c == '\n') margin = 0;
+ }
+ }
+ Str::clear(ch->stashed);
+ WRITE_TO(ch->stashed, "%S", detabbed);
+ DISCARD_TEXT(detabbed);
+ }
+ }
+}
+
+int DocumentationInMarkdown::paste_icons_renderer(markdown_feature *feature, text_stream *OUT,
+ markdown_item *md, int mode) {
+ if (md->type == HEADING_MIT) {
+ int L = Markdown::get_heading_level(md);
+ switch (L) {
+ case 1: HTML_OPEN("h2"); break;
+ case 2: HTML_OPEN("h3"); break;
+ case 3: HTML_OPEN("h4"); break;
+ case 4: HTML_OPEN("h5"); break;
+ default: HTML_OPEN("h6"); break;
+ }
+ TEMPORARY_TEXT(anchor)
+ if (L <= 2) {
+ text_stream *url = RETRIEVE_POINTER_text_stream(md->user_state);
+ for (int i=0; i 0) {
+ HTML_OPEN_WITH("span", "id=%S", anchor);
+ } else {
+ HTML_OPEN("span");
+ }
+ DISCARD_TEXT(anchor)
+ Markdown::render_extended(OUT, md->down, DocumentationInMarkdown::extension_flavoured_Markdown());
+ HTML_CLOSE("span");
+ switch (L) {
+ case 1: HTML_CLOSE("h2"); break;
+ case 2: HTML_CLOSE("h3"); break;
+ case 3: HTML_CLOSE("h4"); break;
+ case 4: HTML_CLOSE("h5"); break;
+ default: HTML_CLOSE("h6"); break;
+ }
+ return TRUE;
+ }
+ if (md->type == INFORM_EXAMPLE_HEADING_MIT) {
+ cdoc_example *E = RETRIEVE_POINTER_cdoc_example(md->user_state);
+ DocumentationInMarkdown::render_example_heading(OUT, E, NULL);
+ return TRUE;
+ }
+ if (md->type == CODE_BLOCK_MIT) {
+ DocumentationInMarkdown::render_code_block(OUT, md, mode);
+ return TRUE;
+ }
+ if (md->type == INFORM_ERROR_MARKER_MIT) {
+ HTML_OPEN_WITH("p", "class=\"documentationerrorbox\"");
+ HTML::begin_span(OUT, I"documentationerror");
+ WRITE("Error: %S", md->stashed);
+ HTML_CLOSE("span");
+ HTML_CLOSE("p");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+@ An example is set with a two-table header, and followed optionally by a
+table of its inset copy, shaded to distinguish it from the rest of the
+page. The heading is constructed with a main table of one row of two cells,
+in the following section. The left-hand cell then contains a further table,
+in the next section.
+
+=
+void DocumentationInMarkdown::render_example_heading(OUTPUT_STREAM, cdoc_example *E,
+ markdown_item *passage_node) {
+ TEMPORARY_TEXT(link)
+ WRITE_TO(link, "style=\"text-decoration: none\" href=\"eg%d.html\"", E->number);
+
+ HTML_TAG("hr"); /* rule a line before the example heading */
+ HTML::begin_plain_html_table(OUT);
+ HTML_OPEN("tr");
+
+ /* Left hand cell: the oval icon */
+ HTML_OPEN_WITH("td", "halign=\"left\" valign=\"top\" cellpadding=0 cellspacing=0 width=38px");
+ HTML_OPEN_WITH("span", "id=eg%d", E->number); /* provide the anchor point */
+ @;
+ HTML_CLOSE("span"); /* end the textual link */
+ HTML_CLOSE("td");
+
+ /* Right hand cell: the asterisks and title, with rubric underneath */
+ HTML_OPEN_WITH("td", "cellpadding=0 cellspacing=0 halign=\"left\" valign=\"top\"");
+
+ if (passage_node == NULL) HTML_OPEN_WITH("a", "%S", link);
+ for (int asterisk = 0; asterisk < E->star_count; asterisk++)
+ PUT(0x2605); /* the Unicode for "black star" emoji */
+ /* or 0x2B50 is the Unicode for "star" emoji */
+ /* or again, could use the asterisk.png image in the app */
+ WRITE(" ");
+ HTML_OPEN("b");
+ HTML::begin_span(OUT, I"indexdarkgrey");
+ WRITE(" Example ");
+ HTML::end_span(OUT);
+ HTML::begin_span(OUT, I"indexblack");
+ DocumentationRenderer::render_text(OUT, E->name);
+ HTML_TAG("br");
+ DocumentationRenderer::render_text(OUT, E->description);
+ HTML::end_span(OUT);
+ HTML_CLOSE("b");
+
+ if (passage_node == NULL) HTML_CLOSE("a"); /* Link does not cover body, only heading */
+
+ if (passage_node) {
+ while (passage_node) {
+ Markdown::render_extended(OUT, passage_node,
+ DocumentationInMarkdown::extension_flavoured_Markdown());
+ passage_node = passage_node->next;
+ }
+ }
+
+ HTML_CLOSE("td");
+ HTML_CLOSE("tr");
+ HTML::end_html_table(OUT);
+
+ DISCARD_TEXT(link)
+}
+
+@ The little oval icon with its superimposed boldface letter is much harder to
+get right on all browsers than it looks, and the following is the result of
+some pretty grim experimentation. Basically, we make a tight, borderless,
+one-cell-in-one-row table, use CSS to make a transparent PNG image of an oval
+the background image for the table, then put a boldface letter in the centre
+of its one and only cell. (Things were even worse when IE6 for Windows still
+had its infamous PNG transparency bug.)
+
+@ =
+ HTML::begin_plain_html_table(OUT);
+ HTML_OPEN_WITH("tr", "class=\"oval\"");
+ HTML_OPEN_WITH("td", "width=38px height=30px align=\"left\" valign=\"center\"");
+ if (passage_node == NULL) HTML_OPEN_WITH("a", "%S", link);
+ HTML_OPEN_WITH("div",
+ "class=\"paragraph Body\" style=\"line-height: 1px; margin-bottom: 0px; "
+ "margin-top: 0px; padding-bottom: 0pt; padding-top: 0px; text-align: center;\"");
+ HTML::begin_span(OUT, I"extensionexampleletter");
+ PUT(E->letter);
+ HTML::end_span(OUT);
+ HTML_CLOSE("div");
+ if (passage_node == NULL) HTML_CLOSE("a");
+ HTML_CLOSE("td");
+ HTML_CLOSE("tr");
+ HTML::end_html_table(OUT);
+
+@ =
+markdown_item *DocumentationInMarkdown::find_section(markdown_item *tree, text_stream *name) {
+ if (Str::len(name) == 0) return NULL;
+ markdown_item *result = NULL;
+ DocumentationInMarkdown::find(tree, name, &result);
+ return result;
+}
+
+void DocumentationInMarkdown::find(markdown_item *md, text_stream *name, markdown_item **result) {
+ if (md->type == HEADING_MIT) {
+ switch (Markdown::get_heading_level(md)) {
+ case 1:
+ case 2: {
+ int i=0;
+ for (; istashed); i++)
+ if (Str::get_at(md->stashed, i) == ':') { i+=2; break; }
+ if (i + Str::len(name) == Str::len(md->stashed)) {
+ int fail = FALSE;
+ for (int j=0; jstashed, i)) { fail = TRUE; break; }
+ if ((fail == FALSE) && (*result == NULL)) *result = md;
+ }
+ break;
+ }
+ }
+ }
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ DocumentationInMarkdown::find(ch, name, result);
+ }
+}
+
+@ =
+markdown_item *DocumentationInMarkdown::find_example(markdown_item *tree, int eg) {
+ if (eg <= 0) return NULL;
+ markdown_item *result = NULL;
+ int counter = 0;
+ DocumentationInMarkdown::find_e(tree, eg, &result, &counter);
+ return result;
+}
+
+void DocumentationInMarkdown::find_e(markdown_item *md, int eg, markdown_item **result, int *counter) {
+ if (md->type == INFORM_EXAMPLE_HEADING_MIT) {
+ (*counter)++;
+ if (*counter == eg) *result = md;
+ }
+ for (markdown_item *ch = md->down; ch; ch=ch->next) {
+ DocumentationInMarkdown::find_e(ch, eg, result, counter);
+ }
+}
+
+void DocumentationInMarkdown::render_code_block(OUTPUT_STREAM, markdown_item *md, int mode) {
+ if ((Str::eq_insensitive(md->info_string, I"inform")) ||
+ (Str::eq_insensitive(md->info_string, I"inform7")) ||
+ (Str::len(md->info_string) == 0)) {
+ @;
+ } else {
+ programming_language *pl = NULL;
+
+ if (mode & TAGS_MDRMODE) HTML_OPEN("pre");
+ TEMPORARY_TEXT(language)
+ for (int i=0; iinfo_string); i++) {
+ wchar_t c = Str::get_at(md->info_string, i);
+ if ((c == ' ') || (c == '\t')) break;
+ PUT_TO(language, c);
+ }
+ if (Str::len(language) > 0) {
+ TEMPORARY_TEXT(language_rendered)
+ md->sliced_from = language;
+ md->from = 0; md->to = Str::len(language) - 1;
+ MDRenderer::slice(language_rendered, md, mode | ENTITIES_MDRMODE);
+ if (mode & TAGS_MDRMODE)
+ HTML_OPEN_WITH("code", "class=\"language-%S\"", language_rendered);
+ pl = DocumentationCompiler::get_language(language_rendered);
+ if (pl == NULL) LOG("Unable to find language <%S>\n", language_rendered);
+ DISCARD_TEXT(language_rendered)
+ } else {
+ if (mode & TAGS_MDRMODE) HTML_OPEN("code");
+ }
+ DISCARD_TEXT(language)
+
+ Painter::reset_syntax_colouring(pl);
+ TEMPORARY_TEXT(line)
+ TEMPORARY_TEXT(line_colouring)
+ for (int k=0; kstashed); k++) {
+ if (Str::get_at(md->stashed, k) == '\n') {
+ @;
+ Str::clear(line);
+ Str::clear(line_colouring);
+ } else {
+ PUT_TO(line, Str::get_at(md->stashed, k));
+ }
+ if ((k == Str::len(md->stashed) - 1) && (Str::len(line) > 0)) @;
+ }
+ HTML_CLOSE("span");
+ DISCARD_TEXT(line)
+ DISCARD_TEXT(line_colouring)
+ if (mode & TAGS_MDRMODE) HTML_CLOSE("code");
+ if (mode & TAGS_MDRMODE) HTML_CLOSE("pre");
+ }
+}
+
+@ =
+ if (pl) Painter::syntax_colour(pl, NULL, line, line_colouring, FALSE);
+ DocumentationInMarkdown::syntax_coloured_code(OUT, line, line_colouring,
+ 0, Str::len(line), mode);
+ if (mode & TAGS_MDRMODE) WRITE(" "); else WRITE(" ");
+
+@ =
+ HTML_OPEN("blockquote");
+ if (GENERAL_POINTER_IS_NULL(md->user_state) == FALSE) {
+ markdown_item *first = RETRIEVE_POINTER_markdown_item(md->user_state);
+ TEMPORARY_TEXT(accumulated)
+ for (markdown_item *ch = md; ch; ch = ch->next) {
+ if (ch->type == CODE_BLOCK_MIT) {
+ if (GENERAL_POINTER_IS_NULL(ch->user_state) == FALSE) {
+ markdown_item *latest = RETRIEVE_POINTER_markdown_item(ch->user_state);
+ if (first == latest) WRITE_TO(accumulated, "%S", ch->stashed);
+ }
+ }
+ }
+ ExtensionWebsite::paste_button(OUT, accumulated);
+ }
+ TEMPORARY_TEXT(colouring)
+ programming_language *default_language = DocumentationCompiler::get_language(I"Inform");
+ programming_language *pl = default_language;
+ if (pl) {
+ Painter::reset_syntax_colouring(pl);
+ Painter::syntax_colour(pl, NULL, md->stashed, colouring, FALSE);
+ if (Str::eq(pl->language_name, I"Inform")) {
+ int ts = FALSE;
+ for (int i=0; istashed, i);
+ if (c == '[') ts = TRUE;
+ if (ts) Str::put_at(colouring, i, EXTRACT_COLOUR);
+ if (c == ']') ts = FALSE;
+ } else ts = FALSE;
+ }
+ }
+ }
+ HTML::begin_span(OUT, I"indexdullblue");
+ int tabulating = FALSE, tabular = FALSE, line_count = 0;
+ TEMPORARY_TEXT(line)
+ TEMPORARY_TEXT(line_colouring)
+ for (int k=0; kstashed); k++) {
+ if (Str::get_at(md->stashed, k) == '\n') {
+ @;
+ Str::clear(line);
+ Str::clear(line_colouring);
+ } else {
+ PUT_TO(line, Str::get_at(md->stashed, k));
+ PUT_TO(line_colouring, Str::get_at(colouring, k));
+ }
+ if (k == Str::len(md->stashed) - 1) @;
+ }
+ HTML_CLOSE("span");
+ if (tabulating) @;
+ HTML_CLOSE("blockquote");
+ DISCARD_TEXT(line)
+ DISCARD_TEXT(line_colouring)
+
+@ =
+ line_count++;
+ if (Str::is_whitespace(line)) tabular = FALSE;
+ match_results mr = Regexp::create_mr();
+ if (Regexp::match(&mr, line, L"Table %c*")) tabular = TRUE;
+ Regexp::dispose_of(&mr);
+ if (tabular) {
+ if (tabulating) {
+ @;
+ } else {
+ @;
+ tabulating = TRUE;
+ }
+ int cell_from = 0, cell_to = 0, i = 0;
+ @;
+ for (; i;
+ while (Str::get_at(line, i) == '\t') i++;
+ @;
+ i--;
+ } else {
+ cell_to++;
+ }
+ }
+ @;
+ @;
+ } else {
+ if (line_count > 1) HTML_TAG("br");
+ if (tabulating) {
+ @;
+ tabulating = FALSE;
+ }
+ int indentation = 1;
+ int z=0, spaces = 0;
+ for (; z =
+ HTML::end_span(OUT);
+ HTML_TAG("br");
+ HTML::begin_plain_html_table(OUT);
+ HTML::first_html_column(OUT, 0);
+
+@ =
+ DocumentationInMarkdown::syntax_coloured_code(OUT, line, line_colouring,
+ cell_from, cell_to, mode);
+ HTML::end_span(OUT);
+ HTML::next_html_column(OUT, 0);
+
+@ =
+ cell_from = i; cell_to = cell_from;
+ HTML::begin_span(OUT, I"indexdullblue");
+
+@ =
+ HTML::first_html_column(OUT, 0);
+
+@ =
+ HTML::end_html_row(OUT);
+
+@ =
+ HTML::end_html_table(OUT);
+ HTML::begin_span(OUT, I"indexdullblue");
+
+@ =
+void DocumentationInMarkdown::syntax_coloured_code(OUTPUT_STREAM, text_stream *text,
+ text_stream *colouring, int from, int to, int mode) {
+ wchar_t current_col = 0;
+ for (int i=from; i auto.inf
- 7.2% in step 5/15: load-binary-kits
- 5.7% in step 6/15: make-synoptic-module
- 1.9% in step 9/15: make-identifiers-unique
+ 7.0% in step 5/15: load-binary-kits
+ 5.9% in step 6/15: make-synoptic-module
+ 1.8% in step 9/15: make-identifiers-unique
0.3% in step 12/15: eliminate-redundant-operations
0.3% in step 4/15: compile-splats
0.3% in step 7/15: shorten-wiring
0.3% in step 8/15: detect-indirect-calls
2.3% not specifically accounted for
- 3.8% in supervisor
+ 3.7% in supervisor
0.8% not specifically accounted for
diff --git a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json
index 4ff7d3dbd..cbaa43901 100644
--- a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json
+++ b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "Architecture16Kit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"compatibility": "16-bit",
"kit-details": {
diff --git a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json
index bccbfad7f..f197ff069 100644
--- a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json
+++ b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "Architecture32Kit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"compatibility": "32-bit",
"kit-details": {
diff --git a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json
index e313ccbaa..9187d1bf2 100644
--- a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json
+++ b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "BasicInformKit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"needs": [ {
"need": {
diff --git a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json
index c530c85bc..83b51c09c 100644
--- a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json
+++ b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "CommandParserKit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"needs": [ {
"need": {
diff --git a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json
index ee82f90de..3a5363852 100644
--- a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json
+++ b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "EnglishLanguageKit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"needs": [ {
"need": {
diff --git a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json
index f88880243..8e9f73626 100644
--- a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json
+++ b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json
@@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "WorldModelKit",
- "version": "10.2.0-beta+6X03"
+ "version": "10.2.0-beta+6X04"
},
"needs": [ {
"need": {
diff --git a/inform7/Internal/PLs/Inform 6.ildf b/inform7/Internal/PLs/Inform6.ildf
similarity index 99%
rename from inform7/Internal/PLs/Inform 6.ildf
rename to inform7/Internal/PLs/Inform6.ildf
index de2bd1513..495fbf040 100644
--- a/inform7/Internal/PLs/Inform 6.ildf
+++ b/inform7/Internal/PLs/Inform6.ildf
@@ -1,4 +1,4 @@
-Name: "Inform 6"
+Name: "Inform6"
Details: "The C-like interactive fiction language Inform 6"
Extension: ".i6"
Line Comment: "!"