UNPKG

conextra

Version:

Conextra for Web Development. Helps create a SPWA (Single-page Progressive Web Application).

1,989 lines 77 kB
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>List of modules</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        .markdown-body {
            box-sizing: border-box;
            min-width: 200px;
            max-width: 980px;
            margin: 0 auto;
            padding: 45px;
        }

        @media (max-width: 767px) {
            .markdown-body {
                padding: 15px;
            }
        }

        .markdown-body {
            --base-size-4: 0.25rem;
            --base-size-8: 0.5rem;
            --base-size-16: 1rem;
            --base-size-24: 1.5rem;
            --base-size-40: 2.5rem;
            --base-text-weight-normal: 400;
            --base-text-weight-medium: 500;
            --base-text-weight-semibold: 600;
            --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
            --fgColor-accent: Highlight;
        }

        @media (prefers-color-scheme: dark) {
            .markdown-body, [data-theme="dark"] {
                /* dark */
                color-scheme: dark;
                --focus-outlineColor: #1f6feb;
                --fgColor-default: #f0f6fc;
                --fgColor-muted: #9198a1;
                --fgColor-accent: #4493f8;
                --fgColor-success: #3fb950;
                --fgColor-attention: #d29922;
                --fgColor-danger: #f85149;
                --fgColor-done: #ab7df8;
                --bgColor-default: #0d1117;
                --bgColor-muted: #151b23;
                --bgColor-neutral-muted: #656c7633;
                --bgColor-attention-muted: #bb800926;
                --borderColor-default: #3d444d;
                --borderColor-muted: #3d444db3;
                --borderColor-neutral-muted: #3d444db3;
                --borderColor-accent-emphasis: #1f6feb;
                --borderColor-success-emphasis: #238636;
                --borderColor-attention-emphasis: #9e6a03;
                --borderColor-danger-emphasis: #da3633;
                --borderColor-done-emphasis: #8957e5;
                --color-prettylights-syntax-comment: #9198a1;
                --color-prettylights-syntax-constant: #79c0ff;
                --color-prettylights-syntax-constant-other-reference-link: #a5d6ff;
                --color-prettylights-syntax-entity: #d2a8ff;
                --color-prettylights-syntax-storage-modifier-import: #f0f6fc;
                --color-prettylights-syntax-entity-tag: #7ee787;
                --color-prettylights-syntax-keyword: #ff7b72;
                --color-prettylights-syntax-string: #a5d6ff;
                --color-prettylights-syntax-variable: #ffa657;
                --color-prettylights-syntax-brackethighlighter-unmatched: #f85149;
                --color-prettylights-syntax-brackethighlighter-angle: #9198a1;
                --color-prettylights-syntax-invalid-illegal-text: #f0f6fc;
                --color-prettylights-syntax-invalid-illegal-bg: #8e1519;
                --color-prettylights-syntax-carriage-return-text: #f0f6fc;
                --color-prettylights-syntax-carriage-return-bg: #b62324;
                --color-prettylights-syntax-string-regexp: #7ee787;
                --color-prettylights-syntax-markup-list: #f2cc60;
                --color-prettylights-syntax-markup-heading: #1f6feb;
                --color-prettylights-syntax-markup-italic: #f0f6fc;
                --color-prettylights-syntax-markup-bold: #f0f6fc;
                --color-prettylights-syntax-markup-deleted-text: #ffdcd7;
                --color-prettylights-syntax-markup-deleted-bg: #67060c;
                --color-prettylights-syntax-markup-inserted-text: #aff5b4;
                --color-prettylights-syntax-markup-inserted-bg: #033a16;
                --color-prettylights-syntax-markup-changed-text: #ffdfb6;
                --color-prettylights-syntax-markup-changed-bg: #5a1e02;
                --color-prettylights-syntax-markup-ignored-text: #f0f6fc;
                --color-prettylights-syntax-markup-ignored-bg: #1158c7;
                --color-prettylights-syntax-meta-diff-range: #d2a8ff;
                --color-prettylights-syntax-sublimelinter-gutter-mark: #3d444d;
            }
        }

        @media (prefers-color-scheme: light) {
            .markdown-body, [data-theme="light"] {
                /* light */
                color-scheme: light;
                --focus-outlineColor: #0969da;
                --fgColor-default: #1f2328;
                --fgColor-muted: #59636e;
                --fgColor-accent: #0969da;
                --fgColor-success: #1a7f37;
                --fgColor-attention: #9a6700;
                --fgColor-danger: #d1242f;
                --fgColor-done: #8250df;
                --bgColor-default: #ffffff;
                --bgColor-muted: #f6f8fa;
                --bgColor-neutral-muted: #818b981f;
                --bgColor-attention-muted: #fff8c5;
                --borderColor-default: #d1d9e0;
                --borderColor-muted: #d1d9e0b3;
                --borderColor-neutral-muted: #d1d9e0b3;
                --borderColor-accent-emphasis: #0969da;
                --borderColor-success-emphasis: #1a7f37;
                --borderColor-attention-emphasis: #9a6700;
                --borderColor-danger-emphasis: #cf222e;
                --borderColor-done-emphasis: #8250df;
                --color-prettylights-syntax-comment: #59636e;
                --color-prettylights-syntax-constant: #0550ae;
                --color-prettylights-syntax-constant-other-reference-link: #0a3069;
                --color-prettylights-syntax-entity: #6639ba;
                --color-prettylights-syntax-storage-modifier-import: #1f2328;
                --color-prettylights-syntax-entity-tag: #0550ae;
                --color-prettylights-syntax-keyword: #cf222e;
                --color-prettylights-syntax-string: #0a3069;
                --color-prettylights-syntax-variable: #953800;
                --color-prettylights-syntax-brackethighlighter-unmatched: #82071e;
                --color-prettylights-syntax-brackethighlighter-angle: #59636e;
                --color-prettylights-syntax-invalid-illegal-text: #f6f8fa;
                --color-prettylights-syntax-invalid-illegal-bg: #82071e;
                --color-prettylights-syntax-carriage-return-text: #f6f8fa;
                --color-prettylights-syntax-carriage-return-bg: #cf222e;
                --color-prettylights-syntax-string-regexp: #116329;
                --color-prettylights-syntax-markup-list: #3b2300;
                --color-prettylights-syntax-markup-heading: #0550ae;
                --color-prettylights-syntax-markup-italic: #1f2328;
                --color-prettylights-syntax-markup-bold: #1f2328;
                --color-prettylights-syntax-markup-deleted-text: #82071e;
                --color-prettylights-syntax-markup-deleted-bg: #ffebe9;
                --color-prettylights-syntax-markup-inserted-text: #116329;
                --color-prettylights-syntax-markup-inserted-bg: #dafbe1;
                --color-prettylights-syntax-markup-changed-text: #953800;
                --color-prettylights-syntax-markup-changed-bg: #ffd8b5;
                --color-prettylights-syntax-markup-ignored-text: #d1d9e0;
                --color-prettylights-syntax-markup-ignored-bg: #0550ae;
                --color-prettylights-syntax-meta-diff-range: #8250df;
                --color-prettylights-syntax-sublimelinter-gutter-mark: #818b98;
            }
        }

        .markdown-body {
            -ms-text-size-adjust: 100%;
            -webkit-text-size-adjust: 100%;
            margin: 0;
            color: var(--fgColor-default);
            background-color: var(--bgColor-default);
            font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
            font-size: 16px;
            line-height: 1.5;
            word-wrap: break-word;
        }

            .markdown-body .octicon {
                display: inline-block;
                fill: currentColor;
                vertical-align: text-bottom;
            }

            .markdown-body h1:hover .anchor .octicon-link:before,
            .markdown-body h2:hover .anchor .octicon-link:before,
            .markdown-body h3:hover .anchor .octicon-link:before,
            .markdown-body h4:hover .anchor .octicon-link:before,
            .markdown-body h5:hover .anchor .octicon-link:before,
            .markdown-body h6:hover .anchor .octicon-link:before {
                width: 16px;
                height: 16px;
                content: ' ';
                display: inline-block;
                background-color: currentColor;
                -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
                mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg>");
            }

            .markdown-body details,
            .markdown-body figcaption,
            .markdown-body figure {
                display: block;
            }

            .markdown-body summary {
                display: list-item;
            }

            .markdown-body [hidden] {
                display: none !important;
            }

            .markdown-body a {
                background-color: transparent;
                color: var(--fgColor-accent);
                text-decoration: none;
            }

            .markdown-body abbrList of modules {
                border-bottom: none;
                -webkit-text-decoration: underline dotted;
                text-decoration: underline dotted;
            }

            .markdown-body b,
            .markdown-body strong {
                font-weight: var(--base-text-weight-semibold, 600);
            }

            .markdown-body dfn {
                font-style: italic;
            }

            .markdown-body h1 {
                margin: .67em 0;
                font-weight: var(--base-text-weight-semibold, 600);
                padding-bottom: .3em;
                font-size: 2em;
                border-bottom: 1px solid var(--borderColor-muted);
            }

            .markdown-body mark {
                background-color: var(--bgColor-attention-muted);
                color: var(--fgColor-default);
            }

            .markdown-body small {
                font-size: 90%;
            }

            .markdown-body sub,
            .markdown-body sup {
                font-size: 75%;
                line-height: 0;
                position: relative;
                vertical-align: baseline;
            }

            .markdown-body sub {
                bottom: -0.25em;
            }

            .markdown-body sup {
                top: -0.5em;
            }

            .markdown-body img {
                border-style: none;
                max-width: 100%;
                box-sizing: content-box;
            }

            .markdown-body code,
            .markdown-body kbd,
            .markdown-body pre,
            .markdown-body samp {
                font-family: monospace;
                font-size: 1em;
            }

            .markdown-body figure {
                margin: 1em var(--base-size-40);
            }

            .markdown-body hr {
                box-sizing: content-box;
                overflow: hidden;
                background: transparent;
                border-bottom: 1px solid var(--borderColor-muted);
                height: .25em;
                padding: 0;
                margin: var(--base-size-24) 0;
                background-color: var(--borderColor-default);
                border: 0;
            }

            .markdown-body input {
                font: inherit;
                margin: 0;
                overflow: visible;
                font-family: inherit;
                font-size: inherit;
                line-height: inherit;
            }

            .markdown-body [type=button],
            .markdown-body [type=reset],
            .markdown-body [type=submit] {
                -webkit-appearance: button;
                appearance: button;
            }

            .markdown-body [type=checkbox],
            .markdown-body [type=radio] {
                box-sizing: border-box;
                padding: 0;
            }

            .markdown-body [type=number]::-webkit-inner-spin-button,
            .markdown-body [type=number]::-webkit-outer-spin-button {
                height: auto;
            }

            .markdown-body [type=search]::-webkit-search-cancel-button,
            .markdown-body [type=search]::-webkit-search-decoration {
                -webkit-appearance: none;
                appearance: none;
            }

            .markdown-body ::-webkit-input-placeholder {
                color: inherit;
                opacity: .54;
            }

            .markdown-body ::-webkit-file-upload-button {
                -webkit-appearance: button;
                appearance: button;
                font: inherit;
            }

            .markdown-body a:hover {
                text-decoration: underline;
            }

            .markdown-body ::placeholder {
                color: var(--fgColor-muted);
                opacity: 1;
            }

            .markdown-body hr::before {
                display: table;
                content: "";
            }

            .markdown-body hr::after {
                display: table;
                clear: both;
                content: "";
            }

            .markdown-body table {
                border-spacing: 0;
                border-collapse: collapse;
                display: block;
                width: max-content;
                max-width: 100%;
                overflow: auto;
                font-variant: tabular-nums;
            }

            .markdown-body td,
            .markdown-body th {
                padding: 0;
            }

            .markdown-body details summary {
                cursor: pointer;
            }

            .markdown-body a:focus,
            .markdown-body [role=button]:focus,
            .markdown-body input[type=radio]:focus,
            .markdown-body input[type=checkbox]:focus {
                outline: 2px solid var(--focus-outlineColor);
                outline-offset: -2px;
                box-shadow: none;
            }

                .markdown-body a:focus:not(:focus-visible),
                .markdown-body [role=button]:focus:not(:focus-visible),
                .markdown-body input[type=radio]:focus:not(:focus-visible),
                .markdown-body input[type=checkbox]:focus:not(:focus-visible) {
                    outline: solid 1px transparent;
                }

            .markdown-body a:focus-visible,
            .markdown-body [role=button]:focus-visible,
            .markdown-body input[type=radio]:focus-visible,
            .markdown-body input[type=checkbox]:focus-visible {
                outline: 2px solid var(--focus-outlineColor);
                outline-offset: -2px;
                box-shadow: none;
            }

            .markdown-body a:not([class]):focus,
            .markdown-body a:not([class]):focus-visible,
            .markdown-body input[type=radio]:focus,
            .markdown-body input[type=radio]:focus-visible,
            .markdown-body input[type=checkbox]:focus,
            .markdown-body input[type=checkbox]:focus-visible {
                outline-offset: 0;
            }

            .markdown-body kbd {
                display: inline-block;
                padding: var(--base-size-4);
                font: 11px var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
                line-height: 10px;
                color: var(--fgColor-default);
                vertical-align: middle;
                background-color: var(--bgColor-muted);
                border: solid 1px var(--borderColor-neutral-muted);
                border-bottom-color: var(--borderColor-neutral-muted);
                border-radius: 6px;
                box-shadow: inset 0 -1px 0 var(--borderColor-neutral-muted);
            }

            .markdown-body h1,
            .markdown-body h2,
            .markdown-body h3,
            .markdown-body h4,
            .markdown-body h5,
            .markdown-body h6 {
                margin-top: var(--base-size-24);
                margin-bottom: var(--base-size-16);
                font-weight: var(--base-text-weight-semibold, 600);
                line-height: 1.25;
            }

            .markdown-body h2 {
                font-weight: var(--base-text-weight-semibold, 600);
                padding-bottom: .3em;
                font-size: 1.5em;
                border-bottom: 1px solid var(--borderColor-muted);
            }

            .markdown-body h3 {
                font-weight: var(--base-text-weight-semibold, 600);
                font-size: 1.25em;
            }

            .markdown-body h4 {
                font-weight: var(--base-text-weight-semibold, 600);
                font-size: 1em;
            }

            .markdown-body h5 {
                font-weight: var(--base-text-weight-semibold, 600);
                font-size: .875em;
            }

            .markdown-body h6 {
                font-weight: var(--base-text-weight-semibold, 600);
                font-size: .85em;
                color: var(--fgColor-muted);
            }

            .markdown-body p {
                margin-top: 0;
                margin-bottom: 10px;
            }

            .markdown-body blockquote {
                margin: 0;
                padding: 0 1em;
                color: var(--fgColor-muted);
                border-left: .25em solid var(--borderColor-default);
            }

            .markdown-body ul,
            .markdown-body ol {
                margin-top: 0;
                margin-bottom: 0;
                padding-left: 2em;
            }

                .markdown-body ol ol,
                .markdown-body ul ol {
                    list-style-type: lower-roman;
                }

                    .markdown-body ul ul ol,
                    .markdown-body ul ol ol,
                    .markdown-body ol ul ol,
                    .markdown-body ol ol ol {
                        list-style-type: lower-alpha;
                    }

            .markdown-body dd {
                margin-left: 0;
            }

            .markdown-body tt,
            .markdown-body code,
            .markdown-body samp {
                font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
                font-size: 12px;
            }

            .markdown-body pre {
                margin-top: 0;
                margin-bottom: 0;
                font-family: var(--fontStack-monospace, ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace);
                font-size: 12px;
                word-wrap: normal;
            }

            .markdown-body .octicon {
                display: inline-block;
                overflow: visible !important;
                vertical-align: text-bottom;
                fill: currentColor;
            }

            .markdown-body input::-webkit-outer-spin-button,
            .markdown-body input::-webkit-inner-spin-button {
                margin: 0;
                appearance: none;
            }

            .markdown-body .mr-2 {
                margin-right: var(--base-size-8, 8px) !important;
            }

            .markdown-body::before {
                display: table;
                content: "";
            }

            .markdown-body::after {
                display: table;
                clear: both;
                content: "";
            }

            .markdown-body > *:first-child {
                margin-top: 0 !important;
            }

            .markdown-body > *:last-child {
                margin-bottom: 0 !important;
            }

            .markdown-body a:not([href]) {
                color: inherit;
                text-decoration: none;
            }

            .markdown-body .absent {
                color: var(--fgColor-danger);
            }

            .markdown-body .anchor {
                float: left;
                padding-right: var(--base-size-4);
                margin-left: -20px;
                line-height: 1;
            }

                .markdown-body .anchor:focus {
                    outline: none;
                }

            .markdown-body p,
            .markdown-body blockquote,
            .markdown-body ul,
            .markdown-body ol,
            .markdown-body dl,
            .markdown-body table,
            .markdown-body pre,
            .markdown-body details {
                margin-top: 0;
                margin-bottom: var(--base-size-16);
            }

                .markdown-body blockquote > :first-child {
                    margin-top: 0;
                }

                .markdown-body blockquote > :last-child {
                    margin-bottom: 0;
                }

            .markdown-body h1 .octicon-link,
            .markdown-body h2 .octicon-link,
            .markdown-body h3 .octicon-link,
            .markdown-body h4 .octicon-link,
            .markdown-body h5 .octicon-link,
            .markdown-body h6 .octicon-link {
                color: var(--fgColor-default);
                vertical-align: middle;
                visibility: hidden;
            }

            .markdown-body h1:hover .anchor,
            .markdown-body h2:hover .anchor,
            .markdown-body h3:hover .anchor,
            .markdown-body h4:hover .anchor,
            .markdown-body h5:hover .anchor,
            .markdown-body h6:hover .anchor {
                text-decoration: none;
            }

                .markdown-body h1:hover .anchor .octicon-link,
                .markdown-body h2:hover .anchor .octicon-link,
                .markdown-body h3:hover .anchor .octicon-link,
                .markdown-body h4:hover .anchor .octicon-link,
                .markdown-body h5:hover .anchor .octicon-link,
                .markdown-body h6:hover .anchor .octicon-link {
                    visibility: visible;
                }

            .markdown-body h1 tt,
            .markdown-body h1 code,
            .markdown-body h2 tt,
            .markdown-body h2 code,
            .markdown-body h3 tt,
            .markdown-body h3 code,
            .markdown-body h4 tt,
            .markdown-body h4 code,
            .markdown-body h5 tt,
            .markdown-body h5 code,
            .markdown-body h6 tt,
            .markdown-body h6 code {
                padding: 0 .2em;
                font-size: inherit;
            }

            .markdown-body summary h1,
            .markdown-body summary h2,
            .markdown-body summary h3,
            .markdown-body summary h4,
            .markdown-body summary h5,
            .markdown-body summary h6 {
                display: inline-block;
            }

                .markdown-body summary h1 .anchor,
                .markdown-body summary h2 .anchor,
                .markdown-body summary h3 .anchor,
                .markdown-body summary h4 .anchor,
                .markdown-body summary h5 .anchor,
                .markdown-body summary h6 .anchor {
                    margin-left: -40px;
                }

            .markdown-body summary h1,
            .markdown-body summary h2 {
                padding-bottom: 0;
                border-bottom: 0;
            }

            .markdown-body ul.no-list,
            .markdown-body ol.no-list {
                padding: 0;
                list-style-type: none;
            }

            .markdown-body ol[type="a s"] {
                list-style-type: lower-alpha;
            }

            .markdown-body ol[type="A s"] {
                list-style-type: upper-alpha;
            }

            .markdown-body ol[type="i s"] {
                list-style-type: lower-roman;
            }

            .markdown-body ol[type="I s"] {
                list-style-type: upper-roman;
            }

            .markdown-body ol[type="1"] {
                list-style-type: decimal;
            }

            .markdown-body div > ol:not([type]) {
                list-style-type: decimal;
            }

            .markdown-body ul ul,
            .markdown-body ul ol,
            .markdown-body ol ol,
            .markdown-body ol ul {
                margin-top: 0;
                margin-bottom: 0;
            }

            .markdown-body li > p {
                margin-top: var(--base-size-16);
            }

            .markdown-body li + li {
                margin-top: .25em;
            }

            .markdown-body dl {
                padding: 0;
            }

                .markdown-body dl dt {
                    padding: 0;
                    margin-top: var(--base-size-16);
                    font-size: 1em;
                    font-style: italic;
                    font-weight: var(--base-text-weight-semibold, 600);
                }

                .markdown-body dl dd {
                    padding: 0 var(--base-size-16);
                    margin-bottom: var(--base-size-16);
                }

            .markdown-body table th {
                font-weight: var(--base-text-weight-semibold, 600);
            }

            .markdown-body table th,
            .markdown-body table td {
                padding: 6px 13px;
                border: 1px solid var(--borderColor-default);
            }

                .markdown-body table td > :last-child {
                    margin-bottom: 0;
                }

            .markdown-body table tr {
                background-color: var(--bgColor-default);
                border-top: 1px solid var(--borderColor-muted);
            }

                .markdown-body table tr:nth-child(2n) {
                    background-color: var(--bgColor-muted);
                }

            .markdown-body table img {
                background-color: transparent;
            }

            .markdown-body img[align=right] {
                padding-left: 20px;
            }

            .markdown-body img[align=left] {
                padding-right: 20px;
            }

            .markdown-body .emoji {
                max-width: none;
                vertical-align: text-top;
                background-color: transparent;
            }

            .markdown-body span.frame {
                display: block;
                overflow: hidden;
            }

                .markdown-body span.frame > span {
                    display: block;
                    float: left;
                    width: auto;
                    padding: 7px;
                    margin: 13px 0 0;
                    overflow: hidden;
                    border: 1px solid var(--borderColor-default);
                }

                .markdown-body span.frame span img {
                    display: block;
                    float: left;
                }

                .markdown-body span.frame span span {
                    display: block;
                    padding: 5px 0 0;
                    clear: both;
                    color: var(--fgColor-default);
                }

            .markdown-body span.align-center {
                display: block;
                overflow: hidden;
                clear: both;
            }

                .markdown-body span.align-center > span {
                    display: block;
                    margin: 13px auto 0;
                    overflow: hidden;
                    text-align: center;
                }

                .markdown-body span.align-center span img {
                    margin: 0 auto;
                    text-align: center;
                }

            .markdown-body span.align-right {
                display: block;
                overflow: hidden;
                clear: both;
            }

                .markdown-body span.align-right > span {
                    display: block;
                    margin: 13px 0 0;
                    overflow: hidden;
                    text-align: right;
                }

                .markdown-body span.align-right span img {
                    margin: 0;
                    text-align: right;
                }

            .markdown-body span.float-left {
                display: block;
                float: left;
                margin-right: 13px;
                overflow: hidden;
            }

                .markdown-body span.float-left span {
                    margin: 13px 0 0;
                }

            .markdown-body span.float-right {
                display: block;
                float: right;
                margin-left: 13px;
                overflow: hidden;
            }

                .markdown-body span.float-right > span {
                    display: block;
                    margin: 13px auto 0;
                    overflow: hidden;
                    text-align: right;
                }

            .markdown-body code,
            .markdown-body tt {
                padding: .2em .4em;
                margin: 0;
                font-size: 85%;
                white-space: break-spaces;
                background-color: var(--bgColor-neutral-muted);
                border-radius: 6px;
            }

                .markdown-body code br,
                .markdown-body tt br {
                    display: none;
                }

            .markdown-body del code {
                text-decoration: inherit;
            }

            .markdown-body samp {
                font-size: 85%;
            }

            .markdown-body pre code {
                font-size: 100%;
            }

            .markdown-body pre > code {
                padding: 0;
                margin: 0;
                word-break: normal;
                white-space: pre;
                background: transparent;
                border: 0;
            }

            .markdown-body .highlight {
                margin-bottom: var(--base-size-16);
            }

                .markdown-body .highlight pre {
                    margin-bottom: 0;
                    word-break: normal;
                }

                .markdown-body .highlight pre,
                .markdown-body pre {
                    padding: var(--base-size-16);
                    overflow: auto;
                    font-size: 85%;
                    line-height: 1.45;
                    color: var(--fgColor-default);
                    background-color: var(--bgColor-muted);
                    border-radius: 6px;
                }

                    .markdown-body pre code,
                    .markdown-body pre tt {
                        display: inline;
                        max-width: auto;
                        padding: 0;
                        margin: 0;
                        overflow: visible;
                        line-height: inherit;
                        word-wrap: normal;
                        background-color: transparent;
                        border: 0;
                    }

            .markdown-body .csv-data td,
            .markdown-body .csv-data th {
                padding: 5px;
                overflow: hidden;
                font-size: 12px;
                line-height: 1;
                text-align: left;
                white-space: nowrap;
            }

            .markdown-body .csv-data .blob-num {
                padding: 10px var(--base-size-8) 9px;
                text-align: right;
                background: var(--bgColor-default);
                border: 0;
            }

            .markdown-body .csv-data tr {
                border-top: 0;
            }

            .markdown-body .csv-data th {
                font-weight: var(--base-text-weight-semibold, 600);
                background: var(--bgColor-muted);
                border-top: 0;
            }

            .markdown-body [data-footnote-ref]::before {
                content: "[";
            }

            .markdown-body [data-footnote-ref]::after {
                content: "]";
            }

            .markdown-body .footnotes {
                font-size: 12px;
                color: var(--fgColor-muted);
                border-top: 1px solid var(--borderColor-default);
            }

                .markdown-body .footnotes ol {
                    padding-left: var(--base-size-16);
                }

                    .markdown-body .footnotes ol ul {
                        display: inline-block;
                        padding-left: var(--base-size-16);
                        margin-top: var(--base-size-16);
                    }

                .markdown-body .footnotes li {
                    position: relative;
                }

                    .markdown-body .footnotes li:target::before {
                        position: absolute;
                        top: calc(var(--base-size-8)*-1);
                        right: calc(var(--base-size-8)*-1);
                        bottom: calc(var(--base-size-8)*-1);
                        left: calc(var(--base-size-24)*-1);
                        pointer-events: none;
                        content: "";
                        border: 2px solid var(--borderColor-accent-emphasis);
                        border-radius: 6px;
                    }

                    .markdown-body .footnotes li:target {
                        color: var(--fgColor-default);
                    }

                .markdown-body .footnotes .data-footnote-backref g-emoji {
                    font-family: monospace;
                }

            .markdown-body body:has(:modal) {
                padding-right: var(--dialog-scrollgutter) !important;
            }

            .markdown-body .pl-c {
                color: var(--color-prettylights-syntax-comment);
            }

            .markdown-body .pl-c1,
            .markdown-body .pl-s .pl-v {
                color: var(--color-prettylights-syntax-constant);
            }

            .markdown-body .pl-e,
            .markdown-body .pl-en {
                color: var(--color-prettylights-syntax-entity);
            }

            .markdown-body .pl-smi,
            .markdown-body .pl-s .pl-s1 {
                color: var(--color-prettylights-syntax-storage-modifier-import);
            }

            .markdown-body .pl-ent {
                color: var(--color-prettylights-syntax-entity-tag);
            }

            .markdown-body .pl-k {
                color: var(--color-prettylights-syntax-keyword);
            }

            .markdown-body .pl-s,
            .markdown-body .pl-pds,
            .markdown-body .pl-s .pl-pse .pl-s1,
            .markdown-body .pl-sr,
            .markdown-body .pl-sr .pl-cce,
            .markdown-body .pl-sr .pl-sre,
            .markdown-body .pl-sr .pl-sra {
                color: var(--color-prettylights-syntax-string);
            }

            .markdown-body .pl-v,
            .markdown-body .pl-smw {
                color: var(--color-prettylights-syntax-variable);
            }

            .markdown-body .pl-bu {
                color: var(--color-prettylights-syntax-brackethighlighter-unmatched);
            }

            .markdown-body .pl-ii {
                color: var(--color-prettylights-syntax-invalid-illegal-text);
                background-color: var(--color-prettylights-syntax-invalid-illegal-bg);
            }

            .markdown-body .pl-c2 {
                color: var(--color-prettylights-syntax-carriage-return-text);
                background-color: var(--color-prettylights-syntax-carriage-return-bg);
            }

            .markdown-body .pl-sr .pl-cce {
                font-weight: bold;
                color: var(--color-prettylights-syntax-string-regexp);
            }

            .markdown-body .pl-ml {
                color: var(--color-prettylights-syntax-markup-list);
            }

            .markdown-body .pl-mh,
            .markdown-body .pl-mh .pl-en,
            .markdown-body .pl-ms {
                font-weight: bold;
                color: var(--color-prettylights-syntax-markup-heading);
            }

            .markdown-body .pl-mi {
                font-style: italic;
                color: var(--color-prettylights-syntax-markup-italic);
            }

            .markdown-body .pl-mb {
                font-weight: bold;
                color: var(--color-prettylights-syntax-markup-bold);
            }

            .markdown-body .pl-md {
                color: var(--color-prettylights-syntax-markup-deleted-text);
                background-color: var(--color-prettylights-syntax-markup-deleted-bg);
            }

            .markdown-body .pl-mi1 {
                color: var(--color-prettylights-syntax-markup-inserted-text);
                background-color: var(--color-prettylights-syntax-markup-inserted-bg);
            }

            .markdown-body .pl-mc {
                color: var(--color-prettylights-syntax-markup-changed-text);
                background-color: var(--color-prettylights-syntax-markup-changed-bg);
            }

            .markdown-body .pl-mi2 {
                color: var(--color-prettylights-syntax-markup-ignored-text);
                background-color: var(--color-prettylights-syntax-markup-ignored-bg);
            }

            .markdown-body .pl-mdr {
                font-weight: bold;
                color: var(--color-prettylights-syntax-meta-diff-range);
            }

            .markdown-body .pl-ba {
                color: var(--color-prettylights-syntax-brackethighlighter-angle);
            }

            .markdown-body .pl-sg {
                color: var(--color-prettylights-syntax-sublimelinter-gutter-mark);
            }

            .markdown-body .pl-corl {
                text-decoration: underline;
                color: var(--color-prettylights-syntax-constant-other-reference-link);
            }

            .markdown-body [role=button]:focus:not(:focus-visible),
            .markdown-body [role=tabpanel][tabindex="0"]:focus:not(:focus-visible),
            .markdown-body button:focus:not(:focus-visible),
            .markdown-body summary:focus:not(:focus-visible),
            .markdown-body a:focus:not(:focus-visible) {
                outline: none;
                box-shadow: none;
            }

            .markdown-body [tabindex="0"]:focus:not(:focus-visible),
            .markdown-body details-dialog:focus:not(:focus-visible) {
                outline: none;
            }

            .markdown-body g-emoji {
                display: inline-block;
                min-width: 1ch;
                font-family: "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
                font-size: 1em;
                font-style: normal !important;
                font-weight: var(--base-text-weight-normal, 400);
                line-height: 1;
                vertical-align: -0.075em;
            }

                .markdown-body g-emoji img {
                    width: 1em;
                    height: 1em;
                }

            .markdown-body .task-list-item {
                list-style-type: none;
            }

                .markdown-body .task-list-item label {
                    font-weight: var(--base-text-weight-normal, 400);
                }

                .markdown-body .task-list-item.enabled label {
                    cursor: pointer;
                }

                .markdown-body .task-list-item + .task-list-item {
                    margin-top: var(--base-size-4);
                }

                .markdown-body .task-list-item .handle {
                    display: none;
                }

            .markdown-body .task-list-item-checkbox {
                margin: 0 .2em .25em -1.4em;
                vertical-align: middle;
            }

            .markdown-body ul:dir(rtl) .task-list-item-checkbox {
                margin: 0 -1.6em .25em .2em;
            }

            .markdown-body ol:dir(rtl) .task-list-item-checkbox {
                margin: 0 -1.6em .25em .2em;
            }

            .markdown-body .contains-task-list:hover .task-list-item-convert-container,
            .markdown-body .contains-task-list:focus-within .task-list-item-convert-container {
                display: block;
                width: auto;
                height: 24px;
                overflow: visible;
                clip: auto;
            }

            .markdown-body ::-webkit-calendar-picker-indicator {
                filter: invert(50%);
            }

            .markdown-body .markdown-alert {
                padding: var(--base-size-8) var(--base-size-16);
                margin-bottom: var(--base-size-16);
                color: inherit;
                border-left: .25em solid var(--borderColor-default);
            }

                .markdown-body .markdown-alert > :first-child {
                    margin-top: 0;
                }

                .markdown-body .markdown-alert > :last-child {
                    margin-bottom: 0;
                }

                .markdown-body .markdown-alert .markdown-alert-title {
                    display: flex;
                    font-weight: var(--base-text-weight-medium, 500);
                    align-items: center;
                    line-height: 1;
                }

                .markdown-body .markdown-alert.markdown-alert-note {
                    border-left-color: var(--borderColor-accent-emphasis);
                }

                    .markdown-body .markdown-alert.markdown-alert-note .markdown-alert-title {
                        color: var(--fgColor-accent);
                    }

                .markdown-body .markdown-alert.markdown-alert-important {
                    border-left-color: var(--borderColor-done-emphasis);
                }

                    .markdown-body .markdown-alert.markdown-alert-important .markdown-alert-title {
                        color: var(--fgColor-done);
                    }

                .markdown-body .markdown-alert.markdown-alert-warning {
                    border-left-color: var(--borderColor-attention-emphasis);
                }

                    .markdown-body .markdown-alert.markdown-alert-warning .markdown-alert-title {
                        color: var(--fgColor-attention);
                    }

                .markdown-body .markdown-alert.markdown-alert-tip {
                    border-left-color: var(--borderColor-success-emphasis);
                }

                    .markdown-body .markdown-alert.markdown-alert-tip .markdown-alert-title {
                        color: var(--fgColor-success);
                    }

                .markdown-body .markdown-alert.markdown-alert-caution {
                    border-left-color: var(--borderColor-danger-emphasis);
                }

                    .markdown-body .markdown-alert.markdown-alert-caution .markdown-alert-title {
                        color: var(--fgColor-danger);
                    }

            .markdown-body > *:first-child > .heading-element:first-child {
                margin-top: 0 !important;
            }

            .markdown-body .highlight pre:has(+.zeroclipboard-container) {
                min-height: 52px;
            }
    </style>
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-12">
                <h1 class="text-center">Conextra Framework</h1>
                <p class="text-center">Documentation for Conextra framework modules</p>
            </div>
        </div>
        <div class="row w-100">
            <div class="col-3 d-none d-lg-inline">
                <div class="sticky-top overflow-auto vh-100">
                    <div id="list-headers" class="list-group mt-5">
                        <p>
                            <a href="#config-sets-module">'<strong>config-sets</strong>' module</a>
                            <a href="#data-context-module">'<strong>data-context</strong>' module</a>
                            <a href="#data-context-binding-module">'<strong>data-context-binding</strong>' module</a>
                            <a href="#tiny-https-server-module">'<strong>tiny-https-server</strong>' module</a>
                            <a href="#url-fragment-extender-module">'<strong>url-fragment-extender</strong>' module</a>
                            <a href="#ws13-module">'<strong>ws13</strong>' module</a>
                            <a href="#ws-user-module">'<strong>ws-user</strong>' module</a>
                        </p>
                    </div>
                </div>
            </div>

            <div class="col col-lg-9">
                <div class="p-2 markdown-body" data-bs-spy="scroll" data-bs-target="#list-headers" data-bs-offset="0" tabindex="0">
                    <h1 id="list-of-modules">List of modules</h1>
                    <p>
                        This is a list of modules that are part of the Conextra framework.<br>
                        Conextra is a framework for building web applications using Node.js and WebSocket.<br>
                    </p>
