mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-11-03 21:24:17 +00:00 
			
		
		
		
	Improve syntax highlighting in the language reference
Highlight all Slint code and don't do the preview on snippets where it doesn't make sense. Some snippets, such as the bare statement or expression snippets, are now highlighted, but they are continued to be excluded from the doctest.
This commit is contained in:
		
							parent
							
								
									1891e4489a
								
							
						
					
					
						commit
						ed5b76e7fc
					
				
					 5 changed files with 46 additions and 28 deletions
				
			
		| 
						 | 
					@ -59,7 +59,7 @@ Slint comes with a markup language that is specifically designed for user interf
 | 
				
			||||||
powerful way to describe graphical elements, their placement, and the flow of data through the different states. It is a familiar syntax to describe the hierarchy
 | 
					powerful way to describe graphical elements, their placement, and the flow of data through the different states. It is a familiar syntax to describe the hierarchy
 | 
				
			||||||
of elements and property bindings. Here's the obligatory "Hello World":
 | 
					of elements and property bindings. Here's the obligatory "Hello World":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: slint-no-preview
 | 
					.. code-block:: slint,ignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HelloWorld := Window {
 | 
					    HelloWorld := Window {
 | 
				
			||||||
        width: 400px;
 | 
					        width: 400px;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ You can also declare your own properties. The properties declared at the top lev
 | 
				
			||||||
component are public and can be accessed by the component using it as an element, or using the
 | 
					component are public and can be accessed by the component using it as an element, or using the
 | 
				
			||||||
language bindings:
 | 
					language bindings:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    // declare a property of type int with the name `my-property`
 | 
					    // declare a property of type int with the name `my-property`
 | 
				
			||||||
    property<int> my-property;
 | 
					    property<int> my-property;
 | 
				
			||||||
| 
						 | 
					@ -186,7 +186,7 @@ together.
 | 
				
			||||||
The right hand side of the `<=>` must be a reference to a property of the same type.
 | 
					The right hand side of the `<=>` must be a reference to a property of the same type.
 | 
				
			||||||
The type can be omitted in a property declaration to have the type automatically inferred.
 | 
					The type can be omitted in a property declaration to have the type automatically inferred.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Window {
 | 
					Example := Window {
 | 
				
			||||||
    property<brush> rect-color <=> r.background;
 | 
					    property<brush> rect-color <=> r.background;
 | 
				
			||||||
    // it is allowed to omit the type to have it automatically inferred
 | 
					    // it is allowed to omit the type to have it automatically inferred
 | 
				
			||||||
| 
						 | 
					@ -227,7 +227,7 @@ Anonymous structs type can be declared with curly braces: `{ identifier1: type2,
 | 
				
			||||||
The trailing semicolon is optional.
 | 
					The trailing semicolon is optional.
 | 
				
			||||||
They can be initialized with a struct literal: `{ identifier1: expression1, identifier2: expression2  }`
 | 
					They can be initialized with a struct literal: `{ identifier1: expression1, identifier2: expression2  }`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Window {
 | 
					Example := Window {
 | 
				
			||||||
    property<{name: string, score: int}> player: { name: "Foo", score: 100 };
 | 
					    property<{name: string, score: int}> player: { name: "Foo", score: 100 };
 | 
				
			||||||
    property<{a: int, }> foo: { a: 3 };
 | 
					    property<{a: int, }> foo: { a: 3 };
 | 
				
			||||||
| 
						 | 
					@ -238,7 +238,7 @@ Example := Window {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It is possible to define a named struct using the `struct` keyword,
 | 
					It is possible to define a named struct using the `struct` keyword,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
export struct Player := {
 | 
					export struct Player := {
 | 
				
			||||||
    name: string,
 | 
					    name: string,
 | 
				
			||||||
    score: int,
 | 
					    score: int,
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ Example := Window {
 | 
				
			||||||
The type array is using square brackets for example  `[int]` is an array of `int`. In the runtime, they are
 | 
					The type array is using square brackets for example  `[int]` is an array of `int`. In the runtime, they are
 | 
				
			||||||
basically used as models for the `for` expression.
 | 
					basically used as models for the `for` expression.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Window {
 | 
					Example := Window {
 | 
				
			||||||
    property<[int]> list-of-int: [1,2,3];
 | 
					    property<[int]> list-of-int: [1,2,3];
 | 
				
			||||||
    property<[{a: int, b: string}]> list-of-structs: [{ a: 1, b: "hello" }, {a: 2, b: "world"}];
 | 
					    property<[{a: int, b: string}]> list-of-structs: [{ a: 1, b: "hello" }, {a: 2, b: "world"}];
 | 
				
			||||||
| 
						 | 
					@ -280,7 +280,7 @@ Example := Window {
 | 
				
			||||||
* String can be converted to float by using the `to-float` function. That function returns 0 if the string is not
 | 
					* String can be converted to float by using the `to-float` function. That function returns 0 if the string is not
 | 
				
			||||||
   a valid number. you can check with `is-float` if the string contains a valid number
 | 
					   a valid number. you can check with `is-float` if the string contains a valid number
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Window {
 | 
					Example := Window {
 | 
				
			||||||
    // ok: int converts to string
 | 
					    // ok: int converts to string
 | 
				
			||||||
    property<{a: string, b: int}> prop1: {a: 12, b: 12 };
 | 
					    property<{a: string, b: int}> prop1: {a: 12, b: 12 };
 | 
				
			||||||
| 
						 | 
					@ -341,7 +341,7 @@ element comes with a `clicked` callback, that's emitted when the user touches th
 | 
				
			||||||
it with the mouse. In the example below, the emission of that callback is forwarded to another custom callback (`hello`) by declaring a
 | 
					it with the mouse. In the example below, the emission of that callback is forwarded to another custom callback (`hello`) by declaring a
 | 
				
			||||||
handler and emitting our custom callback:
 | 
					handler and emitting our custom callback:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    // declare a callback
 | 
					    // declare a callback
 | 
				
			||||||
    callback hello;
 | 
					    callback hello;
 | 
				
			||||||
| 
						 | 
					@ -358,7 +358,7 @@ Example := Rectangle {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It is also possible to add parameters to the callback.
 | 
					It is also possible to add parameters to the callback.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    // declares a callback
 | 
					    // declares a callback
 | 
				
			||||||
    callback hello(int, string);
 | 
					    callback hello(int, string);
 | 
				
			||||||
| 
						 | 
					@ -368,7 +368,7 @@ Example := Rectangle {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
And return value.
 | 
					And return value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    // declares a callback with a return value
 | 
					    // declares a callback with a return value
 | 
				
			||||||
    callback hello(int, int) -> int;
 | 
					    callback hello(int, int) -> int;
 | 
				
			||||||
| 
						 | 
					@ -380,7 +380,7 @@ Example := Rectangle {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It is possible to declare callback aliases in a similar way to two-way bindings:
 | 
					It is possible to declare callback aliases in a similar way to two-way bindings:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    callback clicked <=> area.clicked;
 | 
					    callback clicked <=> area.clicked;
 | 
				
			||||||
    area := TouchArea {}
 | 
					    area := TouchArea {}
 | 
				
			||||||
| 
						 | 
					@ -394,7 +394,7 @@ are typically used to combine basic arithmetic with access to properties of othe
 | 
				
			||||||
these properties change, the expression is automatically re-evaluated and a new value is assigned
 | 
					these properties change, the expression is automatically re-evaluated and a new value is assigned
 | 
				
			||||||
to the property the expression is associated with:
 | 
					to the property the expression is associated with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    // declare a property of type int
 | 
					    // declare a property of type int
 | 
				
			||||||
    property<int> my-property;
 | 
					    property<int> my-property;
 | 
				
			||||||
| 
						 | 
					@ -409,7 +409,7 @@ If something changes `my-property`, the width will be updated automatically.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Arithmetic in expression with numbers works like in most programming language with the operators `*`, `+`, `-`, `/`:
 | 
					Arithmetic in expression with numbers works like in most programming language with the operators `*`, `+`, `-`, `/`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    property <int> p: 1 * 2 + 3 * 4; // same as (1 * 2) + (3 * 4)
 | 
					    property <int> p: 1 * 2 + 3 * 4; // same as (1 * 2) + (3 * 4)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -422,7 +422,7 @@ There are also the operators `&&` and `||` for logical *and* and *or* between bo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can access properties by addressing the associated element, followed by a `.` and the property name:
 | 
					You can access properties by addressing the associated element, followed by a `.` and the property name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint
 | 
					```slint,no_run
 | 
				
			||||||
Example := Rectangle {
 | 
					Example := Rectangle {
 | 
				
			||||||
    foo := Rectangle {
 | 
					    foo := Rectangle {
 | 
				
			||||||
        x: 42px;
 | 
					        x: 42px;
 | 
				
			||||||
| 
						 | 
					@ -559,25 +559,25 @@ Inside callback handlers, more complicated statements are allowed:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Assignment:
 | 
					Assignment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
clicked => { some-property = 42; }
 | 
					clicked => { some-property = 42; }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Self-assignment with `+=` `-=` `*=` `/=`
 | 
					Self-assignment with `+=` `-=` `*=` `/=`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
clicked => { some-property += 42; }
 | 
					clicked => { some-property += 42; }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Calling a callback
 | 
					Calling a callback
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
clicked => { root.some-callback(); }
 | 
					clicked => { root.some-callback(); }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Conditional statements
 | 
					Conditional statements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
clicked => {
 | 
					clicked => {
 | 
				
			||||||
    if (condition) {
 | 
					    if (condition) {
 | 
				
			||||||
        foo = 42;
 | 
					        foo = 42;
 | 
				
			||||||
| 
						 | 
					@ -591,7 +591,7 @@ clicked => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Empty expression
 | 
					Empty expression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
clicked => { }
 | 
					clicked => { }
 | 
				
			||||||
// or
 | 
					// or
 | 
				
			||||||
clicked => { ; }
 | 
					clicked => { ; }
 | 
				
			||||||
| 
						 | 
					@ -684,11 +684,13 @@ Animation can be configured with the following parameter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It is also possible to animate several properties with the same animation:
 | 
					It is also possible to animate several properties with the same animation:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ignore
 | 
					```slint,ignore
 | 
				
			||||||
animate x, y { duration: 100ms; }
 | 
					animate x, y { duration: 100ms; }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is the same as
 | 
					is the same as
 | 
				
			||||||
```ignore
 | 
					
 | 
				
			||||||
 | 
					```slint,ignore
 | 
				
			||||||
animate x { duration: 100ms; }
 | 
					animate x { duration: 100ms; }
 | 
				
			||||||
animate y { duration: 100ms; }
 | 
					animate y { duration: 100ms; }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -1017,7 +1019,7 @@ instructions the Slint compiler to include the font and makes the font families
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For example:
 | 
					For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```slint,notest
 | 
					```slint,ignore
 | 
				
			||||||
import "./NotoSans-Regular.ttf";
 | 
					import "./NotoSans-Regular.ttf";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example := Window {
 | 
					Example := Window {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
<link rel="stylesheet" href="https://slint-ui.com/resources/highlightjs/11.0.1/default.min.css">
 | 
					<link rel="stylesheet" href="https://slint-ui.com/resources/highlightjs/11.0.1/default.min.css">
 | 
				
			||||||
<script src="https://slint-ui.com/resources/highlightjs/11.0.1/highlight.min.js"></script>
 | 
					<script src="https://slint-ui.com/resources/highlightjs/11.0.1/highlight.min.js"></script>
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
  hljs.registerLanguage("slint", function (hljs) {
 | 
					  function highlight_slint(hljs) {
 | 
				
			||||||
    const KEYWORDS = {
 | 
					    const KEYWORDS = {
 | 
				
			||||||
      keyword:
 | 
					      keyword:
 | 
				
			||||||
        'struct export import signal property animate for in if states transitions parent root self',
 | 
					        'struct export import signal property animate for in if states transitions parent root self',
 | 
				
			||||||
| 
						 | 
					@ -49,13 +49,19 @@
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      illegal: /@/
 | 
					      illegal: /@/
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  });
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Tags used in fenced code blocks
 | 
				
			||||||
 | 
					  for (let tag of ["slint", "slint,no_run", "slint,ignore"]) {
 | 
				
			||||||
 | 
					    hljs.registerLanguage(tag, highlight_slint);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  window.addEventListener("DOMContentLoaded", () => {
 | 
					  window.addEventListener("DOMContentLoaded", () => {
 | 
				
			||||||
    const rustDoc = document.querySelector('meta[name="generator"]')?.content == "rustdoc";
 | 
					    const rustDoc = document.querySelector('meta[name="generator"]')?.content == "rustdoc";
 | 
				
			||||||
    if (rustDoc) {
 | 
					    if (rustDoc) {
 | 
				
			||||||
      // Only highlight .slint blocks, leave the others to rustdoc
 | 
					      // Only highlight .slint blocks, leave the others to rustdoc
 | 
				
			||||||
      for (slintBlock of document.querySelectorAll(".language-slint")) {
 | 
					      for (slintBlock of document.querySelectorAll("[class*=language-slint]")) {
 | 
				
			||||||
        hljs.highlightElement(slintBlock)
 | 
					        hljs.highlightElement(slintBlock)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +95,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // The Sphinx/my_st generated HTML for code blocks does not use <code> tags, so highlight.js'
 | 
					      // The Sphinx/my_st generated HTML for code blocks does not use <code> tags, so highlight.js'
 | 
				
			||||||
      // default selector "pre code" does not match. Let's do it by hand:
 | 
					      // default selector "pre code" does not match. Let's do it by hand:
 | 
				
			||||||
      for (block of document.querySelectorAll("div.highlight-slint div.highlight pre, div.highlight-slint-no-preview div.highlight pre")) {
 | 
					      for (block of document.querySelectorAll("div[class*=highlight-slint] div.highlight pre")) {
 | 
				
			||||||
        hljs.highlightElement(block)
 | 
					        hljs.highlightElement(block)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function run() {
 | 
					    async function run() {
 | 
				
			||||||
        await slint.default();
 | 
					        await slint.default();
 | 
				
			||||||
        var elements = document.querySelectorAll("code.language-slint, .rustdoc pre.language-slint, div.highlight-slint");
 | 
					        let selector = ["code.language-slint", ".rustdoc pre.language-slint", "div.highlight-slint"]
 | 
				
			||||||
 | 
					            .map((sel) => `${sel}:not([class*=slint\\,ignore]):not([class*=slint\\,no_run])`).join(",");
 | 
				
			||||||
 | 
					        var elements = document.querySelectorAll(selector);
 | 
				
			||||||
        for (var i = 0; i < elements.length; ++i) {
 | 
					        for (var i = 0; i < elements.length; ++i) {
 | 
				
			||||||
            let source = elements[i].innerText;
 | 
					            let source = elements[i].innerText;
 | 
				
			||||||
            let div = document.createElement("div");
 | 
					            let div = document.createElement("div");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,9 +27,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
				
			||||||
        let file = file.replace('\r', ""); // Remove \r, because Windows.
 | 
					        let file = file.replace('\r', ""); // Remove \r, because Windows.
 | 
				
			||||||
        let mut rest = file.as_str();
 | 
					        let mut rest = file.as_str();
 | 
				
			||||||
        let mut count = 0;
 | 
					        let mut count = 0;
 | 
				
			||||||
        const BEGIN_MARKER: &str = "\n```slint\n";
 | 
					        const BEGIN_MARKER: &str = "\n```slint";
 | 
				
			||||||
        while let Some(begin) = rest.find(BEGIN_MARKER) {
 | 
					        while let Some(begin) = rest.find(BEGIN_MARKER) {
 | 
				
			||||||
            rest = rest[begin..].strip_prefix(BEGIN_MARKER).unwrap();
 | 
					            rest = rest[begin..].strip_prefix(BEGIN_MARKER).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Permit `slint,no_run` but skip `slint,ignore` and others.
 | 
				
			||||||
 | 
					            rest = match rest.split_once('\n') {
 | 
				
			||||||
 | 
					                Some((",no_run", rest)) => rest,
 | 
				
			||||||
 | 
					                Some(("", _)) => rest,
 | 
				
			||||||
 | 
					                _ => continue,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let end = rest.find("\n```\n").ok_or_else(|| {
 | 
					            let end = rest.find("\n```\n").ok_or_else(|| {
 | 
				
			||||||
                format!("Could not find the end of a code snippet in {}", path.display())
 | 
					                format!("Could not find the end of a code snippet in {}", path.display())
 | 
				
			||||||
            })?;
 | 
					            })?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue