Sage
Welcome to Sage
Volume (69%) Hide Volume
Topics
Dynamic Content with MiniCalc
Sage offers two pairs of tags, which use MiniCalc to support dynamic content.


[=early] [@early]
[=late] [@late]


All four tags evaluate MiniCalc code, which is supplied after the tag, and terminated with an [end] tag.

The two "early" tags evaluate the MiniCalc code as the Sage file is being parsed. In contrast, the two "late" tags evaluate the MiniCalc code as the Sage article is being served up.

The two "@" tags evaluate the MiniCalc expression, and discard any result.

The two "=" tags evaluate the MiniCalc expression, convert it to a string, and uses this string as follows:

  • The [=early] tag parses the string as Sage content.

  • The [=late] tag emits the string as HTML content.

Important

  • These tags are not allowed outside of an article.

  • Each article is parsed and evaluated in its own MiniCalc environment. Declarations from one article are not visible to others.

  • To share code between articles in a volume, place that code in the Volume Script file.

  • The "early" tags are evaluated when an article is parsed, so for example…

    [wild][=early]@Now()[end][end]

    The above generates: 7/19/2024 1:08:43 PM (refreshing the web page will not update the time). Note the use of the [wild] tag here.

  • The "late" tags are evaluated when an article is served up, so for example…

    [wild][=late]@Now()[end][end]

    The above generates: 9/30/2024 7:16:24 PM (refreshing the web page will update the time). Note the use of the [wild] tag here.

  • Sage's Search feature is based on the plain text content of each article, generated during the startup phase of the web server. Therefore, output of [=late] tags, as seen by the search logic, is updated only when the web server restarts.


Example: URLs

Consider the following Sage code…

See Delphi's built-in [url https://docwiki.embarcadero.com/Libraries/Alexandria/en/ System.ParamCount]`ParamCount`[end] and [url https://docwiki.embarcadero.com/Libraries/Alexandria/en/ System.ParamStr]`ParamStr`[end] functions.

The above generates this content…


See Delphi's built-in ParamCount and ParamStr functions.


We can use MiniCalc to clean up the Sage code…

[@late] function RadURL(Page, Caption); const Base = 'https://docwiki.embarcadero.com/Libraries/Alexandria/en/' begin $'<a href="${Base}${Page}">${Caption}</a>'; end; [end] See Delphi's built-in `[=late]RadURL('System.ParamCount', 'ParamCount')[end]` and `[=late]RadURL('System.ParamStr', 'ParamStr')[end]` functions.

This generates the same content as before…


See Delphi's built-in ParamCount and ParamStr functions.


A similar effect can be achieved with the [@early] and [=early] tags…

[@early end=stop] function RadURL(Page, Caption); const Base = 'https://docwiki.embarcadero.com/Libraries/Alexandria/en/' begin $'[url "${Base}${Page}"]${Caption}[end]'; // see note below end; [stop] See Delphi's built-in `[=early]RadURL('System.ParamCount', 'ParamCount')[end]` and `[=early]RadURL('System.ParamStr', 'ParamStr')[end]` functions.

This generates the same content as before…


See Delphi's built-in ParamCount and ParamStr functions.


Note

The [@early] and [=early] tags will often need to override the [end] tag, as shown above. This is less often an issue for the "late" tags, as they generate HTML content, not Sage content.


Volume Scripts

As noted above, the [=early], [@early], [=late], and [@late] tags are not allowed outside an article. Additionally, each article is parsed and evaluated in its own MiniCalc environment. Thus, declarations from one article are not visible to others.

Fortunately, Sage does offer a way to share code across the various articles in a volume: Volume Scripts.

A Volume Script is a MiniCalc file with the same name as the Sage volume file, but with the .mc file extension. For example, the Volume Script for Info.vol.sage would be Info.vol.mc (same folder). When parsing a volume, and when generating an article, Sage automatically executes the Volume Script (if any). The result of the Volume Script is not used, but any functions or values defined in the script will be accessible in MiniCalc throughout the volume.

MiniCalc's @Include Function

MiniCalc offers a way to include one MiniCalc file in another: the @Include function.

To share code among several Sage volumes, place the code in a single .mc file, and each volume's Volume Script can include this file.

For example, suppose a folder contains A.vol.sage and B.vol.sage. In this same folder, if the file Shared.mc contains shared code, A.vol.mc and B.vol.mc would both contain this line:

@Include('Shared.mc');

The included file may be in a sub-folder, a parent folder, etc, but it must reside under the Sage Library Root folder.

The <Scripts> Virtual Folder

In Code Vault, and therefore on disk, we tend to organize volumes in a hierarchy, and this is reflected in the Volume Tree. This creates a problem for sharing code across volumes. Consider how to share code between these two volumes:

\Enterprise\Libraries\Database\VDB\VDB.vol.sage \Enterprise\Applications\GUI\VDB Explorer\VDBExplorer.vol.sage

In each of the Volume Scripts, we would include a shared MiniCalc file. If that file resides in the Enterprise folder from the above hierarchy (the common ancestor between the two volumes), then…

@Include('..\..\..\Shared.mc');

This is bad enough on its own, but it also means that we'd need to edit the Volume Script if we move the volume folder up or down in the tree.

Sage provides a solution to this issue: the <Scripts> virtual folder. MiniCalc filenames can use <Scripts> to refer to the top-level Scripts folder under the Sage Library Root.

For example, if we move the Shared.mc file from under \Enterprise to \Scripts\Enterprise, then…

@Include('<Scripts>\Enterprise\Shared.mc');

This way, we don't spend all day counting dots, and if volumes move up or down in the tree, this path remains accurate. It also makes it a breeze to share code across departments.

Theme-Sensitive Content

In MiniCalc code, the Sage.LightTheme and Sage.DarkTheme variables allow you to customize dynamic Sage content based on the user's theme choice. For example…

[@late] BGColor := Sage.DarkTheme ? '#404040' : '#E0E0E0'; FGColor := Sage.DarkTheme ? 'orange' : 'maroon'; FontStyle := @Format('background-color:%s;color:%s', [BGColor, FGColor]); [end] [=late]'<font style="' + FontStyle + '">&nbsp;Important&nbsp;</font>'[end]

The above generates this…


 Important 


To see the two options, toggle the Sage Theme in your web browser.

The Sage Object

MiniCalc code has access to an object named Sage, which offers the following properties…

Property Type Notes
DarkTheme Boolean Not available to "early" tags; Indicates whether the dark theme is active.
IsEarly Boolean If True, the Sage volume is being parsed; if False, a Sage article is being generated.
IsLate Boolean If True, a Sage article is being generated; if False, the Sage volume is being parsed.
LightTheme Boolean Not available to "early" tags; Indicates whether the light theme is active.
OnError function You can call this function to generate a Sage hint, warning, or error. The function takes between 2 and 4 arguments…
  1. Severity: an enum – @ssHint, @ssWarning, or @ssError;
  2. Message: a string specifying the message text;
  3. URL: a string specifying a URL for more info (the default is the empty string);
  4. LocationLevel: an Integer specifying how many levels up (in the function call stack) to report the source of the error (the default is zero).
ParserMode Enumeration Choices are: @smAuthoring, @smCompiling, or @smServing.

Last Modified: 7/19 1:08:04 pm
In this article (top)  View article's Sage markup
7/19 1:08:04 pm