I think I need to change the documentation format
This commit is contained in:
@@ -3,5 +3,6 @@ Time and Date Functions
|
||||
time_precise
|
||||
time
|
||||
time_format_local
|
||||
time_format_relative
|
||||
time_format_utc
|
||||
time_parse
|
||||
|
||||
+53
-29
@@ -23,6 +23,8 @@ RENDER(Request& context)
|
||||
{
|
||||
|
||||
String page = first(context.get["p"], "index");
|
||||
String page_title = page;
|
||||
nibble(page_title, "_");
|
||||
|
||||
<><html>
|
||||
<head>
|
||||
@@ -34,7 +36,7 @@ RENDER(Request& context)
|
||||
<a href="index.uce">UCE Docs</a><?
|
||||
if(page != "index")
|
||||
{
|
||||
?><span class="dim"> / </span><?= page ?><?
|
||||
?><span class="dim"> / </span><?= page_title ?><?
|
||||
}
|
||||
?>
|
||||
</h1>
|
||||
@@ -78,6 +80,14 @@ RENDER(Request& context)
|
||||
<div class="func-item"><a href="?p=<?= uri_encode(ft) ?>"><?= fn ?><span class="badge">directive</span></a></div>
|
||||
<?
|
||||
}
|
||||
else if(ft.substr(0, 2) == "3_")
|
||||
{
|
||||
String fn = ft;
|
||||
String pre = nibble(fn, "_");
|
||||
?>
|
||||
<div class="func-item"><a href="?p=<?= uri_encode(ft) ?>"><?= fn ?><span class="badge">info</span></a></div>
|
||||
<?
|
||||
}
|
||||
else
|
||||
{
|
||||
?>
|
||||
@@ -135,18 +145,28 @@ RENDER(Request& context)
|
||||
{
|
||||
auto doc = split(file_get_contents("pages/"+page+".txt"), "\n");
|
||||
|
||||
// Pre-extract related lines for sidebar
|
||||
StringList rel_lines;
|
||||
bool in_rel = false;
|
||||
// Pre-extract sidebar-only sections so the article body stays focused.
|
||||
StringList equiv_lines;
|
||||
StringList see_lines;
|
||||
String sidebar_section = "";
|
||||
for(auto s : doc)
|
||||
{
|
||||
if(s == ":related") { in_rel = true; }
|
||||
else if(s != "" && s.substr(0, 1) == ":") { in_rel = false; }
|
||||
else if(in_rel && s != "") { rel_lines.push_back(s); }
|
||||
if(s != "" && s.substr(0, 1) == ":")
|
||||
{
|
||||
sidebar_section = s.substr(1);
|
||||
}
|
||||
else if(sidebar_section == "related" && s != "")
|
||||
{
|
||||
equiv_lines.push_back(s);
|
||||
}
|
||||
else if(sidebar_section == "see" && s != "")
|
||||
{
|
||||
see_lines.push_back(s);
|
||||
}
|
||||
}
|
||||
|
||||
String detail_class = "detail-layout";
|
||||
if(rel_lines.size() == 0) detail_class += " no-sidebar";
|
||||
if(equiv_lines.size() == 0 && see_lines.size() == 0) detail_class += " no-sidebar";
|
||||
?><div class="<?= detail_class ?>">
|
||||
<article class="doc-detail"><?
|
||||
String layout_class = "text";
|
||||
@@ -169,7 +189,7 @@ RENDER(Request& context)
|
||||
?></div><?
|
||||
}
|
||||
|
||||
section_hidden = (new_class == "related");
|
||||
section_hidden = (new_class == "related" || new_class == "see");
|
||||
layout_class = new_class;
|
||||
|
||||
if(!section_hidden)
|
||||
@@ -191,10 +211,6 @@ RENDER(Request& context)
|
||||
{
|
||||
?><h3>Description</h3><?
|
||||
}
|
||||
else if(layout_class == "see")
|
||||
{
|
||||
?><h3>Related</h3><?
|
||||
}
|
||||
else
|
||||
{
|
||||
?><h3><?= layout_class ?></h3><?
|
||||
@@ -216,17 +232,6 @@ RENDER(Request& context)
|
||||
{
|
||||
?><div><b><?= trim(nibble(s, ":")) ?></b> : <?= trim(s) ?></div><?
|
||||
}
|
||||
else if(layout_class == "see")
|
||||
{
|
||||
if(s[0] == '>')
|
||||
{
|
||||
render_see_section(s.substr(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
?><div><a href="index.uce?p=<?= trim(s) ?>"><?= trim(s) ?><span class="dim">()</span></a></div><?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
?><div><?: markdown_to_html(s) ?></div><?
|
||||
@@ -239,14 +244,33 @@ RENDER(Request& context)
|
||||
}
|
||||
?></article><?
|
||||
|
||||
if(rel_lines.size() > 0)
|
||||
if(equiv_lines.size() > 0 || see_lines.size() > 0)
|
||||
{
|
||||
?><aside class="detail-sidebar">
|
||||
<div class="sidebar-card">
|
||||
<h3>PHP & JS Equivalents</h3><?
|
||||
for(auto rl : rel_lines)
|
||||
<div class="sidebar-card"><?
|
||||
if(equiv_lines.size() > 0)
|
||||
{
|
||||
?><div><?: markdown_to_html(rl) ?></div><?
|
||||
?><h3>PHP & JS Equivalents</h3><?
|
||||
for(auto rl : equiv_lines)
|
||||
{
|
||||
?><div><?: markdown_to_html(rl) ?></div><?
|
||||
}
|
||||
}
|
||||
|
||||
if(see_lines.size() > 0)
|
||||
{
|
||||
?><h3 class="sidebar-subhead">Related</h3><?
|
||||
for(auto sl : see_lines)
|
||||
{
|
||||
if(sl[0] == '>')
|
||||
{
|
||||
render_see_section(sl.substr(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
?><div><a href="index.uce?p=<?= trim(sl) ?>"><?= trim(sl) ?><span class="dim">()</span></a></div><?
|
||||
}
|
||||
}
|
||||
}
|
||||
?></div>
|
||||
</aside><?
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
:sig
|
||||
DTree
|
||||
|
||||
:desc
|
||||
Dynamic tree/container type used throughout UCE for structured data.
|
||||
|
||||
:Overview
|
||||
`DTree` is UCE's general-purpose structured value type.
|
||||
|
||||
This is the runtime's default container for nested data such as configuration trees, call payloads, decoded JSON, connection state, and metadata returned by runtime helpers.
|
||||
|
||||
:Value Kinds
|
||||
- `DTree` can hold:
|
||||
- `String`
|
||||
- `f64`
|
||||
- `bool`
|
||||
- pointer
|
||||
- nested map of child `DTree` values (map-shaped `DTree` values can be used to represent list-like data when the keys are numeric strings in sequence)
|
||||
|
||||
:Used in
|
||||
`context.var`
|
||||
`context.cfg`
|
||||
`context.call`
|
||||
`context.connection`
|
||||
`json_decode()` results
|
||||
`unit_call()` return values
|
||||
`unit_info()`
|
||||
|
||||
:Reading Values
|
||||
`["key"]` accesses or creates a child node.
|
||||
`.has("key")` checks whether a child exists without creating it.
|
||||
`.key("key")` returns a child pointer when it already exists.
|
||||
`.get_or_create("key")` returns a child pointer and creates it when missing.
|
||||
`.get_by_path("a/b/c")` traverses nested children without creating missing keys.
|
||||
`.to_string()` reads scalar content as text.
|
||||
`.to_s64()`, `.to_u64()`, and `.to_f64()` perform best-effort numeric conversion.
|
||||
`.to_bool()` performs best-effort boolean conversion.
|
||||
`.to_stringmap()` converts a map-shaped tree into `StringMap`.
|
||||
|
||||
`operator[]` creates missing entries, just like `std::map`.
|
||||
`.has()` and `.key()` are the non-mutating lookup helpers.
|
||||
`.get_by_path()` is the non-creating traversal helper.
|
||||
`.json_decode()` currently stores JSON numbers as string-valued `DTree` nodes, so typed numeric conversion is the normal way to consume those values.
|
||||
References are dereferenced automatically in most normal reads.
|
||||
|
||||
:Conversion Rules
|
||||
Scalar-looking strings are trimmed before numeric and boolean parsing.
|
||||
`.to_bool()` understands common textual forms such as `true`, `false`, `yes`, `no`, `1`, and `0`.
|
||||
`bool` values convert numerically to `1` / `0`.
|
||||
Pointer values convert numerically when read as numbers.
|
||||
Single-value maps can act as scalar wrappers for numeric and boolean conversion.
|
||||
Invalid numeric input falls back to `0`.
|
||||
`.to_stringmap()` converts map children key-by-key using each child's `to_string()`.
|
||||
|
||||
:Writing Values
|
||||
`.set(String)`
|
||||
`.set(f64)`
|
||||
`.set_bool(bool)`
|
||||
`.set(StringMap)`
|
||||
`.set_array()`
|
||||
`.push(...)`
|
||||
`.pop()`
|
||||
`.remove(key)`
|
||||
`.clear()`
|
||||
|
||||
Use `.set_array()` when you want list-style behavior with `push()` / `pop()`.
|
||||
|
||||
:Inspection Helpers
|
||||
`.has(key)`
|
||||
`.key(key)`
|
||||
`.get_or_create(key)`
|
||||
`.get_type_name()`
|
||||
`.is_array()`
|
||||
`.is_list()`
|
||||
`.to_json()`
|
||||
|
||||
:each()
|
||||
`each(std::function<void (DTree t, String key)> f)` iterates over the current tree value.
|
||||
|
||||
For map-shaped `DTree` values, the callback is invoked once for each child entry and receives:
|
||||
`t` as the child value
|
||||
`key` as the child key
|
||||
|
||||
For non-map values, `each()` still invokes the callback once:
|
||||
`t` is the current value
|
||||
`key` is an empty string
|
||||
|
||||
Typical usage:
|
||||
`context.var["items"].each([&](DTree item, String key) { print(key, ": ", item.to_string(), "\n"); });`
|
||||
|
||||
:Examples
|
||||
`String theme = context.cfg.get_by_path("theme/key").to_string()`
|
||||
|
||||
`u64 compiled_mtime = unit_info("test/hello.uce")["compiled_mtime"].to_u64()`
|
||||
|
||||
`bool dark_mode = context.call["dark_mode"].to_bool()`
|
||||
|
||||
`if(DTree* user = payload.key("user")) { print(user->to_json()); }`
|
||||
|
||||
`payload.get_or_create("headers")->get_or_create("Content-Type")->set("text/plain")`
|
||||
|
||||
`StringMap headers = payload["headers"].to_stringmap()`
|
||||
|
||||
:related
|
||||
**PHP:** Nested associative arrays, `stdClass`, decoded JSON trees, and helper accessors for deep array paths.
|
||||
**JavaScript / Node.js:** Plain objects, arrays, `Map`, and JSON-shaped data passed between handlers.
|
||||
|
||||
:see
|
||||
>types
|
||||
get_by_path
|
||||
json_decode
|
||||
@@ -1,32 +0,0 @@
|
||||
:sig
|
||||
DTree
|
||||
|
||||
:desc
|
||||
Dynamic tree/container type used throughout UCE for structured data.
|
||||
|
||||
`DTree` can hold a `String`, `f64`, `bool`, pointer, or a nested map of child `DTree` values.
|
||||
|
||||
Use `t["key"]` to access or create child entries. Use `push()` / `pop()` when treating it like an array-like container with numeric string keys.
|
||||
|
||||
Common uses include:
|
||||
- `json_decode()` / `json_encode()`
|
||||
- `context.var`
|
||||
- `context.call`
|
||||
- `unit_call()` return values
|
||||
|
||||
Useful methods include:
|
||||
- `to_string()`
|
||||
- `to_json()`
|
||||
- `get_type_name()`
|
||||
- `get_by_path()`
|
||||
- `set_bool()`
|
||||
- `remove()`
|
||||
- `clear()`
|
||||
- `each()`
|
||||
|
||||
:related
|
||||
**PHP:** Nested associative arrays, `stdClass`, decoded JSON trees, and helper accessors for deep array paths.
|
||||
**JavaScript / Node.js:** Plain objects, arrays, `Map`, and JSON-shaped data passed between handlers.
|
||||
|
||||
:see
|
||||
>types
|
||||
@@ -8,6 +8,23 @@ return value : a DTree object containing the deserialized JSON data
|
||||
:desc
|
||||
Deserializes 's' into a DTree structure.
|
||||
|
||||
The returned structure is usually consumed through `DTree` accessors such as:
|
||||
- `tree["key"].to_string()`
|
||||
- `tree["count"].to_u64()`
|
||||
- `tree["enabled"].to_bool()`
|
||||
|
||||
Current runtime note:
|
||||
- JSON objects and arrays become map-shaped `DTree` values
|
||||
- JSON booleans become native `bool` `DTree` values
|
||||
- JSON strings become native `String` `DTree` values
|
||||
- JSON numbers currently deserialize as string-valued `DTree` nodes, so typed conversions like `to_f64()` and `to_u64()` are the normal way to read numeric content
|
||||
|
||||
:see
|
||||
DTree
|
||||
json_encode
|
||||
to_bool
|
||||
to_f64
|
||||
to_u64
|
||||
|
||||
:related
|
||||
**PHP:** `json_decode()`
|
||||
|
||||
@@ -105,6 +105,18 @@ Returns a formatted date. This is based on the Linux date() command. The formatt
|
||||
|
||||
%Z alphabetic time zone abbreviation (e.g., EDT)
|
||||
|
||||
%deltaS total elapsed seconds between the timestamp and now
|
||||
|
||||
%deltaM total elapsed minutes between the timestamp and now
|
||||
|
||||
%deltaH total elapsed hours between the timestamp and now
|
||||
|
||||
%deltad total elapsed days between the timestamp and now
|
||||
|
||||
%deltam total elapsed 30-day months between the timestamp and now
|
||||
|
||||
%deltaY total elapsed 365-day years between the timestamp and now
|
||||
|
||||
By default, date pads numeric fields with zeroes. The following
|
||||
optional flags may follow '%':
|
||||
|
||||
@@ -123,6 +135,7 @@ Returns a formatted date. This is based on the Linux date() command. The formatt
|
||||
|
||||
:see
|
||||
>time
|
||||
>time_format_relative
|
||||
|
||||
:related
|
||||
**PHP:** `date()` and `DateTime` formatting in the server local timezone
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
:sig
|
||||
String time_format_relative(u64 timestamp, String format_very_recent = "", u64 medium_recency_seconds = 0, String format_medium_recent = "", u64 not_recent_seconds = 0, String format_not_recent = "")
|
||||
|
||||
:params
|
||||
timestamp : Unix timestamp to compare against the current time
|
||||
format_very_recent : output format for very recent timestamps, defaults to `just now`
|
||||
medium_recency_seconds : cutoff between the very-recent and medium-recent formats, defaults to `90`
|
||||
format_medium_recent : output format for medium-recent timestamps, defaults to `%deltaM minutes ago`
|
||||
not_recent_seconds : cutoff between the medium-recent and not-recent formats, defaults to `5400`
|
||||
format_not_recent : output format for older timestamps, defaults to `%deltaH hours ago`
|
||||
return value : a formatted relative-time string
|
||||
|
||||
:desc
|
||||
Formats a timestamp relative to the current time using the same formatting engine as `time_format_local()` and `time_format_utc()`.
|
||||
|
||||
The chosen format depends on the elapsed time:
|
||||
- if `now - timestamp` is less than `medium_recency_seconds`, use `format_very_recent`
|
||||
- else if it is less than `not_recent_seconds`, use `format_medium_recent`
|
||||
- otherwise use `format_not_recent`
|
||||
|
||||
The custom relative-time sequences available in all time formatters are:
|
||||
|
||||
:pre
|
||||
%deltaS total elapsed seconds between the timestamp and now
|
||||
|
||||
%deltaM total elapsed minutes between the timestamp and now
|
||||
|
||||
%deltaH total elapsed hours between the timestamp and now
|
||||
|
||||
%deltad total elapsed days between the timestamp and now
|
||||
|
||||
%deltam total elapsed 30-day months between the timestamp and now
|
||||
|
||||
%deltaY total elapsed 365-day years between the timestamp and now
|
||||
|
||||
:pre
|
||||
Default behavior examples:
|
||||
|
||||
time_format_relative(time() - 12)
|
||||
=> just now
|
||||
|
||||
time_format_relative(time() - 600)
|
||||
=> 10 minutes ago
|
||||
|
||||
time_format_relative(time() - 7200)
|
||||
=> 2 hours ago
|
||||
|
||||
:see
|
||||
>time
|
||||
>time_format_local
|
||||
>time_format_utc
|
||||
|
||||
:related
|
||||
**PHP:** `DateTimeImmutable` diff formatting or libraries such as Carbon `diffForHumans()`
|
||||
**JavaScript / Node.js:** relative time helpers such as `Intl.RelativeTimeFormat`, `date-fns/formatDistanceToNow`, or Luxon
|
||||
@@ -105,6 +105,18 @@ Returns a formatted date in the GMT/UTC timezone. This is based on the Linux dat
|
||||
|
||||
%Z alphabetic time zone abbreviation (e.g., EDT)
|
||||
|
||||
%deltaS total elapsed seconds between the timestamp and now
|
||||
|
||||
%deltaM total elapsed minutes between the timestamp and now
|
||||
|
||||
%deltaH total elapsed hours between the timestamp and now
|
||||
|
||||
%deltad total elapsed days between the timestamp and now
|
||||
|
||||
%deltam total elapsed 30-day months between the timestamp and now
|
||||
|
||||
%deltaY total elapsed 365-day years between the timestamp and now
|
||||
|
||||
By default, date pads numeric fields with zeroes. The following
|
||||
optional flags may follow '%':
|
||||
|
||||
@@ -123,6 +135,7 @@ Returns a formatted date in the GMT/UTC timezone. This is based on the Linux dat
|
||||
|
||||
:see
|
||||
>time
|
||||
>time_format_relative
|
||||
|
||||
:related
|
||||
**PHP:** `gmdate()` and UTC `DateTime` formatting
|
||||
|
||||
+35
-2
@@ -1,6 +1,35 @@
|
||||
/* UCE Documentation — Theme
|
||||
Color palette: deep blue gradient · warm gold accents · frosted glass surfaces */
|
||||
|
||||
@font-face {
|
||||
font-family: 'default_sans';
|
||||
src: url('../examples/uce-starter/themes/common/fonts/b612/b612-regular.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'default_sans';
|
||||
src: url('../examples/uce-starter/themes/common/fonts/b612/b612-bold.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'default_mono';
|
||||
src: url('../examples/uce-starter/themes/common/fonts/b612/b612-mono-regular.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'default_mono';
|
||||
src: url('../examples/uce-starter/themes/common/fonts/b612/b612-mono-bold.ttf') format('truetype');
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
:root {
|
||||
--bg: #113399;
|
||||
--bg-grad: linear-gradient(168deg, #1a3daa 0%, #113399 40%, #0d2880 100%);
|
||||
@@ -20,8 +49,8 @@
|
||||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.25);
|
||||
--shadow-glow: 0 0 20px rgba(240, 196, 48, 0.06);
|
||||
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;
|
||||
--font-sans: 'default_sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
--font-mono: 'default_mono', 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;
|
||||
--radius: 10px;
|
||||
--radius-lg: 16px;
|
||||
--ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
@@ -327,6 +356,10 @@ a:hover {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.sidebar-card .sidebar-subhead {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.sidebar-card div {
|
||||
padding: 3px 0;
|
||||
font-size: 0.875rem;
|
||||
|
||||
Reference in New Issue
Block a user