% Copyright 2024 Remy Blank <remy@c-space.org>
% SPDX-License-Identifier: MIT

# HTML, CSS, JavaScript

```{metadata}
styles:
  - demo-html-styles.css
scripts:
  - src: demo-html-script.js
    type: module
```

## Inline document

The [`{exec} html`](../reference/exec.md#html) directive allows displaying a
complete HTML document as an `<iframe>`. The `<iframe>` defaults to a 16/9
aspect ratio, but its size can be adjusted with
{rst:dir}`:output-style: <exec:output-style>`.

Console output generated by.
[`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) methods
is displayed in a console output block. Its size can be controlled with
{rst:dir}`:console-style: <exec:console-style>`.

```{exec} html
:when: load
:editor:
:style: height: 17rem;
:output-style: height: 10rem;
:console-style: max-height: 25rem;
<!DOCTYPE html>
<html lang="en">
<head>
  <title>This is the page title (counter: 0)</title>
  <style>h1 { margin: 0; font-size: 3rem; }</style>
</head>
<body>
  <h1 id="top">Hello, </h1>
  <p>Go to <a href="#sect-1">section 1</a>, <a href="#sect-2">section 2</a>,
    <a href="#sect-3">section 3</a> or <a href="#sect-4">section 4</a>.</p>
  <br><br><br><br>

  <h2 id="sect-1">Section 1</h2>
  <p>This is section 1. Go back to the <a href="#top">top</a>.</p>
  <h2 id="sect-2">Section 2</h2>
  <p>This is section 2. Go back to the <a href="#top">top</a>.</p>
  <h2 id="sect-3">Section 3</h2>
  <p>This is section 3. Go back to the <a href="#top">top</a>.</p>
  <h2 id="sect-4">Section 4</h2>
  <p>This is section 4. Go back to the <a href="#top">top</a>.</p>

  <script>
document.addEventListener('DOMContentLoaded', () => {
  document.querySelector('h1').appendChild(document.createTextNode('world!'));
});
let counter = 0;
setInterval(() => {
  document.title = document.title.replace(/\d+/, ++counter);
}, 1000);

console.log("log");
console.debug("debug");
console.info("info");
console.warn("Warn");
console.error("Error");
console.log('\n');
console.log();
console.log(undefined, null, 42, 12.45, "A % string %% value %%%", {a: 1, b: 2},
            [1, 2, 3, 4]);
console.log(document.querySelector('title'));
console.log("A % string %% on %%% its %%%% own");
console.log("Objects: %o %O %o %O", {a: 1}, {a: 1}, [1, 2], [1, 2]);
console.log("Integers: %d %i %d %d %d", 1.2, 1.2, -7.8, "-7.8a", "a");
console.log("Strings: %s %s %s %s", "abc", 12.34, {a: 1}, [1, 2]);
console.log("Floats: %f %f %f", 12.34, "-12.34a", "a");
console.log("Styles: %cred %cgreen %cblue",
            'color: red', 'color: green', 'color: blue');
console.log("Prefix & suffix: %% %% %d %d %d %d", 1, 2);
(async () => { throw new Error("Async boom!"); })();
throw new Error("Boom!");
  </script>
  <script>*Invalid JavaScript*</script>
</body>
</html>
```

### Partial content

Browsers are smart enough to render `<iframe>` tags with partial content
correctly. So an [`{exec} html`](../reference/exec.md#html) block can specify
just an HTML snippet, and optionally styles (with a `<style>` element):

```{exec} html
:when: load
:editor:
:output-style: height: 7rem;
<style>h1 { margin: 0; font-size: 5rem; }</style>
<h1>Hello, world!</h1>
```

Or scripts (with a `<script>` element):

```{exec} html
:when: load
:editor:
:output-style: height: 3rem;
:console-style: max-height: 5rem;
Please click <button>here</button>
<script>
let clicks = 0;
document.querySelector('button')
  .addEventListener('click', () => {
    document.title = `Clicks: ${++clicks}`;
    console.log(`Clicks: ${clicks}`);
  });
</script>
```

## Web application

Markdown already allows adding arbitrary HTML. Page-specific stylesheets and
scripts can be added with the `styles` and `scripts` entries of a
{rst:dir}`metadata` directive.

<div class="tdoc-web-app">
  Please click <button>here</button> (clicks: <span>0</span>)
</div>