<pre><code>Conextra Power for web development:

- module 'config-sets' configure and change app settings in real-time
- module 'data-context' monitoring data changes 
- module 'data-context-binding' bind data to DOM elements
- module 'tiny-https-server' SPA and PWA services
- module 'url-fragment-extender' manage URL fragments
- module 'ws13' create WebSocket connection
- module 'ws-user' manage users over WebSocket
</code></pre>
                    <p>
                        It helps you create SPWA (Single-page Progressive Web Application) and efficiently perform real-time updates over WebSocket.<br>
                        The modules are designed to work together to provide a complete solution for building SPAs and PWAs.<br>
                    </p>
                    <h2 id="config-sets-module">'config-sets' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/config-sets" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/config-sets" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/config-sets" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/config-sets" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/config-sets/README.html">HTML5</a>.<br><br>
                        This Node.js module manages configuration settings by reading from and writing to a config-sets.json file.<br>
                        It handles command-line arguments and watches for changes to the configuration file.<br>
                        It allows you to create applications that can be configured in real time.<br>
                    </p>
                    <h3 id="install-of-config-sets-module">Install of 'config-sets' module</h3>
                    <p><code>npm install config-sets</code></p>
                    <h3 id="basic-usage-of-config-sets-module">Basic Usage of 'config-sets' module</h3>
                    <p>
                        Application settings are stored in a JSON file named config-sets.json.<br>
                        The file is located in the same directory as the application.<br>
                        The JSON file contains the following properties:<br>
                    </p>
                    <ul>
                        <li>isProduction: true/false</li>
                        <li>production: </li>
                        <li>development: </li>
                    </ul>
