Compare commits
5 commits
ci-testing
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f8708f2500 | |||
| 1aef9d6ee6 | |||
| 0987269307 | |||
| a38d93ba2a | |||
| 26ba5c90e6 |
8 changed files with 221 additions and 34 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
/target
|
||||
/result
|
||||
|
|
|
|||
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -86,9 +86,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.12.1"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
|
||||
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
|
|
@ -469,9 +469,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.25"
|
||||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a"
|
||||
checksum = "b915661dd01db3f05050265b2477bcc6527b3792388e2749b41623cc592be67d"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"globset",
|
||||
|
|
|
|||
22
Cargo.toml
22
Cargo.toml
|
|
@ -54,6 +54,7 @@ cast_sign_loss = "warn"
|
|||
checked_conversions = "warn"
|
||||
clear_with_drain = "warn"
|
||||
cloned_instead_of_copied = "warn"
|
||||
cmp_owned = "warn"
|
||||
coerce_container_to_any = "warn"
|
||||
collapsible_else_if = "allow"
|
||||
collapsible_if = "allow"
|
||||
|
|
@ -70,6 +71,7 @@ doc_link_code = "warn"
|
|||
doc_link_with_quotes = "warn"
|
||||
doc_markdown = "warn"
|
||||
doc_paragraphs_missing_punctuation = "warn"
|
||||
double_must_use = "warn"
|
||||
duration_suboptimal_units = "warn"
|
||||
empty_drop = "warn"
|
||||
empty_enum_variants_with_brackets = "warn"
|
||||
|
|
@ -80,6 +82,7 @@ error_impl_error = "warn"
|
|||
exit = "warn"
|
||||
expect_used = "warn"
|
||||
expl_impl_clone_on_copy = "warn"
|
||||
explicit_counter_loop = "warn"
|
||||
explicit_deref_methods = "warn"
|
||||
explicit_into_iter_loop = "warn"
|
||||
explicit_iter_loop = "warn"
|
||||
|
|
@ -107,6 +110,7 @@ index_refutable_slice = "warn"
|
|||
indexing_slicing = "warn"
|
||||
inefficient_to_string = "warn"
|
||||
infinite_loop = "warn"
|
||||
int_plus_one = "warn"
|
||||
integer_division = "warn"
|
||||
integer_division_remainder_used = "warn"
|
||||
into_iter_without_iter = "warn"
|
||||
|
|
@ -114,6 +118,7 @@ invalid_upcast_comparisons = "warn"
|
|||
ip_constant = "warn"
|
||||
iter_filter_is_ok = "warn"
|
||||
iter_filter_is_some = "warn"
|
||||
iter_kv_map = "warn"
|
||||
iter_not_returning_iterator = "warn"
|
||||
iter_on_empty_collections = "warn"
|
||||
iter_on_single_items = "warn"
|
||||
|
|
@ -129,14 +134,19 @@ literal_string_with_formatting_args = "warn"
|
|||
lossy_float_literal = "warn"
|
||||
macro_use_imports = "warn"
|
||||
manual_assert = "warn"
|
||||
manual_checked_ops = "warn"
|
||||
manual_ilog2 = "warn"
|
||||
manual_instant_elapsed = "warn"
|
||||
manual_is_multiple_of = "warn"
|
||||
manual_is_power_of_two = "warn"
|
||||
manual_is_variant_and = "warn"
|
||||
manual_let_else = "warn"
|
||||
manual_midpoint = "warn"
|
||||
manual_non_exhaustive = "allow"
|
||||
manual_option_zip = "warn"
|
||||
manual_pop_if = "warn"
|
||||
manual_string_new = "warn"
|
||||
manual_take = "warn"
|
||||
many_single_char_names = "warn"
|
||||
map_err_ignore = "warn"
|
||||
map_with_unused_argument_over_ranges = "warn"
|
||||
|
|
@ -179,15 +189,19 @@ option_option = "warn"
|
|||
panic_in_result_fn = "warn"
|
||||
path_buf_push_overwrite = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
possible_missing_else = "warn"
|
||||
pub_underscore_fields = "warn"
|
||||
pub_without_shorthand = "warn"
|
||||
question_mark = "warn"
|
||||
range_minus_one = "warn"
|
||||
range_plus_one = "warn"
|
||||
rc_buffer = "warn"
|
||||
rc_mutex = "warn"
|
||||
read_zero_byte_vec = "warn"
|
||||
redundant_clone = "warn"
|
||||
redundant_closure = "warn"
|
||||
redundant_closure_for_method_calls = "warn"
|
||||
redundant_iter_cloned = "warn"
|
||||
redundant_pub_crate = "warn"
|
||||
redundant_test_prefix = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
|
|
@ -195,6 +209,7 @@ ref_binding_to_reference = "warn"
|
|||
ref_option = "warn"
|
||||
ref_option_ref = "warn"
|
||||
renamed_function_params = "warn"
|
||||
replace_box = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
return_and_then = "warn"
|
||||
return_self_not_must_use = "warn"
|
||||
|
|
@ -235,12 +250,17 @@ unchecked_time_subtraction = "warn"
|
|||
unicode_not_nfc = "warn"
|
||||
uninlined_format_args = "warn"
|
||||
unnecessary_box_returns = "warn"
|
||||
unnecessary_cast = "warn"
|
||||
unnecessary_debug_formatting = "warn"
|
||||
unnecessary_fold = "warn"
|
||||
unnecessary_join = "warn"
|
||||
unnecessary_literal_bound = "warn"
|
||||
unnecessary_option_map_or_else = "warn"
|
||||
unnecessary_result_map_or_else = "warn"
|
||||
unnecessary_self_imports = "warn"
|
||||
unnecessary_semicolon = "warn"
|
||||
unnecessary_struct_initialization = "warn"
|
||||
unnecessary_trailing_comma = "warn"
|
||||
unnecessary_wraps = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unnested_or_patterns = "warn"
|
||||
|
|
@ -257,6 +277,8 @@ unwrap_in_result = "warn"
|
|||
unwrap_used = "warn"
|
||||
used_underscore_binding = "warn"
|
||||
used_underscore_items = "warn"
|
||||
useless_concat = "warn"
|
||||
useless_conversion = "warn"
|
||||
useless_let_if_seq = "warn"
|
||||
verbose_file_reads = "warn"
|
||||
volatile_composites = "warn"
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ You can learn more and see what en looks like by visiting the [homepage](https:/
|
|||
|
||||
## Install and run
|
||||
|
||||
See the [Documentation](https://en.jutty.dev/node/Documentation) page for instructions and how to install and start using en.
|
||||
See the [Get Started](https://en.jutty.dev/node/GetStarted) page for instructions and how to install and start using en.
|
||||
|
||||
## Roadmap
|
||||
|
||||
For a high-level view of what's in the future for en, see the [What's ahead section](https://en.jutty.dev/node/Introduction/#What's) of the docs Introduction.
|
||||
For a high-level view of what's in the future for en, see the [What's ahead section](https://en.jutty.dev/node/Introduction#What's) of the docs Introduction.
|
||||
|
||||
For a more detailed outline of what's planned, along with what's already been completed, see the [roadmap](https://en.jutty.dev/node/Roadmap).
|
||||
|
|
|
|||
26
flake.lock
generated
Normal file
26
flake.lock
generated
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1780453794,
|
||||
"narHash": "sha256-bXMRa9VTsHSPXL4Cw8R6JJLQeY3Y/IP4+YJCYVmQ7FY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6b316287bae2ee04c9b93c8c858d930fd07d7338",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"ref": "nixos-26.05",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
80
flake.nix
Normal file
80
flake.nix
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
description = "A non-linear writing instrument.";
|
||||
|
||||
inputs.nixpkgs.url = "nixpkgs/nixos-26.05";
|
||||
|
||||
outputs = { nixpkgs, self }: let
|
||||
name = "en";
|
||||
version = "0.4.0";
|
||||
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
|
||||
nixpkgsFor = forAllSystems (system: import nixpkgs {
|
||||
inherit system;
|
||||
});
|
||||
|
||||
in {
|
||||
packages = forAllSystems (system: let
|
||||
pkgs = nixpkgsFor.${system};
|
||||
in {
|
||||
default = pkgs.rustPlatform.buildRustPackage {
|
||||
inherit name version;
|
||||
src = ./.;
|
||||
|
||||
cargoHash =
|
||||
"sha256-"
|
||||
+ "em229cShq/IShRnxlp5mgcIu7pIOf0LflV8Pw0lLUEY=";
|
||||
};
|
||||
});
|
||||
|
||||
apps = forAllSystems (system: {
|
||||
default = {
|
||||
type = "app";
|
||||
program =
|
||||
"${self.packages.${system}.default}/bin/en";
|
||||
};
|
||||
});
|
||||
|
||||
devShells = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system}; in {
|
||||
default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
rustup
|
||||
just
|
||||
watchexec
|
||||
cargo-deny
|
||||
cargo-llvm-cov
|
||||
cargo-mutants
|
||||
go-tools
|
||||
typos
|
||||
taplo
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
nixosModules.bot = { config, lib, system, ... }: {
|
||||
options.within.services.en.enable =
|
||||
lib.mkEnableOption "enable en server";
|
||||
|
||||
config = lib.mkIf config.within.services.en.enable {
|
||||
systemd.services.en = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
"${self.packages."${system}".default}/bin/en";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
|
@ -6,7 +6,33 @@
|
|||
"type": "object",
|
||||
"$defs": {
|
||||
"node": {
|
||||
|
||||
"type": "object",
|
||||
"title": "Node",
|
||||
"description": "A node object.",
|
||||
"example": "[nodes.Earth]\ntext = \"Earth is a planet of the solar system.\"",
|
||||
"default": null,
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "The text content of this node."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "The node display title, useful to make it distinct from the ID.",
|
||||
"default": "The node's ID."
|
||||
},
|
||||
"listed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether this node is shown in listing pages.",
|
||||
"default": true
|
||||
},
|
||||
"redirect": {
|
||||
"type": "string",
|
||||
"description": "A node ID to where any requests for this node will be redirected.",
|
||||
"default": null
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
|
@ -23,33 +49,7 @@
|
|||
"default": null,
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"title": "Node",
|
||||
"description": "A node object.",
|
||||
"example": "[nodes.Earth]\ntext = \"Earth is a planet of the solar system.\"",
|
||||
"default": null,
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "The text content of this node."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "The node display title, useful to make it distinct from the ID.",
|
||||
"default": "The node's ID."
|
||||
},
|
||||
"listed": {
|
||||
"type": "boolean",
|
||||
"description": "Whether this node is shown in listing pages.",
|
||||
"default": true
|
||||
},
|
||||
"redirect": {
|
||||
"type": "string",
|
||||
"description": "A node ID to where any requests for this node will be redirected.",
|
||||
"default": null
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"$ref": "#/$defs/node"
|
||||
},
|
||||
"propertyNames": {
|
||||
"pattern": "^[^-][^!@#$%^&*;:/~| \\]\\[()\\\\]*$"
|
||||
|
|
|
|||
|
|
@ -842,6 +842,64 @@ en must differentiate node anchors from outgoing URLs:
|
|||
It does this by looking at the destination and checking if it contains a `/` or `:`. That's one more reason to avoid these characters in your node IDs.
|
||||
"""
|
||||
|
||||
[nodes.Customization]
|
||||
text = """
|
||||
You can customize several aspects of en by overriding its default templates, styles and other assets.
|
||||
|
||||
## The `public` directory
|
||||
|
||||
The `static/public` directory is searched by en in the current working directory and can also be |passed as a command line option|CLI. All files placed inside this directory will be served by the en server as static files. You can create directories and organize files as you see fit, and then reference them through custom templates and includes.
|
||||
|
||||
If you place a file in a default path, it will override the default. Namely:
|
||||
|
||||
- `static/public/assets/favicon.svg`: Website icon as seen on tabs and other UI elements
|
||||
- `static/public/assets/style.css`: Main CSS stylesheet
|
||||
- `static/public/assets/fonts/fonts.css`: Fonts CSS index mapping the default families `sans`, `serifed`, `mono`, `prose` and `title`. The `prose` family is used for paragraphs such as in the node text content, while the `sans` family is used for UI elements such as the navigation bar and footer.
|
||||
|
||||
The en server supports a variety of file types including plain text; data formats such as CSV, TOML and JSON; various font and image formats; and document formats such as PDF and EPUB. If you want to serve a file with a mimetype that is not included among the |builtin ones|https://codeberg.org/jutty/en/src/branch/main/src/router/handlers/mime.rs|, you can use the `mimes` |configuration option|Configuration#mimes|. If you don't, the file will be served with mimetype `application/octet-stream`, which may or may not work depending on what you are actually serving and how it's being consumed.
|
||||
|
||||
## Styles
|
||||
|
||||
You can override the default CSS and fonts using custom CSS files.
|
||||
|
||||
To completely override the default style, you can place your replacement at the default path as explained in the previous section.
|
||||
|
||||
If you just want to add small customizations, this can be better accomplished by adding a CSS file as part of a custom headers include, as explained in the next section.
|
||||
|
||||
## Templates
|
||||
|
||||
en uses the Tera|https://keats.github.io/tera templating engine, which provides several features for creating your own templates.
|
||||
|
||||
When starting up, en will look for a `templates` directory in the current working directory. For each template, it looks up the corresponding filename inside this directory. If it can't find one, it will fallback to a default template.
|
||||
|
||||
For a list of templates along with their names, see the |templates directory|https://codeberg.org/jutty/en/src/branch/main/templates| in the source code repository.
|
||||
|
||||
See the |Tera documentation|https://keats.github.io/tera/docs for a more extensive description of the available features for writing templates.
|
||||
|
||||
### Includes
|
||||
|
||||
Overriding an entire template can be very verbose, considering the default templates attempt to handle various edge cases.
|
||||
|
||||
To make it easier to override the most common use cases, the following templates are consumed as "includes" in specific parts of the main templates if placed inside the `templates` directory with the suffix `.include.html`:
|
||||
|
||||
- `header`: Included at the end of the default templates' base header
|
||||
- `post-body`: Included after the body in the default base template
|
||||
- `favicon`: Replaces the default favicon code
|
||||
- `styles`: Replaces the default CSS links
|
||||
- `footer`: Replaces the footer
|
||||
- `navigation`: Replaces the navigation bar
|
||||
- `index-header`: Replaces the block showing the title and subtitle of the website in the index page
|
||||
- `index-list`: Replaces the block showing the list of nodes in the index page
|
||||
|
||||
For example, to override the block in the header of all pages that globally sets the CSS stylesheets, you can drop a file at `templates/styles.include.html` containing something like:
|
||||
|
||||
`
|
||||
<link href="https://cdn.example.com/external.css" rel="stylesheet">
|
||||
<link href="/static/assets/my-styles.css" rel="stylesheet">
|
||||
`
|
||||
|
||||
"""
|
||||
|
||||
[nodes.Graph]
|
||||
text = """
|
||||
A graph is a data structure composed of connected (and disconnected) nodes.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue