mirror of
https://github.com/alexhopeoconnor/DFTE.git
synced 2026-10-04 04:28:10 +10:00
feat: prepare DFTE 1.0.2
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# Async web responses
|
||||
|
||||
Build a `PlaceholderRegistry` once during setup, but allocate a fresh `TemplateContext` for each request. A shared context would mix rendering state when clients overlap.
|
||||
|
||||
```cpp
|
||||
#include <TemplateEngine.h>
|
||||
#include <TemplateEngineAsyncWeb.h>
|
||||
|
||||
std::shared_ptr<PlaceholderRegistry> registry;
|
||||
|
||||
void sendTemplate(AsyncWebServerRequest* request, const char* root) {
|
||||
auto context = std::make_shared<TemplateContext>();
|
||||
context->setRegistry(registry.get());
|
||||
TemplateRenderer::initializeContext(*context, root);
|
||||
request->onDisconnect([context]() mutable { context.reset(); });
|
||||
|
||||
AsyncWebServerResponse* response =
|
||||
TemplateEngineAsyncWeb::beginSafeTemplateResponse(
|
||||
request, "text/html; charset=utf-8", context, 128
|
||||
);
|
||||
request->send(response);
|
||||
}
|
||||
```
|
||||
|
||||
The response retains the context while it streams. Releasing the request-owned `shared_ptr` on disconnect prevents state from leaking into later requests.
|
||||
|
||||
Use [StreamingAsync](../examples/StreamingAsync/) for a complete SoftAP/captive-portal project.
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
@@ -0,0 +1,25 @@
|
||||
# Configuration and memory limits
|
||||
|
||||
DFTE object layouts depend on fixed `DFTE_*` compile-time limits. Define any changes through shared PlatformIO `build_flags` so the library and every consuming translation unit agree on the same layout.
|
||||
|
||||
```ini
|
||||
build_flags =
|
||||
-DDFTE_BUFFER_SIZE=768
|
||||
-DDFTE_MAX_STACK_DEPTH=24
|
||||
-DDFTE_PLACEHOLDER_NAME_SIZE=32
|
||||
-DDFTE_MAX_ITERATIONS=80
|
||||
```
|
||||
|
||||
| Flag | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `DFTE_BUFFER_SIZE` | 512 | Streaming buffer size in `TemplateContext` |
|
||||
| `DFTE_MAX_STACK_DEPTH` | 16 | Render stack frames; nested templates usually need two frames each |
|
||||
| `DFTE_PLACEHOLDER_NAME_SIZE` | 24 | Maximum token length including `%` characters |
|
||||
| `DFTE_PROGMEM_CHUNK_SIZE` | 512 | PROGMEM source copy window |
|
||||
| `DFTE_RAM_CHUNK_SIZE` | 128 | RAM source copy window |
|
||||
| `DFTE_MAX_ITERATIONS` | 50 | Safety cap for one render call |
|
||||
| `DFTE_MAX_PLACEHOLDERS_DEFAULT` | 16 | Default registry constructor capacity |
|
||||
|
||||
`DFTE_MAX_PLACEHOLDERS_DEFAULT` is only a constructor default; pass an explicit registry capacity where a device needs more. DeviceFramework runtime template parameters do not change DFTE’s compile-time object layout.
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
@@ -0,0 +1,16 @@
|
||||
# Development and releases
|
||||
|
||||
Released applications should use a public Git tag. While changing DFTE with a sibling library, select a local `symlink://` or `file://` dependency from an ignored PlatformIO override rather than changing tracked application dependencies.
|
||||
|
||||
Before a release, update `library.json`, `CHANGELOG.md`, and the relevant guides, then run:
|
||||
|
||||
```bash
|
||||
./scripts/check-docs.sh
|
||||
./scripts/test.sh compile --platform esp8266
|
||||
./scripts/test.sh compile --platform esp32
|
||||
./scripts/prepare-release.sh vMAJOR.MINOR.PATCH --tag
|
||||
```
|
||||
|
||||
Push the branch and annotated tag. GitHub Actions repeats the board-free compile checks, validates the package, and creates a GitHub Release from that version’s changelog section. It does not publish to the PlatformIO Registry.
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
@@ -0,0 +1,42 @@
|
||||
# Getting started
|
||||
|
||||
DFTE renders a named root template through a `TemplateContext`. Register templates and placeholder values once, then ask the renderer for fixed-size chunks until completion.
|
||||
|
||||
```cpp
|
||||
#include <Arduino.h>
|
||||
#include <TemplateEngine.h>
|
||||
|
||||
static const char ROOT[] PROGMEM = R"DFTE(
|
||||
<h1>%TITLE%</h1><p>Uptime: %UPTIME%</p>
|
||||
)DFTE";
|
||||
|
||||
PlaceholderRegistry registry;
|
||||
TemplateContext context;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
registry.registerProgmemData(PSTR("%TITLE%"), PSTR("DFTE Quickstart"));
|
||||
registry.registerRamData(PSTR("%UPTIME%"), []() -> const char* {
|
||||
static char value[16];
|
||||
snprintf(value, sizeof(value), "%lus", millis() / 1000);
|
||||
return value;
|
||||
});
|
||||
registry.registerProgmemTemplate(PSTR("%ROOT%"), ROOT);
|
||||
context.setRegistry(®istry);
|
||||
TemplateRenderer::initializeContext(context, PSTR("%ROOT%"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint8_t chunk[128];
|
||||
if (!TemplateRenderer::isComplete(context) && !TemplateRenderer::hasError(context)) {
|
||||
const size_t written = TemplateRenderer::renderNextChunk(context, chunk, sizeof(chunk));
|
||||
Serial.write(chunk, written);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`registerProgmemData()` is for static flash data. `registerRamData()` takes a getter for a value that can change as chunks are rendered. `registerProgmemTemplate()` lets a placeholder expand to another template.
|
||||
|
||||
For a buildable project, start with [HelloPlaceholder](../examples/HelloPlaceholder/). Next: [template language](TEMPLATE_LANGUAGE.md).
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
@@ -0,0 +1,20 @@
|
||||
# DFTE documentation
|
||||
|
||||
DFTE documentation is organised by the rendering problem being solved.
|
||||
|
||||
| I want to… | Read |
|
||||
| --- | --- |
|
||||
| Render a first template | [Getting started](GETTING_STARTED.md) |
|
||||
| Use placeholders, templates, conditions, dynamic fragments, or iterators | [Template language](TEMPLATE_LANGUAGE.md) |
|
||||
| Stream a response through ESPAsyncWebServer | [Async web responses](ASYNC_WEB.md) |
|
||||
| Change buffer, stack, or placeholder limits safely | [Configuration](CONFIGURATION.md) |
|
||||
| Build the standalone examples | [Examples](../examples/README.md) |
|
||||
| Run checks or prepare a release | [Testing](TESTING.md) · [Development](DEVELOPMENT.md) |
|
||||
|
||||
## Documentation rules
|
||||
|
||||
- The template-language guide owns DFTE semantics and lifecycle contracts.
|
||||
- The configuration guide owns ABI-sensitive build flags.
|
||||
- The project README is an entry point and example chooser, not a full API manual.
|
||||
|
||||
Back to the [project overview](../README.md).
|
||||
@@ -0,0 +1,30 @@
|
||||
# Template language and lifecycle
|
||||
|
||||
Every token has the form `%NAME%`. DFTE resolves it from a `PlaceholderRegistry` according to its registered type.
|
||||
|
||||
| Registered type | Purpose |
|
||||
| --- | --- |
|
||||
| `registerProgmemData()` | Static flash-resident text |
|
||||
| `registerRamData()` | Getter returning current `const char*` data |
|
||||
| `registerProgmemTemplate()` | Nested PROGMEM template |
|
||||
| `registerDynamicTemplate()` | Template fragment supplied at render time |
|
||||
| `registerConditional()` | Choose a true, false, or skipped delegate |
|
||||
| `registerIterator()` | Stream repeated item templates through an iterator handle |
|
||||
|
||||
## Context lifecycle
|
||||
|
||||
1. Populate a registry during setup.
|
||||
2. Attach it to a `TemplateContext`.
|
||||
3. Initialise the context with the root placeholder.
|
||||
4. Call `renderNextChunk()` until complete or error.
|
||||
5. Call `reset()` before reusing a completed context for another root.
|
||||
|
||||
Do not treat `isComplete()` as a success result by itself; check `hasError()` as well.
|
||||
|
||||
## Iterators
|
||||
|
||||
An iterator opens a handle, produces `IteratorItemView` values, then closes the handle. Handles are closed when rendering finishes, resets, stalls, or fails. The `open`, `next`, and `close` callbacks must therefore tolerate early termination.
|
||||
|
||||
Use [AsyncDashboardDemo](../examples/AsyncDashboardDemo/) for a complete iterator example. Use [NestedLayouts](../examples/NestedLayouts/) for partials and conditions.
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
@@ -0,0 +1,14 @@
|
||||
# Testing
|
||||
|
||||
The two PlatformIO Unity commands compile the complete DFTE test suites without uploading or executing them, so they require no attached board.
|
||||
|
||||
```bash
|
||||
./scripts/test.sh compile --platform esp8266
|
||||
./scripts/test.sh compile --platform esp32
|
||||
```
|
||||
|
||||
The test environments include the library sources with `test_build_src = yes`. CI runs both target checks on the maintained branch and pull requests.
|
||||
|
||||
The standalone examples are buildable PlatformIO projects; see [examples](../examples/README.md).
|
||||
|
||||
Back to [documentation](README.md) · [project overview](../README.md).
|
||||
Reference in New Issue
Block a user