<pre><code class="language-javascript">'use strict';
//Import the required modules.
const configSets = require('config-sets');

// Setup the configuration. 
//Automatically read the config-sets.json file. 
//Metadata is optional. If you would like to add a comment to the key, use the '-metadata-key' format.
const config = configSets({ 
    '-metadata-key1': ' key1 comment ',
    key1: 'value1', 
    '-metadata-key2': ' key2 comment ',
    key2: 'value2' 
});

//Example of using in code. 
if (config.key1 === 'value1') { ... }

//Example of using the module configuration. 
//This allows you to get the module settings from the config-sets.json file.
const moduleConfig = configSets('moduleName', { key1: 'value1', key2: 'value2' });

console.log(moduleConfig);
//Watch 'key1' property for changes. 
//Return true to continue watching, false to stop watching.
config.on('key1', function (ev) { console.log(ev); return true; });
</code></pre>
                    <p>file: <code>config-sets.json</code></p>
<pre><code class="language-json">{
  &quot;isProduction&quot;: true,
  &quot;production&quot;: {
    /* key1 comment */
    &quot;key1&quot;: &quot;value1&quot;,
    /* key2 comment */
    &quot;key2&quot;: &quot;value2&quot;,
    &quot;moduleName&quot;: {
        &quot;key1&quot;: &quot;value1&quot;,
        &quot;key2&quot;: &quot;value2&quot;
    }
  },
  &quot;development&quot;: {}
}
</code></pre>
                    <h2 id="data-context-module">'data-context' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/data-context" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/data-context" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/data-context" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/data-context" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/data-context/README.html">HTML5</a>.<br><br>
                        This Node.js module monitors data changes in a data context and notifies listeners when changes occur.<br>
                    </p>
                    <h3 id="install-of-data-context-module">Install of 'data-context' module</h3>
                    <p><code>npm install config-sets</code></p>
                    <h3 id="basic-usage-of-data-context-module">Basic Usage of 'data-context' module</h3>
                    <p>node.js example:</p>
