1
0
Fork 0
mirror of https://github.com/TheLartians/ModernCppStarter.git synced 2025-08-30 21:51:12 +02:00
This commit is contained in:
TheLartians 2023-09-18 14:22:23 +00:00
parent 8829793737
commit b8340c097b
19 changed files with 262 additions and 136 deletions

View file

@ -90,13 +90,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -90,13 +90,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -90,13 +90,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -111,13 +111,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -53,7 +53,7 @@
<div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="greeter_8h.html">&lt;greeter/greeter.h&gt;</a></div> <div class="m-doc-include m-code m-inverted m-text-right"><span class="cp">#include</span> <a class="cpf" href="greeter_8h.html">&lt;greeter/greeter.h&gt;</a></div>
</h1> </h1>
<p>A class for saying hello in multiple languages.</p> <p>A class for saying hello in multiple languages.</p>
<div class="m-block m-default"> <nav class="m-block m-default">
<h3>Contents</h3> <h3>Contents</h3>
<ul> <ul>
<li> <li>
@ -64,7 +64,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </nav>
<section id="typeless-methods"> <section id="typeless-methods">
<h2><a href="#typeless-methods">Constructors, destructors, conversion operators</a></h2> <h2><a href="#typeless-methods">Constructors, destructors, conversion operators</a></h2>
<dl class="m-doc"> <dl class="m-doc">
@ -164,13 +164,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -52,7 +52,7 @@
documentation<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span> documentation<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span>
</h1> </h1>
<p><span></span></p> <p><span></span></p>
<div class="m-block m-default"> <nav class="m-block m-default">
<h3>Contents</h3> <h3>Contents</h3>
<ul> <ul>
<li> <li>
@ -62,7 +62,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </nav>
<section id="subdirs"> <section id="subdirs">
<h2><a href="#subdirs">Directories</a></h2> <h2><a href="#subdirs">Directories</a></h2>
<dl class="m-doc"> <dl class="m-doc">
@ -108,13 +108,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -90,13 +90,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -52,7 +52,7 @@
greeter<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span> greeter<span class="m-breadcrumb">/</span> <span class="m-thin">directory</span>
</h1> </h1>
<p><span></span></p> <p><span></span></p>
<div class="m-block m-default"> <nav class="m-block m-default">
<h3>Contents</h3> <h3>Contents</h3>
<ul> <ul>
<li> <li>
@ -62,7 +62,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </nav>
<section id="files"> <section id="files">
<h2><a href="#files">Files</a></h2> <h2><a href="#files">Files</a></h2>
<dl class="m-doc"> <dl class="m-doc">
@ -108,13 +108,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -119,13 +119,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -52,7 +52,7 @@
<span class="m-breadcrumb"><a href="dir_efc517448da1cf4216d09f3867bece28.html">greeter</a>/</span>greeter.h <span class="m-thin">file</span> <span class="m-breadcrumb"><a href="dir_efc517448da1cf4216d09f3867bece28.html">greeter</a>/</span>greeter.h <span class="m-thin">file</span>
</h1> </h1>
<p><span></span></p> <p><span></span></p>
<div class="m-block m-default"> <nav class="m-block m-default">
<h3>Contents</h3> <h3>Contents</h3>
<ul> <ul>
<li> <li>
@ -63,7 +63,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </nav>
<section id="namespaces"> <section id="namespaces">
<h2><a href="#namespaces">Namespaces</a></h2> <h2><a href="#namespaces">Namespaces</a></h2>
<dl class="m-doc"> <dl class="m-doc">
@ -118,13 +118,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

File diff suppressed because one or more lines are too long

View file

