1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-07 17:44:22 +03:00
inform7/services/html-module/Chapter 2/Source Links.w

78 lines
2.9 KiB
OpenEdge ABL

[SourceLinks::] Source Links.
To provide HTML links to an Inform source text, using the non-standard
"source" protocol.
@ Index and Problem pages generated by //inform7//, via the //index// and
//problems// modules, frequently need to have clickable icons linking to
positions in the source text; when these are clicked in the Inform UI
applications, the Source panel opens at the appropriate line.
This is done with a non-standard HTML protocol called |source:|, one of
two which the Inform UI apps must provide special handling for. For instance,
line 21 of file |Bits and Pieces/marbles.txt| has URL:
= (text)
source:Bits and Pieces/marbles.txt#line14
=
When an Inform app is viewing an extension project, there can also be
references to individual examples in that extension, and these are referred
to as "cases" since they are test cases when the app is testing the extension.
For example,
= (text)
source:Locksmith.i7x?case=B#line7
=
refers to line 7 of Example B of |Locksmith.i7x|.
@ Locations are given relative to the current project bundle. However, if
only a leafname is supplied, then this is read as a file within the |Source|
subfolder of the project bundle. (Thus it is not possible to have a
source link to a source file at the root of the project bundle: but this is
no loss, since source is not allowed to be kept there.) For instance,
line 14 of file |Source/story.ni| has URL
= (text)
source:story.ni#line14
=
The following routine writes the clickable source-reference icon, and
is the only place in Inform where |source:| URLs are generated.
=
inchar32_t source_link_case = 0;
void SourceLinks::set_case(text_stream *p) {
source_link_case = Characters::toupper(Str::get_first_char(p));
}
void SourceLinks::link(OUTPUT_STREAM, source_location sl, int nonbreaking_space) {
if (sl.file_of_origin) {
TEMPORARY_TEXT(fn)
WRITE_TO(fn, "%f", TextFromFiles::get_filename(sl.file_of_origin));
@<Truncate the path according to the current abbreviation@>;
@<Remove indication that the path is inside the Source directory@>;
if (nonbreaking_space) WRITE("&nbsp;"); else WRITE(" ");
if (source_link_case)
HTML_OPEN_WITH("a", "href=\"source:%S?case=%c#line%d\"",
fn, source_link_case, sl.line_number)
else
HTML_OPEN_WITH("a", "href=\"source:%S#line%d\"", fn, sl.line_number);
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/Reveal.png");
HTML_CLOSE("a");
DISCARD_TEXT(fn)
}
}
@ This rather clumsily simplifies links to make them relative.
@<Truncate the path according to the current abbreviation@> =
pathname *abbrev = HTML::get_link_abbreviation_path();
if (abbrev) {
TEMPORARY_TEXT(pp)
WRITE_TO(pp, "%p", abbrev);
int N = Str::len(pp);
if (Str::prefix_eq(fn, pp, N)) Str::delete_n_characters(fn, N+1);
DISCARD_TEXT(pp)
}
@<Remove indication that the path is inside the Source directory@> =
if ((Str::begins_with_wide_string(fn, U"Source")) &&
(Platform::is_folder_separator(Str::get_at(fn, 6))))
Str::delete_n_characters(fn, 7);