<pre><code class="language-javascript">'use strict';

//Import the required modules.
const { createDataContext, parse } = require('data-context');
//import { createDataContext, parse } from &quot;data-context&quot;;

//Create a JSON string.
var strJSON = `{
    &quot;count&quot;: 0
}`;

//Interval id.
var intervalId = null;

//Create data context.
const context = parse(
    //Parse the JSON string.
    strJSON,
    //Reviver function. Create data context.
    createDataContext
);

//Listen to the count property.
context.on('count', (event) =&gt; {

    console.log('event:', event);

    if (event.newValue &gt; 10) {

        console.log('I am dead.');
        clearInterval(intervalId);

        //I am dead. Remove listener.
        return false;
    }

    //I am live. Continue listening.
    return true;
});

context.on('-change', (event) =&gt; {

    //Stringify the changes.
    var str = context.stringifyChanges(
        //Reviver function. Default is null.
        null,
        //Indentation. Default is 0.
        4,
        //Include only modified data. Default is true.
        true,
        //Set data to unmodified after stringification. Default is true.
        true
    );
    console.log('changes:', str);

    //I am live. Continue listening.
    return true;
});

//Start the interval.
intervalId = setInterval(() =&gt; {

    //Increment the count property.
    context.count++;
}, 1000);
</code></pre>
                    <p>browser example:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;data-context&lt;/title&gt;
    &lt;!-- STEP 1. Import the module. Import for an HTML page hosted on the server. --&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;./index.js&quot;&gt;&lt;/script&gt;
    &lt;!-- STEP 1. Import the module. Import for a standalone HTML page. --&gt;
    &lt;!--&lt;script src=&quot;https://cdn.jsdelivr.net/npm/data-context&quot;&gt;&lt;/script&gt;--&gt;
    &lt;script&gt;

        'use strict';

        // STEP 3. Import the module.
        importModules(['data-context'], function (DC) {

            var { createDataContext, parse } = DC;

            //Create a JSON string.
            var strJSON = `{
                &quot;count&quot;: 0
            }`;

            //Interval id.
            var intervalId = null;

            //Create data context.
            const context = parse(
                //Parse the JSON string.
                strJSON,
                //Reviver function. Create data context.
                createDataContext
            );

            //Listen to the count property.
            context.on('count', (event) =&gt; {

                console.log('event:', event);

                if (event.newValue &gt; 10) {

                    console.log('I am dead.');
                    clearInterval(intervalId);

                    //I am dead. Remove listener.
                    return false;
                }

                //I am live. Continue listening.
                return true;
            });

            context.on('-change', (event) =&gt; {

                //Stringify the changes.
                var str = context.stringifyChanges(
                    //Reviver function. Default is null.
                    null,
                    //Indentation. Default is 0.
                    4,
                    //Include only modified data. Default is true.
                    true,
                    //Set data to unmodified after stringification. Default is true.
                    true
                );
                console.log('changes:', str);

                //I am live. Continue listening.
                return true;
            });

            //Start the interval.
            intervalId = setInterval(() =&gt; {

                //Increment the count property.
                context.count++;
            }, 1000);
        });

        // STEP 2. Add module import function.
        /**
         * Module import function.
         * @param {string[]} importIdentifierArray Modules to import.
         * @param {(...importModules:any[]) =&gt; void} callback Callback function.
         */
        function importModules(importIdentifierArray, callback) {

            var thisScope = &quot;undefined&quot; != typeof globalThis
                ? globalThis
                : &quot;undefined&quot; != typeof window
                    ? window
                    : &quot;undefined&quot; != typeof global
                        ? global : &quot;undefined&quot; != typeof self
                            ? self
                            : {};

            if (!thisScope.modules) { thisScope.modules = {}; }

            waitModules();


            function waitModules() {

                if (importIdentifierArray.length) {

                    for (let i = 0; i &lt; importIdentifierArray.length; i++) {

                        if (!thisScope.modules[importIdentifierArray[i]]) { return setTimeout(waitModules, 10); }
                    }
                }

                callback.call(thisScope, ...importIdentifierArray.map(function (id) { return thisScope.modules[id]; }));
            }
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h3&gt;Example 'data-context'&lt;/h3&gt;
    &lt;p&gt;Press F12. Console results.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
                    <h2 id="data-context-binding-module">'data-context-binding' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/data-context-binding" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/data-context-binding" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/data-context-binding" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/data-context-binding" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/data-context-binding/README.html">HTML5</a>.<br><br>
                        Data context binding library for browser.<br>
                        This library is used to bind data to DOM elements and update the DOM when the data changes.<br>
                    </p>
                    <h3 id="basic-usage-of-data-context-binding-module">Basic Usage of 'data-context-binding' module</h3>
                    <p><a href="https://manuel-lohmus.github.io/data-context-binding/examples/hello-world.html">hello-world.html</a>:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;data-context-binding&lt;/title&gt;
    &lt;!-- STEP 1. Import the modules 'data-context' and 'data-context-binding'.
        Import for an HTML page hosted on the server. --&gt;
    &lt;!--&lt;script src=&quot;./datacontext.js&quot;&gt;&lt;/script&gt;--&gt;
    &lt;!--&lt;script src=&quot;./browser.js&quot;&gt;&lt;/script&gt;--&gt;
    &lt;!-- STEP 1. Import the modules 'data-context' and 'data-context-binding'.
        Import for a standalone HTML page. --&gt;
    &lt;script async src=&quot;https://cdn.jsdelivr.net/npm/data-context&quot;&gt;&lt;/script&gt;
    &lt;script async src=&quot;https://cdn.jsdelivr.net/npm/data-context-binding&quot;&gt;&lt;/script&gt;
    &lt;!-- STEP 2. Add the data to a container with the ID 'data'. Its contents will be read automatically. --&gt;
    &lt;script id=&quot;data&quot; type=&quot;application/json&quot;&gt;
        {
            &quot;doc&quot;: {
                /* 1: The metadata-title context object */
                /* 2: The metadata-title context object */
                &quot;title&quot;: &quot;Hello World&quot;, // The title comment
                /* The metadata-description context object */
                &quot;description&quot;: &quot;This is a simple example of data context binding.&quot;, // The description comment
                /* { &quot;hidden&quot;: &quot;This is a must be hidden value.&quot; } */
                &quot;debug&quot;: false
            }
        }
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- STEP 3. Bind data to the DOM elements.
        In this container we use the 'doc' object.
        The 'path' attribute is part of property path. --&gt;
    &lt;div path=&quot;doc&quot;&gt;
        &lt;div&gt;
            &lt;!-- STEP 3. Bind data to the DOM elements.
            The `path` attribute  is property path in the data object.
            The `bind` attribute is performed data binding. --&gt;
            &lt;h1 path=&quot;title&quot; bind&gt;Title&lt;/h1&gt;
            &lt;!-- STEP 3. Bind data to the DOM elements.
            The `path` attribute  is property path in the data object.
            The `bind` attribute is performed data binding. --&gt;
            &lt;p path=&quot;description&quot; bind&gt;Description&lt;/p&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;hr /&gt;
    &lt;h3&gt;Edit the values:&lt;/h3&gt;
    &lt;label for=&quot;title&quot;&gt;Title:&lt;/label&gt;
    &lt;br /&gt;
    &lt;!-- STEP 3. Bind data to the DOM elements.
    The `path` attribute  is property path in the data object.
    The `bind` attribute is performed data binding. --&gt;
    &lt;input type=&quot;text&quot; path=&quot;doc.title&quot; bind style=&quot;width:380px&quot; /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    &lt;label&gt;Description:&lt;/label&gt;
    &lt;br /&gt;
    &lt;!-- STEP 3. Bind data to the DOM elements.
    The `path` attribute  is property path in the data object.
    The `bind` attribute is performed data binding. --&gt;
    &lt;input type=&quot;text&quot; path=&quot;doc.description&quot; bind style=&quot;width:380px&quot; /&gt;
    &lt;hr /&gt;
    &lt;label&gt;Live changes:&lt;/label&gt;
    &lt;br /&gt;
    &lt;!-- STEP 3. Bind data to the DOM elements.
    The `bind` attribute is performed data binding. 
    Listens for data context changes --&gt;
    &lt;textarea cols=&quot;50&quot; rows=&quot;10&quot; bind=&quot;change&quot;&gt;&lt;/textarea&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
                    <h2 id="tiny-https-server-module">'tiny-https-server' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/tiny-https-server" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/tiny-https-server" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/tiny-https-server" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/tiny-https-server" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/tiny-https-server/README.html">HTML5</a>.<br><br>
                        Tiny web server is disain for SPA (Single Page Application).<br>
                        A tiny web server serves static files, supports HTTPS, subdomains, middleware, and service workers.<br>
                    </p>
                    <h3 id="install-of-tiny-https-server-module">Install of 'tiny-https-server' module</h3>
                    <p><code>npm install tiny-https-server</code></p>
                    <h3 id="basic-usage-of-tiny-https-server-module">Basic Usage of 'tiny-https-server' module</h3>
                    <p>You can use tiny-https-server in your project like this:</p>
<pre><code class="language-javascript">const WebCluster = require('tiny-https-server');

consr cluster = WebCluster({
    isDebug: true, // Enable debug mode to see logs in the console
    parallelism: 'auto 2' // Start 2 workers and scale up and down automatically
}, function _initServer(server) {
    // Add a request handler for the /hello path
    server.on('request', (req, res, next) =&gt; {
    
        if (req.url === '/hello') {

            res.writeHead(200, { 'Content-Type': 'text/plain' });
            res.end('Hello World');
            return;
        }
    
        next();
    });
});
</code></pre>
                    <h2 id="url-fragment-extender-module">'url-fragment-extender' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/url-fragment-extender" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/url-fragment-extender" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/url-fragment-extender" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/url-fragment-extender" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/url-fragment-extender/README.html">HTML5</a>.<br><br>
                        This allows for easy manipulation and extension of URL fragments, as well as handling custom events based on the URL hash.
                    </p>
                    <h3 id="install-of-url-fragment-extender-module">Install of 'url-fragment-extender' module</h3>
                    <p>You can install 'url-fragment-extender' using this command:</p>
                    <p><code>npm install url-fragment-extender</code></p>
                    <p>and use in browser 'tiny-https-server' router:</p>
                    <p><code>&lt;script async src=&quot;node_modules/url-fragment-extender@2&quot;&gt;&lt;/script&gt;</code></p>
                    <p>or:</p>
                    <p><code>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/url-fragment-extender&quot; &gt;&lt;/script&gt;</code></p>
                    <h3 id="basic-usage-of-tiny-https-server-module-1">Basic Usage of 'tiny-https-server' module</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;url-fragment-extender&lt;/title&gt;
    &lt;!-- STEP 1. Import the modules 'url-fragment-extender'.
        Import for an HTML page hosted on the server. --&gt;
    &lt;script async type=&quot;text/javascript&quot; src=&quot;./browser.js&quot;&gt;&lt;/script&gt;
    &lt;!-- STEP 1. Import the modules 'url-fragment-extender'.
        Import for a standalone HTML page. --&gt;
    &lt;!--&lt;script async src=&quot;https://cdn.jsdelivr.net/npm/url-fragment-extender&quot;&gt;&lt;/script&gt;--&gt;
    &lt;script&gt;

        // STEP 3. Import the module.
        importModules(['url-fragment-extender'], function (UFE) {

            UFE.on('', function (event) {
                $('#content').innerHTML = '';
                //I am live. Continue listening.
                return true;
            });

            UFE.on('temp_1', function (event) {
                $('#content').innerHTML = $('#temp_1').innerHTML;
                //I am live. Continue listening.
                return true;
            });

            UFE.on('temp_2', function (event) {
                $('#content').innerHTML = $('#temp_2').innerHTML;
                //I am live. Continue listening.
                return true;
            });

            UFE.on('temp_3', function (event) {
                $('#content').innerHTML = $('#temp_3').innerHTML;
                //I am live. Continue listening.
                return true;
            });
        });


        // STEP 2. Add module import function.
        /**
         * Module import function - step 2.
         * @param {string[]} importIdentifierArray Modules to import.
         * @param {(...importModules:any[]) =&gt; void} callback Callback function.
         */
        function importModules(importIdentifierArray, cb) {

            var thisScope = &quot;undefined&quot; != typeof globalThis
                ? globalThis
                : &quot;undefined&quot; != typeof window
                    ? window
                    : &quot;undefined&quot; != typeof global
                        ? global : &quot;undefined&quot; != typeof self
                            ? self
                            : {};

            if (!thisScope.modules) { thisScope.modules = {}; }

            waitModules();


            function waitModules() {

                if (importIdentifierArray.length) {

                    for (let i = 0; i &lt; importIdentifierArray.length; i++) {

                        if (!thisScope.modules[importIdentifierArray[i]]) { return setTimeout(waitModules, 10); }
                    }
                }

                cb.call(thisScope, ...importIdentifierArray.map(function (id) { return thisScope.modules[id]; }));
            }
        }
        function $(selector, element) { return (element || document).querySelector(selector); }
    &lt;/script&gt;
    &lt;style&gt;
        .button {
            display: inline-block;
            padding: 10px 20px;
            font-size: 16px;
            color: #fff;
            background-color: #007bff;
            text-align: center;
            text-decoration: none;
            border-radius: 5px;
            transition: background-color 0.3s ease;
            margin: 5px;
        }

            .button:hover {
                background-color: #0056b3;
            }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;div&gt;
        &lt;a class=&quot;button&quot; href=&quot;#temp_1&quot;&gt;template 1&lt;/a&gt;
        &lt;a class=&quot;button&quot; href=&quot;#temp_2&quot;&gt;template 2&lt;/a&gt;
        &lt;a class=&quot;button&quot; href=&quot;#temp_3&quot;&gt;template 3&lt;/a&gt;
    &lt;/div&gt;
    &lt;br /&gt;
    &lt;div id=&quot;content&quot;&gt;&lt;/div&gt;

    &lt;template id=&quot;temp_1&quot;&gt;
        &lt;div style=&quot;background-color:darkgreen;color:whitesmoke&quot;&gt;&lt;h1&gt;template 1&lt;/h1&gt;&lt;/div&gt;
    &lt;/template&gt;
    &lt;template id=&quot;temp_2&quot;&gt;
        &lt;div style=&quot;background-color:burlywood;color:darkslateblue&quot;&gt;&lt;h2&gt;template 2&lt;/h2&gt;&lt;/div&gt;
    &lt;/template&gt;
    &lt;template id=&quot;temp_3&quot;&gt;
        &lt;div&gt;&lt;h3&gt;template 3&lt;/h3&gt;&lt;/div&gt;
    &lt;/template&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre>
                    <h2 id="ws13-module">'ws13' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/ws13" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/ws13" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/ws13" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/ws13" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/ws13/README.html">HTML5</a>.<br><br>
                        The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server.
                        With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
                    </p>
                    <h3 id="install-of-ws13-module">Install of 'ws13' module</h3>
                    <p><code>npm install ws13</code></p>
                    <h3 id="basic-usage-of-ws13-module">Basic Usage of 'ws13' module</h3>
                    <p>Example of use on a server:</p>
<pre><code class="language-javascript">const { createServer } = require('node:http');
const createWebSocket = require('ws13');

const server = createServer();
let wsList = [];

server.on('upgrade', function (request) {

    // upgrade WebSocket
    const websocket = createWebSocket({ request });

    // has WebSocket, the handshake is done
    if (websocket) {

        // inserts a WebSocket from the list
        wsList.push(websocket);

        // add listeners
        websocket
            .on('error', console.error)
            .on('open', function () {
                /* now you can send and receive messages */
            })
            .on('message', function (event) {
                // send to everyone
                wsList.forEach((ws) =&gt; { ws.send(event.data); });
            })
            .on('close', function () {
                // removing a WebSocket from the list
                wsList = wsList.filter(ws =&gt; ws !== websocket);
            });
    } else {
        // handshake not accepted
        request.destroy();
    }
});
</code></pre>
                    <h2 id="ws-user-module">'ws-user' module</h2>
                    <p>
                        <img src="https://img.shields.io/npm/l/ws-user" alt="NPM License" />
                        <img src="https://img.shields.io/npm/v/ws-user" alt="NPM Version" />
                        <img src="https://img.shields.io/npm/last-update/ws-user" alt="NPM Last Update" />
                        <img src="https://img.shields.io/npm/dt/ws-user" alt="NPM Total Downloads" />
                    </p>
                    <p>
                        This manual is also available in <a href="https://manuel-lohmus.github.io/ws-user/README.html">HTML5</a>.<br><br>
                        This module is used to manage users over WebSocket.<br>
                        It allows you to create a user manager that can handle user authentication and authorization.<br>
                    </p>
                    <h3 id="install-of-ws-user-module">Install of 'ws-user' module</h3>
                    <p><code>npm install ws-user</code></p>
                    <h3 id="basic-usage-of-ws-user-module">Basic Usage of 'ws-user' module</h3>
                    <p>
                        Use the 'ws-user' module analogous to the 'ws13' module.<br>
                        Example of use on a server:
                    </p>
<pre><code class="language-javascript">const { createServer } = require('node:http');
const { createUserManager } = require('ws-user');

const server = createServer();

server.on('upgrade', function (request) {

    const wsUser = CreateWsUser(request);

    if (wsUser) {

        wsUser.onerror = (error) =&gt; {
            console.error(error);
        };
        wsUser.onopen = () =&gt; {
            console.log('Server started');
        };
        wsUser.onclose = () =&gt; {
            console.log('Server closed');
        };
        wsUser.onmessage = (event) =&gt; {
            // Received message from client and websocket is paused, disable to receive messages
            console.log(event.data);
            wsUser.messageHandled(); // continue, websocket is open, enable to receive messages
        };
        wsUser.extensionCommands = {
            'myCommand': (event) =&gt; {
                console.log(event);
                const myData = event.message; // Received `myData` from client
                // Do something
                // Send response to client
                wsUser.send(`$myCommand:${myData}`);
                event.done(); //  or wsUser.messageHandled(); `myCommand` is handled &gt; continue, websocket is open
            }
        };
    }
});
</code></pre>
                    <br>
                    <br>
                    <br>
                </div>
            </div>
        </div>
    </div>

    <script>
        (function () {

            'use strict';

            var isIE = !!document.documentMode; // Detect IE

            if (!isIE) {

                var link, script;

                // bootstrap for styling (https://getbootstrap.com/)
                link = document.createElement('link');
                link.href = 'https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css';
                link.rel = 'stylesheet';
                link.crossOrigin = 'anonymous';
                document.head.appendChild(link);
                script = document.createElement('script');
                script.src = 'https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js';
                script.crossOrigin = 'anonymous';
                document.head.appendChild(script);

                // prism syntax highlighter for code blocks (https://prismjs.com/)
                link = document.createElement('link');
                link.href = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css';
                link.rel = 'stylesheet';
                link.crossOrigin = 'anonymous';
                document.head.appendChild(link);
                script = document.createElement('script');
                script.src = 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js';
                script.crossOrigin = 'anonymous';
                document.head.appendChild(script);

                // list-group style for headers
                document.querySelectorAll('#list-headers a')
                    .forEach(function (a) { a.classList.add('list-group-item', 'list-group-item-action') });
            }
        })();
    </script>
</body>
</html>