@ -3,7 +3,8 @@
/* /*
This file is part of m.css. This file is part of m.css.
Copyright © 2017, 2018, 2019, 2020 Vladimír Vondruš <mosra@centrum.cz> Copyright © 2017, 2018, 2019, 2020, 2021, 2022
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -36,7 +37,7 @@ body { margin: 0; }
margin-left: -1rem; margin-left: -1rem;
margin-right: -1rem; margin-right: -1rem;
} }
.m-row:after { .m-row::after {
content: ' '; content: ' ';
clear: both; clear: both;
display: table; display: table;
@ -791,7 +792,7 @@ figure.m-figure {
position: relative; position: relative;
display: table; display: table;
} }
figure.m-figure:before { figure.m-figure::before {
position: absolute; position: absolute;
content: ' '; content: ' ';
top: 0; top: 0;
@ -804,7 +805,7 @@ figure.m-figure:before {
border-radius: 0.2rem; border-radius: 0.2rem;
border-color: #405363; border-color: #405363;
} }
figure.m-figure.m-flat:before { figure.m-figure.m-flat::before {
border-color: transparent; border-color: transparent;
} }
figure.m-figure > * { figure.m-figure > * {
@ -845,7 +846,7 @@ figure.m-figure.m-fullwidth > *:first-child {
figure.m-figure.m-fullwidth img, figure.m-figure.m-fullwidth svg { figure.m-figure.m-fullwidth img, figure.m-figure.m-fullwidth svg {
width: 100%; width: 100%;
} }
figure.m-figure.m-fullwidth:after { figure.m-figure.m-fullwidth::after {
content: ' '; content: ' ';
display: block; display: block;
margin-top: 1rem; margin-top: 1rem;
@ -858,7 +859,7 @@ figure.m-figure.m-fullwidth:after {
position: relative; position: relative;
padding: 1rem; padding: 1rem;
} }
.m-code-figure:before, .m-console-figure:before { .m-code-figure::before, .m-console-figure::before {
position: absolute; position: absolute;
content: ' '; content: ' ';
top: 0; top: 0;
@ -870,13 +871,13 @@ figure.m-figure.m-fullwidth:after {
border-width: 0.125rem; border-width: 0.125rem;
border-radius: 0.2rem; border-radius: 0.2rem;
} }
.m-code-figure:before { .m-code-figure::before {
border-color: #282e36; border-color: #282e36;
} }
.m-console-figure:before { .m-console-figure::before {
border-color: #1a1c1d; border-color: #1a1c1d;
} }
.m-code-figure.m-flat:before, .m-console-figure.m-flat:before { .m-code-figure.m-flat::before, .m-console-figure.m-flat::before {
border-color: transparent; border-color: transparent;
} }
.m-code-figure > pre:first-child, .m-console-figure > pre:first-child { .m-code-figure > pre:first-child, .m-console-figure > pre:first-child {
@ -901,6 +902,14 @@ figure.m-figure figcaption, .m-code-figure figcaption, .m-console-figure figcapt
figure.m-figure figcaption a, .m-code-figure figcaption a, .m-console-figure figcaption a { figure.m-figure figcaption a, .m-code-figure figcaption a, .m-console-figure figcaption a {
text-decoration: none; text-decoration: none;
} }
figure.m-figure figcaption .m-figure-description {
margin-top: 0.5rem;
font-weight: normal;
font-size: 1rem;
}
figure.m-figure figcaption .m-figure-description a {
text-decoration: underline;
}
.m-imagegrid > div { .m-imagegrid > div {
background-color: #2f363f; background-color: #2f363f;
} }
@ -1489,19 +1498,24 @@ table.m-table tr.m-dim td a:active, table.m-table td.m-dim a:active,
table.m-table tr.m-dim th a:active, table.m-table th.m-dim a:active { table.m-table tr.m-dim th a:active, table.m-table th.m-dim a:active {
color: #747474; color: #747474;
} }
figure.m-figure.m-default:before { border-color: #34424d; } figure.m-figure.m-default::before { border-color: #34424d; }
figure.m-figure.m-default figcaption { color: #dcdcdc; } figure.m-figure.m-default figcaption { color: #dcdcdc; }
figure.m-figure.m-primary:before { border-color: #a5c2db; } figure.m-figure.m-primary::before { border-color: #a5c2db; }
figure.m-figure.m-primary figcaption { color: #a5c9ea; } figure.m-figure.m-primary figcaption { color: #a5c9ea; }
figure.m-figure.m-success:before { border-color: #2a703f; } figure.m-figure.m-primary figcaption .m-figure-description { color: #dcdcdc; }
figure.m-figure.m-success::before { border-color: #2a703f; }
figure.m-figure.m-success figcaption { color: #3bd267; } figure.m-figure.m-success figcaption { color: #3bd267; }
figure.m-figure.m-warning:before { border-color: #6d702a; } figure.m-figure.m-success figcaption .m-figure-description { color: #dcdcdc; }
figure.m-figure.m-warning:::before { border-color: #6d702a; }
figure.m-figure.m-warning figcaption { color: #c7cf2f; } figure.m-figure.m-warning figcaption { color: #c7cf2f; }
figure.m-figure.m-danger:before { border-color: #702b2a; } figure.m-figure.m-warning figcaption .m-figure-description { color: #dcdcdc; }
figure.m-figure.m-danger:::before { border-color: #702b2a; }
figure.m-figure.m-danger figcaption { color: #cd3431; } figure.m-figure.m-danger figcaption { color: #cd3431; }
figure.m-figure.m-info:before { border-color: #2a4f70; } figure.m-figure.m-danger figcaption .m-figure-description { color: #dcdcdc; }
figure.m-figure.m-info:::before { border-color: #2a4f70; }
figure.m-figure.m-info figcaption { color: #2f83cc; } figure.m-figure.m-info figcaption { color: #2f83cc; }
figure.m-figure.m-dim:before { border-color: #2d3236; } figure.m-figure.m-info figcaption .m-figure-description { color: #dcdcdc; }
figure.m-figure.m-dim:::before { border-color: #2d3236; }
figure.m-figure.m-dim { color: #747474; } figure.m-figure.m-dim { color: #747474; }
figure.m-figure.m-dim a { color: #acacac; } figure.m-figure.m-dim a { color: #acacac; }
figure.m-figure.m-dim a:hover, figure.m-figure.m-dim a:focus, figure.m-figure.m-dim a:active { figure.m-figure.m-dim a:hover, figure.m-figure.m-dim a:focus, figure.m-figure.m-dim a:active {
@ -1885,7 +1899,7 @@ body > header > nav #m-navbar-brand .m-thin {
body > header > nav #m-navbar-brand .m-breadcrumb { body > header > nav #m-navbar-brand .m-breadcrumb {
color: #747474; color: #747474;
} }
body > header > nav a#m-navbar-show:before, body > header > nav a#m-navbar-hide:before { body > header > nav a#m-navbar-show::before, body > header > nav a#m-navbar-hide::before {
content:'\2630'; content:'\2630';
} }
body > header > nav #m-navbar-collapse { body > header > nav #m-navbar-collapse {
@ -2641,8 +2655,8 @@ ul.m-doc li.m-doc-collapsible > a:first-child:active {
color: #dcdcdc; color: #dcdcdc;
} }
a.m-doc-self, a.m-doc-self,
ul.m-doc li.m-doc-expansible > a:first-child:before, ul.m-doc li.m-doc-expansible > a:first-child::before,
ul.m-doc li.m-doc-collapsible > a:first-child:before { ul.m-doc li.m-doc-collapsible > a:first-child::before {
color: #a5c9ea; color: #a5c9ea;
} }
a.m-doc-self:hover, a.m-doc-self:focus, a.m-doc-self:active, a.m-doc-self:hover, a.m-doc-self:focus, a.m-doc-self:active,
@ -2703,14 +2717,14 @@ ul.m-doc li.m-doc-expansible, ul.m-doc li.m-doc-collapsible {
ul.m-doc li.m-doc-expansible > ul.m-doc, ul.m-doc li.m-doc-collapsible > ul.m-doc { ul.m-doc li.m-doc-expansible > ul.m-doc, ul.m-doc li.m-doc-collapsible > ul.m-doc {
margin-left: 0.5rem; margin-left: 0.5rem;
} }
ul.m-doc li.m-doc-expansible > a:first-child:before, ul.m-doc li.m-doc-collapsible > a:first-child:before { ul.m-doc li.m-doc-expansible > a:first-child::before, ul.m-doc li.m-doc-collapsible > a:first-child::before {
background-color: #2f363f; background-color: #2f363f;
display: inline-block; display: inline-block;
width: 0.4rem; width: 0.4rem;
font-weight: bold; font-weight: bold;
} }
ul.m-doc li.m-doc-expansible > a:first-child:before { content: '⊕'; } ul.m-doc li.m-doc-expansible > a:first-child::before { content: '⊕'; }
ul.m-doc li.m-doc-collapsible > a:first-child:before { content: '⊖'; } ul.m-doc li.m-doc-collapsible > a:first-child::before { content: '⊖'; }
h1 .m-doc-template, h1 .m-doc-include { h1 .m-doc-template, h1 .m-doc-include {
font-size: 1.3rem; font-size: 1.3rem;
font-weight: normal; font-weight: normal;

View file

@ -105,13 +105,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -52,7 +52,7 @@
greeter <span class="m-thin">namespace</span> greeter <span class="m-thin">namespace</span>
</h1> </h1>
<p><span></span></p> <p><span></span></p>
<div class="m-block m-default"> <nav class="m-block m-default">
<h3>Contents</h3> <h3>Contents</h3>
<ul> <ul>
<li> <li>
@ -63,7 +63,7 @@
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </nav>
<section id="nested-classes"> <section id="nested-classes">
<h2><a href="#nested-classes">Classes</a></h2> <h2><a href="#nested-classes">Classes</a></h2>
<dl class="m-doc"> <dl class="m-doc">
@ -133,13 +133,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -106,13 +106,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -106,13 +106,13 @@
</div> </div>
</div> </div>
</div> </div>
<script src="search-v1.js"></script> <script src="search-v2.js"></script>
<script src="searchdata-v1.js" async="async"></script> <script src="searchdata-v2.js" async="async"></script>
<footer><nav> <footer><nav>
<div class="m-container"> <div class="m-container">
<div class="m-row"> <div class="m-row">
<div class="m-col-l-10 m-push-l-1"> <div class="m-col-l-10 m-push-l-1">
<p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.1 and <a href="https://mcss.mosra.cz/">m.css</a>.</p> <p>Greeter. Created with <a href="https://doxygen.org/">Doxygen</a> 1.9.8 and <a href="https://mcss.mosra.cz/">m.css</a>.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,8 @@
/* /*
This file is part of m.css. This file is part of m.css.
Copyright © 2017, 2018, 2019, 2020 Vladimír Vondruš <mosra@centrum.cz> Copyright © 2017, 2018, 2019, 2020, 2021, 2022
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,15 +26,27 @@
"use strict"; /* it summons the Cthulhu in a proper way, they say */ "use strict"; /* it summons the Cthulhu in a proper way, they say */
var Search = { var Search = {
formatVersion: 1, /* the data filename contains this number too */ formatVersion: 2, /* the data filename contains this number too */
dataSize: 0, /* used mainly by tests, not here */ dataSize: 0, /* used mainly by tests, not here */
symbolCount: '&hellip;', symbolCount: '&hellip;',
trie: null, trie: null,
map: null, map: null,
mapFlagsOffset: null,
typeMap: null, typeMap: null,
maxResults: 0, maxResults: 0,
/* Type sizes and masks. The data is always fetched as 16/32bit number and
then masked to 1, 2, 3 or 4 bytes. Fortunately on LE a mask is enough,
on BE we'd have to read N bytes before and then mask. */
nameSizeBytes: null,
nameSizeMask: null,
resultIdBytes: null,
resultIdMask: null,
fileOffsetBytes: null,
fileOffsetMask: null,
lookaheadBarrierMask: null,
/* Always contains at least the root node offset and then one node offset /* Always contains at least the root node offset and then one node offset
per entered character */ per entered character */
searchString: '', searchString: '',
@ -57,7 +70,7 @@ var Search = {
/* The file is too short to contain at least the headers and empty /* The file is too short to contain at least the headers and empty
sections */ sections */
if(view.byteLength < 26) { if(view.byteLength < 31) {
console.error("Search data too short"); console.error("Search data too short");
return false; return false;
} }
@ -74,16 +87,61 @@ var Search = {
return false; return false;
} }
/* Separate the data into the trie and the result map */ /* Fetch type sizes. The only value that can fail is result ID byte
let mapOffset = view.getUint32(6, true); count, where value of 3 has no assigned meaning. */
let typeMapOffset = view.getUint32(10, true); let typeSizes = view.getUint8(4, true);
this.trie = new DataView(buffer, 14, mapOffset - 14); if((typeSizes & 0x01) >> 0 == 0) {
this.map = new DataView(buffer, mapOffset, typeMapOffset - mapOffset); this.fileOffsetBytes = 3;
this.fileOffsetMask = 0x00ffffff;
this.lookaheadBarrierMask = 0x00800000;
} else /* (typeSizes & 0x01) >> 0 == 1 */ {
this.fileOffsetBytes = 4;
this.fileOffsetMask = 0xffffffff;
this.lookaheadBarrierMask = 0x80000000;
}
if((typeSizes & 0x06) >> 1 == 0) {
this.resultIdBytes = 2;
this.resultIdMask = 0x0000ffff;
} else if((typeSizes & 0x06) >> 1 == 1) {
this.resultIdBytes = 3;
this.resultIdMask = 0x00ffffff;
} else if((typeSizes & 0x06) >> 1 == 2) {
this.resultIdBytes = 4;
this.resultIdMask = 0xffffffff;
} else /* (typeSizes & 0x06) >> 1 == 3 */ {
console.error("Invalid search data result ID byte value");
return false;
}
if((typeSizes & 0x08) >> 3 == 0) {
this.nameSizeBytes = 1;
this.nameSizeMask = 0x00ff;
} else /* (typeSizes & 0x08) >> 3 == 1 */ {
this.nameSizeBytes = 2;
this.nameSizeMask = 0xffff;
}
/* Separate the data into the trie and the result / type map. Because
we're reading larger values than there might be and then masking out
the high bytes, keep extra 1/2 byte padding at the end to avoid
OOB errors. */
let mapOffset = view.getUint32(12, true);
let typeMapOffset = view.getUint32(16, true);
/* There may be a 3-byte file offset at the end of the trie which we'll
read as 32-bit, add one safety byte in that case */
this.trie = new DataView(buffer, 20, mapOffset - 20 + (4 - this.fileOffsetBytes));
/* There may be a 3-byte file size (for zero results) which we'll read
as 32-bit, add one safety byte in that case */
this.map = new DataView(buffer, mapOffset, typeMapOffset - mapOffset + (4 - this.fileOffsetBytes));
/* No variable-size types in the type map at the moment */
this.typeMap = new DataView(buffer, typeMapOffset); this.typeMap = new DataView(buffer, typeMapOffset);
/* Offset of the first result map item is after N + 1 offsets and N
flags, calculate flag offset from that */
this.mapFlagsOffset = this.fileOffsetBytes*(((this.map.getUint32(0, true) & this.fileOffsetMask) - this.fileOffsetBytes)/(this.fileOffsetBytes + 1) + 1);
/* Set initial properties */ /* Set initial properties */
this.dataSize = buffer.byteLength; this.dataSize = buffer.byteLength;
this.symbolCount = view.getUint16(4, true) + " symbols (" + Math.round(this.dataSize/102.4)/10 + " kB)"; this.symbolCount = view.getUint32(8, true) + " symbols (" + Math.round(this.dataSize/102.4)/10 + " kB)";
this.maxResults = maxResults ? maxResults : 100; this.maxResults = maxResults ? maxResults : 100;
this.searchString = ''; this.searchString = '';
this.searchStack = [this.trie.getUint32(0, true)]; this.searchStack = [this.trie.getUint32(0, true)];
@ -256,25 +314,26 @@ var Search = {
for(; foundPrefix != searchString.length; ++foundPrefix) { for(; foundPrefix != searchString.length; ++foundPrefix) {
/* Calculate offset and count of children */ /* Calculate offset and count of children */
let offset = this.searchStack[this.searchStack.length - 1]; let offset = this.searchStack[this.searchStack.length - 1];
let relChildOffset = 2 + this.trie.getUint8(offset)*2;
/* Calculate child count. If there's a lot of results, the count /* If there's a lot of results, the result count is a 16bit BE value
"leaks over" to the child count storage. */ instead */
let resultCount = this.trie.getUint8(offset); let resultCount = this.trie.getUint8(offset);
let childCount = this.trie.getUint8(offset + 1); let resultCountSize = 1;
if(resultCount & 0x80) { if(resultCount & 0x80) {
resultCount = (resultCount & 0x7f) | ((childCount & 0xf0) << 3); resultCount = this.trie.getUint16(offset, false) & ~0x8000;
childCount = childCount & 0x0f; ++resultCountSize;
} }
let childCount = this.trie.getUint8(offset + resultCountSize);
/* Go through all children and find the next offset */ /* Go through all children and find the next offset */
let childOffset = offset + relChildOffset; let childOffset = offset + resultCountSize + 1 + resultCount*this.resultIdBytes;
let found = false; let found = false;
for(let j = 0; j != childCount; ++j) { for(let j = 0; j != childCount; ++j) {
if(String.fromCharCode(this.trie.getUint8(childOffset + j*4 + 3)) != searchString[foundPrefix]) if(String.fromCharCode(this.trie.getUint8(childOffset + j)) != searchString[foundPrefix])
continue; continue;
this.searchStack.push(this.trie.getUint32(childOffset + j*4, true) & 0x007fffff); this.searchStack.push(this.trie.getUint32(childOffset + childCount + j*this.fileOffsetBytes, true) & this.fileOffsetMask & ~this.lookaheadBarrierMask);
found = true; found = true;
break; break;
} }
@ -322,15 +381,17 @@ var Search = {
"leaks over" to the child count storage. */ "leaks over" to the child count storage. */
/* TODO: hmmm. this is helluvalot duplicated code. hmm. */ /* TODO: hmmm. this is helluvalot duplicated code. hmm. */
let resultCount = this.trie.getUint8(offset); let resultCount = this.trie.getUint8(offset);
let childCount = this.trie.getUint8(offset + 1); let resultCountSize = 1;
if(resultCount & 0x80) { if(resultCount & 0x80) {
resultCount = (resultCount & 0x7f) | ((childCount & 0xf0) << 3); resultCount = this.trie.getUint16(offset, false) & ~0x8000;
childCount = childCount & 0x0f; ++resultCountSize;
} }
let childCount = this.trie.getUint8(offset + resultCountSize);
/* Populate the results with all values associated with this node */ /* Populate the results with all values associated with this node */
for(let i = 0; i != resultCount; ++i) { for(let i = 0; i != resultCount; ++i) {
let index = this.trie.getUint16(offset + 2 + i*2, true); let index = this.trie.getUint32(offset + resultCountSize + 1 + i*this.resultIdBytes, true) & this.resultIdMask;
results.push(this.gatherResult(index, suffixLength, 0xffffff)); /* should be enough haha */ results.push(this.gatherResult(index, suffixLength, 0xffffff)); /* should be enough haha */
/* 'nuff said. */ /* 'nuff said. */
@ -339,17 +400,15 @@ var Search = {
} }
/* Dig deeper */ /* Dig deeper */
/* TODO: hmmm. this is helluvalot duplicated code. hmm. */ let childOffset = offset + resultCountSize + 1 + resultCount*this.resultIdBytes;
let relChildOffset = 2 + this.trie.getUint8(offset)*2;
let childOffset = offset + relChildOffset;
for(let j = 0; j != childCount; ++j) { for(let j = 0; j != childCount; ++j) {
let offsetBarrier = this.trie.getUint32(childOffset + j*4, true); let offsetBarrier = this.trie.getUint32(childOffset + childCount + j*this.fileOffsetBytes, true) & this.fileOffsetMask;
/* Lookahead barrier, don't dig deeper */ /* Lookahead barrier, don't dig deeper */
if(offsetBarrier & 0x00800000) continue; if(offsetBarrier & this.lookaheadBarrierMask) continue;
/* Append to the queue */ /* Append to the queue */
leaves.push([offsetBarrier & 0x007fffff, suffixLength + 1]); leaves.push([offsetBarrier & ~this.lookaheadBarrierMask, suffixLength + 1]);
/* We don't have anything yet and this is the only path /* We don't have anything yet and this is the only path
forward, add the char to suggested Tab autocompletion. Can't forward, add the char to suggested Tab autocompletion. Can't
@ -360,7 +419,7 @@ var Search = {
absolutely unwanted when all I want is check for truncated absolutely unwanted when all I want is check for truncated
UTF-8. */ UTF-8. */
if(!results.length && leaves.length == 1 && childCount == 1) if(!results.length && leaves.length == 1 && childCount == 1)
suggestedTabAutocompletionChars.push(this.trie.getUint8(childOffset + j*4 + 3)); suggestedTabAutocompletionChars.push(this.trie.getUint8(childOffset + j));
} }
} }
@ -368,38 +427,38 @@ var Search = {
}, },
gatherResult: function(index, suffixLength, maxUrlPrefix) { gatherResult: function(index, suffixLength, maxUrlPrefix) {
let flags = this.map.getUint8(index*4 + 3); let flags = this.map.getUint8(this.mapFlagsOffset + index);
let resultOffset = this.map.getUint32(index*4, true) & 0x00ffffff; let resultOffset = this.map.getUint32(index*this.fileOffsetBytes, true) & this.fileOffsetMask;
/* The result is an alias, parse the aliased prefix */ /* The result is an alias, parse the aliased prefix */
let aliasedIndex = null; let aliasedIndex = null;
if((flags & 0xf0) == 0x00) { if((flags & 0xf0) == 0x00) {
aliasedIndex = this.map.getUint16(resultOffset, true); aliasedIndex = this.map.getUint32(resultOffset, true) & this.resultIdMask;
resultOffset += 2; resultOffset += this.resultIdBytes;
} }
/* The result has a prefix, parse that first, recursively */ /* The result has a prefix, parse that first, recursively */
let name = ''; let name = '';
let url = ''; let url = '';
if(flags & (1 << 3)) { if(flags & (1 << 3)) {
let prefixIndex = this.map.getUint16(resultOffset, true); let prefixIndex = this.map.getUint32(resultOffset, true) & this.resultIdMask;
let prefixUrlPrefixLength = Math.min(this.map.getUint8(resultOffset + 2), maxUrlPrefix); let prefixUrlPrefixLength = Math.min(this.map.getUint16(resultOffset + this.resultIdBytes, true) & this.nameSizeMask, maxUrlPrefix);
let prefix = this.gatherResult(prefixIndex, 0 /*ignored*/, prefixUrlPrefixLength); let prefix = this.gatherResult(prefixIndex, 0 /*ignored*/, prefixUrlPrefixLength);
name = prefix.name; name = prefix.name;
url = prefix.url; url = prefix.url;
resultOffset += 3; resultOffset += this.resultIdBytes + this.nameSizeBytes;
} }
/* The result has a suffix, extract its length */ /* The result has a suffix, extract its length */
let resultSuffixLength = 0; let resultSuffixLength = 0;
if(flags & (1 << 0)) { if(flags & (1 << 0)) {
resultSuffixLength = this.map.getUint8(resultOffset); resultSuffixLength = this.map.getUint16(resultOffset, true) & this.nameSizeMask;
++resultOffset; resultOffset += this.nameSizeBytes;
} }
let nextResultOffset = this.map.getUint32((index + 1)*4, true) & 0x00ffffff; let nextResultOffset = this.map.getUint32((index + 1)*this.fileOffsetBytes, true) & this.fileOffsetMask;
/* Extract name */ /* Extract name */
let j = resultOffset; let j = resultOffset;
@ -708,7 +767,6 @@ if(typeof document !== 'undefined') {
document.body.style.overflow = 'auto'; document.body.style.overflow = 'auto';
document.body.style.paddingRight = '0'; document.body.style.paddingRight = '0';
} }
return false; /* so the form doesn't get sent */ return false; /* so the form doesn't get sent */
/* Copy (Markdown) link to keyboard */ /* Copy (Markdown) link to keyboard */
@ -739,9 +797,63 @@ if(typeof document !== 'undefined') {
excluding Ctrl-key, which is usually not for text input. In the excluding Ctrl-key, which is usually not for text input. In the
worst case the autocompletion won't be allowed ever, which is worst case the autocompletion won't be allowed ever, which is
much more acceptable behavior than having no ability to disable much more acceptable behavior than having no ability to disable
it and annoying the users. See also this WONTFIX Android bug: it and annoying the users. */
https://bugs.chromium.org/p/chromium/issues/detail?id=118639 */ } else if(event.key != 'Backspace' && event.key != 'Delete' && !event.metaKey && (!event.ctrlKey || event.altKey)
} else if(event.key != 'Backspace' && event.key != 'Delete' && !event.metaKey && (!event.ctrlKey || event.altKey)) { /* Don't ever attempt autocompletion with Android virtual
keyboards, as those report all `event.key`s as
`Unidentified` (on Chrome) or `Process` (on Firefox) with
`event.code` 229 and thus we have no way to tell if a text
is entered or deleted. See this WONTFIX bug for details:
https://bugs.chromium.org/p/chromium/issues/detail?id=118639
Couldn't find any similar bugreport for Firefox, but I
assume the virtual keyboard is to blame.
An alternative is to hook into inputEvent, which has the
data, but ... there's more cursed issues right after that:
- setSelectionRange() in Chrome on Android only renders
stuff, but doesn't actually act as such. Pressing
Backspace will only remove the highlight, but the text
stays here. Only delay-calling it through a timeout will
work as intended. Possibly related SO suggestion (back
then not even the rendering worked properly):
https://stackoverflow.com/a/13235951
Possibly related Chrome bug:
https://bugs.chromium.org/p/chromium/issues/detail?id=32865
- On Firefox Mobile, programmatically changing an input
value (for the autocompletion highlight) will trigger an
input event, leading to search *and* autocompletion being
triggered again. Ultimately that results in newly typed
characters not replacing the autocompletion but rather
inserting before it, corrupting the searched string. This
event has to be explicitly ignored.
- On Firefox Mobile, deleting a highlight with the
backspace key will result in *three* input events instead
of one:
1. `deleteContentBackward` removing the selection (same
as Chrome or desktop Firefox)
2. `deleteContentBackward` removing *the whole word*
that contained the selection (or the whole text if
it's just one word)
3. `insertCompositionText`, adding the word back in,
resulting in the same state as (1).
I have no idea WHY it has to do this (possibly some
REALLY NASTY workaround to trigger correct font shaping?)
but ultimately it results in the autocompletion being
added again right after it got deleted, making this whole
thing VERY annoying to use.
I attempted to work around the above, but it resulted in a
huge amount of browser-specific code that achieves only 90%
of the goal, with certain corner cases still being rather
broken (such as autocompletion randomly triggering when
erasing the text, even though it shouldn't). So disabling
autocompletion on this HELLISH BROKEN PLATFORM is the best
option at the moment. */
&& event.key != 'Unidentified' && event.key != 'Process'
) {
Search.autocompleteNextInputEvent = true; Search.autocompleteNextInputEvent = true;
/* Otherwise reset the flag, because when the user would press e.g. /* Otherwise reset the flag, because when the user would press e.g.
the 'a' key and then e.g. ArrowRight (which doesn't trigger the 'a' key and then e.g. ArrowRight (which doesn't trigger

View file

@ -1,2 +0,0 @@
/* Generated by https://mcss.mosra.cz/documentation/doxygen/. Do not edit. */
Search.load('O+!-w5dg9R006cH004pl000311ONa51ONbN009U904@Ll4gdgh009&L0A&CH8UO%v00AHX0A&CHCIA3s00Arj0CE5UG5`Q)0RRO60RRU800KS$0B%A60CNEV1^@s7PyhgB0RRX900CM60CE5WMgRb1Q~&^EUH|}Q00CqG06GBy2>@~cfI0vHcmM!p00Dpi0Av6Gh5!I>00E2u0Am0Fk^lf@00Ec)0A~OJo&W%000E=`0CfNXssI3I00FQ70B!&Qwg3QO0RRjD00F`P04V_h3joFdfG7X~%m4s#0RRpF00G(n04V_i4FJ>t0A=0)fG7X~<NyG400Hm-0A&CH_5c8700H~}0CE5U0s#PL009UA06GE!4*&}Q4gr8V#sGjQ009&M0CE8W4FDnm0A=0)fG7X~C;<R;00A@s0A&CHIspJ>00BS&0CE5VyZ``fMgah400B$^06GN(0ssmC4*&oF3jjC(fG-FD04`PmfI7wifG7X~Tmb-b0RjyGcmV)q-T;6o00Djh0CWHWiU9y+00EEz0A&CHmH_~A0RRC200E)_0Av6GrU3wL00FE404@LlvH<{P00FoG0BryPz5xJa00G1S0AT<D$^ign0RRvH00Gtk0CNBV+5rG%00H0u0A~OJ<^cd<00Ha)0B`{T0|4>?fG+?6_yGWJ009630B-;R1_A(S009gF0CWHW5&{5W009^R0CWHW9s&Sv00ATd0A&CHDgpp)00A%p0CfNXHUa=+00KM$0B=wL0A&FH5&!@JOacIS00B?}0B-;RRssNI0Ra&JTmk?t00CkG0CWHWY61Xt00D3U0B-;Rb^-um00^7`0B6tv0CGYC0A#!X0BlA80A*eP0A}m~0C0Q)0AWx70Dyr20Fa;n01&bO0D$QL0GI{=0N5`90N7Xo0N8;60NAPl0Lb0}03iDT0I4_v0I56z0I7Zg0I7lk07$F?0EpWH01)c}0FVR&003ulWo2|_asXs$a$jX;V>K~1G&DG5VKHN7G%_(ZWH32qGdMOkVr64xGB_@1bZu->ML|SOMJ{b*0AF%nWnW=mWM6GxWnVaLWG-lQZEQz!Wo2|_asX*=WMz0RXmo9CWN%}2ZDnqBVRUJ4ZUAIya$hksIALaHGd3_~VmUT7V>B~jIW#ghH)1$sF=J&gIb|+rbZu+^001v%a%E+7WpXZP0B3S#Wprh7UpQzkXmo9C2>>@bIz>(ZVPRo7HD)n5G%#f{I5K27VK_4|G-P69GGj1gH)A<sG6?`TIyyu}0AVv>H8N&1V=^*jWHx4FWMwsCW;QuCVK!qhGGjSqH!}$UH##~+QvhKwG-EM2W??a9H#ah2Vm3BrFkxY2GG%6EHZf*0HDhE605>{1Mp6J_F)?9fWMnX9G&3?cG&f^1Vq;`EH)1$4I50S5GBjZ@3IG*4I!s}1XLVs`WkYXdWdI{#VK_20VPj=vG&C|eH#s$CWo9xrG&wUcV>V+lGGt;fXL4m_bY*e?ZeeX@b8ul}WoL3_Wprh7E@*UZY!3h(4LUkUa%E+7WpXHUbYwa@b98cPZf7X~BVjORVm352Gh<<5F*Z0hWHVx6V>dZwVPP{kGdE&oGB*nVKMM~49TYk`XL4m_bSO+=ZfA92XJtcgWMwHJV{dMAbO0k^G&VA1Vly-`Gc`0cW;8HjI5apgIW;&qFkv%hFfn5_4FEq90000wI!AJ4Wprh70Ap-nb8}~MWo2|_a$hlDF<)nLWo2|_axQ3eZEOPo1TS!5XJvB$GcjQ^H#lQBG-5e5HaIpmGch@1VL4<uGC4G6F*!9kE@*UZY(Zjgb#wq>VsCYHE@*UZY++(=b#yLdZ+HM<VsCYHUpQoMcrIvkZEOM_0U`n`0WbkI0XqRe14jc&1x^K00ayTB0Av7XaA9X<ZeeX@b8ul}WoL44b#P;BVRLhHbaHiLbaifNZ*FvXaAjm=W@Kq{W@&6?W_503WMyV)Ze?X|b!}yCb!{MaVQh9`asU7T');

2
searchdata-v2.js Normal file
View file

@ -0,0 +1,2 @@
/* Generated by https://mcss.mosra.cz/documentation/doxygen/. Do not edit. */
Search.load('O+!-x000005dZ)HxB>tGy9EFMf&u^l0RRL500C$O00001E(ibs00D9i00001WfTAa00DFw00001Wgq|m00Ctt00001ax4G<00Cz*000311pom62LJ#9ZgV~W073u&0RRR700CuC000312mk;9a#{cY00U)YW<~%2Q~&^800001I%EI<0RagBI&uJj00Cuq00001WPktw00D1?00001V~hX*00Cu^00001XP5v000Cj100001b)*0Q00C#J00001Zm<9V00CjP000313;+NDDZ&5%0RamDD8>MQ00DB$000314gdfFDcS%40RjyGWhm4D0NwzA00DI500001W$*w100Cw800001a{K@Q00CzL0RR92ItT#(0s;>J3jjJO4grA10Du4iaufjo0RjyGWhf#60NwzA00DF;0RR92Wi$Z*00Ct>0RR92azFt900L}hyZ``30RR92I!plo1q1>B3IGoP000XBFD^PLH~@eM00342fW`oT00DAb0RRC44FF{*cmV+30Du4ibbbK<00Cu+0RR92Wsm^?00DBA0RRC20RR92WTF8800C{L0RR92F026n00CvP0RR92ZMXpd00Csa0RR92VZ;Fd00Cvn0RRC25C8xHbJhU>00Cv%0RR92XW#(<00Cj<0RR92aO?p90RaO5FY*C^00D0J0RR92ZvX-S00C(R0ssI3bPNIj00ChV0ssI3bQl5v00C|u0ssI3Wh4Rs00C_(0ssI3bua<|00Cn*0ssI4Z)H3J08jt`0RR#J00DSR0ssI3Z%_gN00CrH0ssL45dbb+0ssI3bYcPk00DJs0ssI3Z*T$t00Cll0ssIAXL4k0WoB?;oB;sP0RTb*0K5PIMgRa_008U(0DJ-fPXGXb005r=0I>i7=l}o(0RS!m09OG3fB^uh0RY_r0Qvy{Hv#}V0swsi0D%Gks{#Pp0s!g)00RR6fRGS?nAq6Z*vKHMsi~<*h!Buxa%E+7WpV&yX>wm>W@9xmH#9UjWMMI5W;8M}He@h4W-~Z8H)3UDWimJ}Xmo9CQbj>TO+_wkWB^}sUu9omUu0ixUu9o7ZDcNJbZu-$a%E+7WpV&%Ze(S6E@*UZY-Dd^b!}yCbYXO9Z*Bl&X>wmNGdN*pW-~T0WnwutHDfe0VmUN2HaB88WHDo9Fgax|Xmo9C0000lXL4m_bY*fbXaHw&Wo2|_a$h)TE@*UZYzY82Iyyy80AXQaI5lQ5I5aS2GB`41IAJ(5Ff?RhV=`kfWH)0uVloK;H##~*MF3$lVKp*lGh;F`Wn?yHV`ODDVrDiuHeohnFfwB~Wj8Yk05>{1MN<G_Ff?N^Ic8xoWj8l6VPZBmW-wu4WHM!DWi~NpGBsml2>>@bI!00eVKFgbWn^S9Wi&G~H#9e6GGb$7IX7ZBGB_|eWHK~iFbV(_Iyy{YZfA92XJtcgWMu#&VPQBjG+|?9WHdA~I5#;pW@TnFH#9jjFk?1jGBRXhFlTaQWprh70B&JzWpi+0V`XP@Wo2|_axQ3eZEOz!9Su4<M{;FlbY*fVb97`nI&*Y#X>MmJ03%^AW@0upH8W#jVlg&2He@qmVPiKrW?^A7I5Rh5WimGl06z;4038%MI%jfaWppS^VQy!2VP|DSZ)9aDAY*TCb94YBVKg=}WMVTkF*7wZG-fm~VmLH7FgZ0iI51%|W-u{hH4Oki5&!@IIyy&kWo2|_asXp&VRLh5a%E+7WpZCJUol^2a%E+7WpXZPbZu+{00b{^VP|D?05dURGdDP6I5c88H8walHZw6fV_`XDIWjpkW-&Q6IWA~)ZEQheZ*_D4VPbD}bS`LgZERs;Z*_DoWN&x?VPbD}bYD1RZ+I?fbZu+`9swc(D*-S8H32&TKm$huN(D{@QUO>1TmWPMXK-O>Wo}_@Wpi+0V`XP@Z*_2EY+-YAb98cbV{~<HX>V?Hd2nT9WoBe)a%O34WoC75V`OD!X>Mg@Zgp*CZgp)Sc42IGVR8Tf');