PHP familiarity shortcuts
This commit is contained in:
@@ -188,6 +188,10 @@ RENDER(Request& context)
|
||||
nibble(s, "-");
|
||||
?><li><?= (s) ?></li><?
|
||||
}
|
||||
else if(layout_class == "sig")
|
||||
{
|
||||
?><pre><? print(s); ?></pre><?
|
||||
}
|
||||
else if(layout_class == "params")
|
||||
{
|
||||
?><div><b><?= trim(nibble(s, ":")) ?></b> : <?= trim(s) ?></div><?
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
:sig
|
||||
StringMap array_merge(StringMap a, StringMap b)
|
||||
DTree array_merge(DTree a, DTree b)
|
||||
|
||||
:params
|
||||
a : left-hand source map or tree
|
||||
b : right-hand source map or tree
|
||||
return value : merged result
|
||||
|
||||
:desc
|
||||
Merges two maps or trees using PHP-like merge behavior.
|
||||
|
||||
For `StringMap`, keys from `b` overwrite keys from `a`.
|
||||
|
||||
For `DTree`, string keys from `b` overwrite keys from `a`. Numeric keys are appended and reindexed when either side behaves like a list.
|
||||
|
||||
This helper is intended as the closest UCE equivalent to PHP `array_merge()` for common request, config, and JSON-shaped data.
|
||||
|
||||
:see
|
||||
>types
|
||||
|
||||
:related
|
||||
**PHP:** `array_merge()`
|
||||
**JavaScript / Node.js:** Object spread, `Object.assign()`, or array concatenation depending on whether the data is map-like or list-like
|
||||
@@ -0,0 +1,19 @@
|
||||
:sig
|
||||
bool contains(String haystack, String needle)
|
||||
|
||||
:params
|
||||
haystack : string to search in
|
||||
needle : substring to look for
|
||||
return value : `true` when `needle` appears in `haystack`, otherwise `false`
|
||||
|
||||
:desc
|
||||
Returns whether `haystack` contains `needle`.
|
||||
|
||||
An empty `needle` always returns `true`.
|
||||
|
||||
:see
|
||||
>string
|
||||
|
||||
:related
|
||||
**PHP:** `str_contains()`
|
||||
**JavaScript / Node.js:** `String.prototype.includes()`
|
||||
@@ -0,0 +1,19 @@
|
||||
:sig
|
||||
void redirect(String url, s32 code = 302)
|
||||
|
||||
:params
|
||||
url : target URL for the redirect
|
||||
code : optional HTTP redirect status, defaults to `302`
|
||||
|
||||
:desc
|
||||
Sets the `Location` response header and updates the current HTTP status code.
|
||||
|
||||
Use this helper instead of manually assigning `context.header["Location"]` and `context.set_status(...)` when you want to redirect the current response.
|
||||
|
||||
:see
|
||||
set_status
|
||||
0_context
|
||||
|
||||
:related
|
||||
**PHP:** `header("Location: ...")` together with `http_response_code()` or implicit redirect semantics
|
||||
**JavaScript / Node.js:** `res.redirect(...)`, setting `Location`, or returning a redirect `Response`
|
||||
@@ -0,0 +1,17 @@
|
||||
:sig
|
||||
bool str_ends_with(String haystack, String needle)
|
||||
|
||||
:params
|
||||
haystack : string to inspect
|
||||
needle : suffix to compare against the end of `haystack`
|
||||
return value : `true` when `haystack` ends with `needle`, otherwise `false`
|
||||
|
||||
:desc
|
||||
Checks whether `haystack` ends with the given suffix.
|
||||
|
||||
:see
|
||||
>string
|
||||
|
||||
:related
|
||||
**PHP:** `str_ends_with()`
|
||||
**JavaScript / Node.js:** `String.prototype.endsWith()`
|
||||
@@ -0,0 +1,17 @@
|
||||
:sig
|
||||
bool str_starts_with(String haystack, String needle)
|
||||
|
||||
:params
|
||||
haystack : string to inspect
|
||||
needle : prefix to compare against the start of `haystack`
|
||||
return value : `true` when `haystack` begins with `needle`, otherwise `false`
|
||||
|
||||
:desc
|
||||
Checks whether `haystack` starts with the given prefix.
|
||||
|
||||
:see
|
||||
>string
|
||||
|
||||
:related
|
||||
**PHP:** `str_starts_with()`
|
||||
**JavaScript / Node.js:** `String.prototype.startsWith()`
|
||||
@@ -0,0 +1,22 @@
|
||||
:sig
|
||||
s64 strpos(String haystack, String needle, s64 offset = 0)
|
||||
|
||||
:params
|
||||
haystack : string to search in
|
||||
needle : substring to search for
|
||||
offset : optional start offset; negative values count from the end of the string
|
||||
return value : zero-based position of the first match, or `-1` if `needle` is not found
|
||||
|
||||
:desc
|
||||
Finds the first occurrence of `needle` inside `haystack`.
|
||||
|
||||
This is the closest UCE equivalent to PHP `strpos()`, but it returns `-1` instead of `false` when no match is found.
|
||||
|
||||
If `needle` is an empty string, `strpos()` returns the normalized start offset.
|
||||
|
||||
:see
|
||||
>string
|
||||
|
||||
:related
|
||||
**PHP:** `strpos()`
|
||||
**JavaScript / Node.js:** `String.prototype.indexOf()`
|
||||
@@ -0,0 +1,25 @@
|
||||
:sig
|
||||
String substr(String s, s64 start_pos)
|
||||
String substr(String s, s64 start_pos, s64 length)
|
||||
|
||||
:params
|
||||
s : source string
|
||||
start_pos : zero-based start position; negative values count from the end of the string
|
||||
length : optional substring length; negative values trim bytes from the end of the result range
|
||||
return value : extracted substring, or an empty string if the requested range is outside the source string
|
||||
|
||||
:desc
|
||||
Extracts part of a string using PHP-style start and length semantics.
|
||||
|
||||
Use the two-argument form to return everything from `start_pos` to the end of the string.
|
||||
|
||||
If `start_pos` is negative, counting starts from the end of the string.
|
||||
|
||||
If `length` is negative, the returned range stops that many bytes before the end of the string.
|
||||
|
||||
:see
|
||||
>string
|
||||
|
||||
:related
|
||||
**PHP:** `substr()`
|
||||
**JavaScript / Node.js:** `String.prototype.slice()` or `substring()`
|
||||
+3
-9
@@ -1,10 +1,4 @@
|
||||
|
||||
// Returns whether haystack contains needle (case-sensitive, both should be pre-lowercased)
|
||||
bool str_contains(String haystack, String needle)
|
||||
{
|
||||
return replace(haystack, needle, "\x01") != haystack;
|
||||
}
|
||||
|
||||
void render_hit(String ft, String name, String badge, String snippet)
|
||||
{
|
||||
<><div class="search-hit">
|
||||
@@ -51,8 +45,8 @@ RENDER(Request& context)
|
||||
}
|
||||
|
||||
String content = file_get_contents("pages/" + ft + ".txt");
|
||||
bool name_match = str_contains(to_lower(name), q);
|
||||
bool content_match = str_contains(to_lower(content), q);
|
||||
bool name_match = contains(to_lower(name), q);
|
||||
bool content_match = contains(to_lower(content), q);
|
||||
|
||||
if(!name_match && !content_match)
|
||||
continue;
|
||||
@@ -64,7 +58,7 @@ RENDER(Request& context)
|
||||
for(auto line : split(content, "\n"))
|
||||
{
|
||||
String t = trim(line);
|
||||
if(t.length() > 4 && t.substr(0, 1) != ":" && str_contains(to_lower(t), q))
|
||||
if(t.length() > 4 && t.substr(0, 1) != ":" && contains(to_lower(t), q))
|
||||
{
|
||||
snippet = t;
|
||||
if(snippet.length() > 120)
|
||||
|
||||
@@ -111,13 +111,14 @@ void render_see_section(String name)
|
||||
RENDER(Request& context)
|
||||
{
|
||||
|
||||
already_shown_items = new StringMap();
|
||||
StringMap shown_items;
|
||||
already_shown_items = &shown_items;
|
||||
|
||||
String page = first(context.get["p"], "index");
|
||||
|
||||
<><html>
|
||||
<head>
|
||||
<!--<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>-->
|
||||
<link rel="stylesheet" href='style.css?v=<?= time() ?>'></link>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
|
||||
+82
-34
@@ -1,24 +1,29 @@
|
||||
/* UCE Documentation — Theme
|
||||
Color palette: #139 deep-blue base · white text · yellow accents */
|
||||
Color palette: deep blue gradient · warm gold accents · frosted glass surfaces */
|
||||
|
||||
:root {
|
||||
--bg: #113399;
|
||||
--bg-surface: rgba(255, 255, 255, 0.065);
|
||||
--bg-surface-hover: rgba(255, 255, 255, 0.11);
|
||||
--bg-inset: rgba(0, 0, 0, 0.22);
|
||||
--bg-code: rgba(0, 0, 0, 0.28);
|
||||
--text: #e8ecf4;
|
||||
--text-dim: rgba(255, 255, 255, 0.55);
|
||||
--text-muted: rgba(255, 255, 255, 0.35);
|
||||
--accent: #ffd644;
|
||||
--accent-dim: rgba(255, 214, 68, 0.1);
|
||||
--accent-hover: #ffe680;
|
||||
--border: rgba(255, 255, 255, 0.08);
|
||||
--border-strong: rgba(255, 255, 255, 0.18);
|
||||
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
--font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;
|
||||
--radius: 8px;
|
||||
--radius-lg: 14px;
|
||||
--bg: #0b1d4e;
|
||||
--bg-grad: linear-gradient(168deg, #0f2462 0%, #0b1d4e 40%, #091840 100%);
|
||||
--bg-surface: rgba(255, 255, 255, 0.05);
|
||||
--bg-surface-hover: rgba(255, 255, 255, 0.09);
|
||||
--bg-inset: rgba(0, 0, 0, 0.3);
|
||||
--bg-code: rgba(0, 0, 0, 0.32);
|
||||
--text: #dfe5f2;
|
||||
--text-dim: rgba(200, 210, 235, 0.6);
|
||||
--text-muted: rgba(200, 210, 235, 0.35);
|
||||
--accent: #f0c430;
|
||||
--accent-dim: rgba(240, 196, 48, 0.08);
|
||||
--accent-hover: #ffd95c;
|
||||
--accent-glow: rgba(240, 196, 48, 0.15);
|
||||
--border: rgba(255, 255, 255, 0.06);
|
||||
--border-strong: rgba(255, 255, 255, 0.14);
|
||||
--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;
|
||||
--radius: 10px;
|
||||
--radius-lg: 16px;
|
||||
--ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@@ -52,8 +57,10 @@ body {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1rem;
|
||||
line-height: 1.65;
|
||||
background: var(--bg);
|
||||
background: var(--bg-grad);
|
||||
background-attachment: fixed;
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Typography ── */
|
||||
@@ -63,8 +70,9 @@ h1 {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
padding: 28px 0 20px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 32px 0 20px;
|
||||
border-bottom: 2px solid transparent;
|
||||
border-image: linear-gradient(90deg, var(--accent) 0%, rgba(240, 196, 48, 0.15) 100%) 1;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
@@ -131,15 +139,18 @@ a:hover {
|
||||
|
||||
.category {
|
||||
background: var(--bg-surface);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 14px 18px;
|
||||
margin-bottom: 10px;
|
||||
transition: border-color 150ms var(--ease);
|
||||
transition: border-color 200ms var(--ease), box-shadow 200ms var(--ease);
|
||||
}
|
||||
|
||||
.category:hover {
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.category h3 {
|
||||
@@ -190,23 +201,25 @@ a:hover {
|
||||
display: block;
|
||||
padding: 7px 12px;
|
||||
border-radius: 6px;
|
||||
transition: background 150ms var(--ease);
|
||||
transition: background 150ms var(--ease), transform 150ms var(--ease);
|
||||
}
|
||||
|
||||
.func-item a:hover {
|
||||
background: var(--bg-surface-hover);
|
||||
text-decoration: none;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 0.68rem;
|
||||
font-weight: 500;
|
||||
padding: 1px 7px;
|
||||
border-radius: 4px;
|
||||
margin-left: 6px;
|
||||
font-size: 0.65rem;
|
||||
font-weight: 600;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
margin-left: 8px;
|
||||
vertical-align: middle;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
color: var(--text-dim);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.dim {
|
||||
@@ -221,10 +234,13 @@ a:hover {
|
||||
|
||||
.doc-section {
|
||||
background: var(--bg-surface);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 20px 24px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.doc-section h3 {
|
||||
@@ -240,12 +256,22 @@ a:hover {
|
||||
line-height: 1.5;
|
||||
background: var(--bg-code);
|
||||
border-color: var(--border-strong);
|
||||
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.sig div {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.sig pre {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.params div {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
@@ -261,6 +287,23 @@ a:hover {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.related {
|
||||
background: var(--accent-dim);
|
||||
border: 1px solid rgba(240, 196, 48, 0.12);
|
||||
border-radius: var(--radius);
|
||||
padding: 14px 20px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.related div {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.related strong {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.see {
|
||||
background: transparent;
|
||||
border: none;
|
||||
@@ -333,9 +376,10 @@ pre {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.55;
|
||||
font-size: 0.86rem;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
code {
|
||||
@@ -365,9 +409,12 @@ li {
|
||||
|
||||
details {
|
||||
background: var(--bg-surface);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
margin-bottom: 16px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
summary {
|
||||
@@ -421,7 +468,7 @@ details pre {
|
||||
#doc-search:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 3px rgba(255, 214, 68, 0.12);
|
||||
box-shadow: 0 0 0 3px var(--accent-glow), var(--shadow-glow);
|
||||
}
|
||||
|
||||
.search-count {
|
||||
@@ -445,13 +492,14 @@ details pre {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
padding: 5px 12px;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
transition: background 120ms var(--ease);
|
||||
transition: background 120ms var(--ease), transform 120ms var(--ease);
|
||||
}
|
||||
|
||||
.search-hit:hover {
|
||||
background: var(--bg-surface-hover);
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.search-hit a {
|
||||
|
||||
Reference in New Issue
Block a user