#wip: In Dev client and server connection.

This commit is contained in:
KyMAN 2026-05-25 07:26:02 +02:00
parent ddfe1ab942
commit db7b69ad45
115 changed files with 10512 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
/Data
/Public/data
*.[Ss]ecrets.*
*.[Ss]ecret.*
*.deleted.*
/Python/websockets
__pycache__
.sass-cache

BIN
Artbook/AnP_telegram.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

353
Artbook/AnPv1.svg Executable file
View File

@ -0,0 +1,353 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg8"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="AnPv1.svg">
<style
id="style833"></style>
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="403.71853"
inkscape:cy="404.92376"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Capa 1"
inkscape:groupmode="layer"
id="layer1"
style="display:none"
sodipodi:insensitive="true">
<path
id="path835"
style="opacity:0.996;fill:#000000;stroke-width:5.72927;stroke-linecap:round;stroke-linejoin:round"
d="M 264.56641,0 A 264.56693,264.56693 0 0 0 0,264.56641 H 37.794922 A 226.77165,226.77165 0 0 1 264.18555,37.794922 a 226.77165,226.77165 0 0 1 0.38086,0 z"
transform="scale(0.26458333)" />
<path
id="path835-2"
style="opacity:0.996;fill:#000000;stroke-width:1.51587;stroke-linecap:round;stroke-linejoin:round"
d="m 0,130 a 70,70 0 0 0 69.99987,69.99987 v -9.99991 a 59.999999,59.999999 0 0 1 -59.9999601,-59.89919 59.999999,59.999999 0 0 1 0,-0.10077 z" />
<path
id="path835-6"
style="opacity:0.996;fill:#000000;stroke-width:1.51587;stroke-linecap:round;stroke-linejoin:round"
d="m 130,199.99987 a 70,70 0 0 0 69.99987,-69.99986 h -9.99991 a 59.999999,59.999999 0 0 1 -59.89919,59.99995 59.999999,59.999999 0 0 1 -0.10077,0 z" />
<path
id="path835-2-7"
style="opacity:0.996;fill:#000000;stroke-width:1.51587;stroke-linecap:round;stroke-linejoin:round"
d="M 199.99987,69.99987 A 70,70 0 0 0 130,0 v 9.99991 a 59.999999,59.999999 0 0 1 59.99996,59.89919 59.999999,59.999999 0 0 1 0,0.10077 z" />
<path
sodipodi:type="star"
style="opacity:0.996;fill:#000000;stroke-width:0.829;stroke-linecap:round;stroke-linejoin:round"
id="path909-2"
sodipodi:sides="3"
sodipodi:cx="71.8955"
sodipodi:cy="79.111778"
sodipodi:r1="39.848263"
sodipodi:r2="19.924133"
sodipodi:arg1="0.51165873"
sodipodi:arg2="1.5588563"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 106.64054,98.622453 37.626242,99.446526 71.419721,39.266356 Z"
inkscape:transform-center-x="-4.9775112"
inkscape:transform-center-y="-0.016887793"
transform="matrix(-0.00696336,0.43462046,-0.50129215,-0.00603725,175.18124,34.247249)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.236261"
id="rect926"
width="10"
height="60"
x="0"
y="70" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.236261"
id="rect926-2"
width="10"
height="60"
x="190"
y="70" />
<path
id="path943"
style="opacity:0.996;fill:#000000;stroke-width:0.792813;stroke-linecap:round;stroke-linejoin:round"
d="M 90.000039,50.079065 A 19.999999,19.999999 0 0 0 109.99985,69.999814 V 59.999908 A 10,10 0 0 1 99.999943,50 h -9.999904 a 19.999999,19.999999 0 0 0 0,0.07906 z" />
<path
id="rect926-2-8"
style="fill:#000000;fill-rule:evenodd;stroke-width:0.236261"
d="m 96.457372,0 a 40.000287,40.000367 0 0 1 8.183998,9.9999063 h 20.35845 V 0 Z" />
<path
id="path943-4"
style="opacity:0.996;fill:#000000;stroke-width:0.792813;stroke-linecap:round;stroke-linejoin:round"
d="M 99.99982,19.920747 A 20,20 0 0 0 80,0 v 9.999905 a 10,10 0 0 1 9.999911,9.999912 h 9.999909 a 20,20 0 0 0 0,-0.0791 z" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1056"
width="5.0001798"
height="9.9999104"
x="124.99982"
y="0" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1058"
width="10.000138"
height="9.9999056"
x="69.999863"
y="0" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1060"
width="10.000031"
height="30.000183"
x="89.999908"
y="19.999817" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.265902"
id="rect1062"
width="15"
height="10"
x="109.99985"
y="59.999905" />
<path
sodipodi:type="star"
style="opacity:0.996;fill:#000000;stroke-width:0.829;stroke-linecap:round;stroke-linejoin:round"
id="path909-2-4"
sodipodi:sides="3"
sodipodi:cx="71.8955"
sodipodi:cy="79.111778"
sodipodi:r1="39.848263"
sodipodi:r2="19.924133"
sodipodi:arg1="0.51165873"
sodipodi:arg2="1.5588563"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 106.64054,98.622453 37.626242,99.446526 71.419721,39.266356 Z"
inkscape:transform-center-x="4.9775137"
inkscape:transform-center-y="0.01688725"
transform="matrix(0.00696336,-0.43462046,0.50129215,0.00603725,24.818614,165.75262)" />
<path
id="path943-8"
style="opacity:0.996;fill:#000000;stroke-width:0.792813;stroke-linecap:round;stroke-linejoin:round"
d="M 109.99982,149.9208 A 19.999999,19.999999 0 0 0 90.000014,130.00005 v 9.99991 a 10,10 0 0 1 9.9999,9.99991 h 9.999906 a 19.999999,19.999999 0 0 0 0,-0.0791 z" />
<path
id="rect926-2-8-7"
style="fill:#000000;fill-rule:evenodd;stroke-width:0.236261"
d="m 103.54248,199.99987 a 40.000288,40.000367 0 0 1 -8.183986,-9.99991 h -20.35845 v 9.99991 z" />
<path
id="path943-4-5"
style="opacity:0.996;fill:#000000;stroke-width:0.792813;stroke-linecap:round;stroke-linejoin:round"
d="m 100.00004,180.07912 a 20,20 0 0 0 19.99982,19.92075 v -9.99991 a 10,10 0 0 1 -9.99991,-9.99991 h -9.99991 a 20,20 0 0 0 0,0.0791 z" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1056-4"
width="5.0001798"
height="9.9999104"
x="-75.000053"
y="-199.99986"
transform="scale(-1)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1058-7"
width="10.000138"
height="9.9999056"
x="-129.99998"
y="-199.99986"
transform="scale(-1)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1060-9"
width="10.000031"
height="30.000183"
x="-109.99993"
y="-180.00005"
transform="scale(-1)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.265901"
id="rect1062-5"
width="15"
height="10"
x="-90.000023"
y="-139.99997"
transform="scale(-1)" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Capa 2"
style="display:inline">
<path
id="path1101"
style="opacity:0.996;fill:#000000;stroke-width:4.90719;stroke-linecap:round;stroke-linejoin:round"
d="M 264.56641,0 A 264.56693,264.56693 0 0 0 0,264.56641 H 75.589844 A 188.97638,188.97638 0 0 1 264.56641,75.589844 Z"
transform="scale(0.26458333)" />
<path
id="path1101-5"
style="opacity:0.996;fill:#000000;stroke-width:1.29836;stroke-linecap:round;stroke-linejoin:round"
d="m 0,130 a 70,70 0 0 0 69.999863,69.99986 V 180.00005 A 50.000001,50.000001 0 0 1 19.999813,130 Z" />
<path
id="path1101-1"
style="opacity:0.996;fill:#000000;stroke-width:1.29836;stroke-linecap:round;stroke-linejoin:round"
d="M 130,199.99986 A 70,70 0 0 0 199.99986,130 H 180.00005 A 50.000001,50.000001 0 0 1 130,180.00005 Z" />
<path
id="path1101-5-1"
style="opacity:0.996;fill:#000000;stroke-width:1.29836;stroke-linecap:round;stroke-linejoin:round"
d="M 199.99986,69.99986 A 70,70 0 0 0 130,0 v 19.99981 a 50.000001,50.000001 0 0 1 50.00005,50.00005 z" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1175"
width="19.999813"
height="60.000137"
x="0"
y="69.999863" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1177"
width="19.999811"
height="60.000141"
x="180.00005"
y="69.999863" />
<path
id="rect1179"
style="fill:#000000;fill-rule:evenodd;stroke-width:0.999999"
d="m 400.63086,0 a 132.28346,132.28346 0 0 1 49.4082,75.589844 h 41.29883 V 0 Z"
transform="scale(0.26458333)" />
<path
sodipodi:type="star"
style="opacity:0.996;fill:#000000;stroke-width:0.829;stroke-linecap:round;stroke-linejoin:round"
id="path1183"
sodipodi:sides="3"
sodipodi:cx="82.051743"
sodipodi:cy="49.177593"
sodipodi:r1="52.311821"
sodipodi:r2="26.15591"
sodipodi:arg1="0.5185124"
sodipodi:arg2="1.56571"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 127.48756,75.102736 36.882001,75.563594 81.785666,-3.1335511 Z"
inkscape:transform-center-x="-6.6535474"
inkscape:transform-center-y="-0.014772187"
transform="matrix(-0.00302595,0.66219101,-0.50950409,-0.00393276,168.65092,20.874244)" />
<path
id="path1185"
style="opacity:0.996;fill:#000000;stroke-width:0.857951;stroke-linecap:round;stroke-linejoin:round"
d="m 90,55 a 30,30 0 0 0 29.99972,30.000236 V 64.999905 A 10,10 0 0 1 110.00033,55 Z" />
<path
id="path1185-5"
style="opacity:0.996;fill:#000000;stroke-width:0.857951;stroke-linecap:round;stroke-linejoin:round"
d="M 109.99971,30.000237 A 30.000001,30.000001 0 0 0 80,0 v 20.00033 a 10,10 0 0 1 9.999387,9.999907 z" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1282"
width="10.000138"
height="20.00033"
x="69.999863"
y="0" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1284"
width="20.000942"
height="24.999762"
x="89.999382"
y="30.000237" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.259485"
id="rect1286"
width="15.7732"
height="20"
x="119.99972"
y="64.999901" />
<path
id="rect1179-8"
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
d="m 93.999606,199.99986 a 34.999999,34.999999 0 0 1 -13.07258,-19.99981 h -10.92699 v 19.99981 z" />
<path
sodipodi:type="star"
style="opacity:0.996;fill:#000000;stroke-width:0.829;stroke-linecap:round;stroke-linejoin:round"
id="path1183-6"
sodipodi:sides="3"
sodipodi:cx="82.051743"
sodipodi:cy="49.177593"
sodipodi:r1="52.311821"
sodipodi:r2="26.15591"
sodipodi:arg1="0.5185124"
sodipodi:arg2="1.56571"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 127.48756,75.102736 36.882001,75.563594 81.785666,-3.1335511 Z"
inkscape:transform-center-x="6.6535476"
inkscape:transform-center-y="0.014771914"
transform="matrix(0.00302595,-0.66219102,0.50950408,0.00393276,31.348936,179.12562)" />
<path
id="path1185-8"
style="opacity:0.996;fill:#000000;stroke-width:0.857951;stroke-linecap:round;stroke-linejoin:round"
d="M 109.99986,144.99986 A 30.000001,30.000001 0 0 0 80.000136,114.99963 v 20.00033 a 10,10 0 0 1 9.99939,9.9999 z" />
<path
id="path1185-5-3"
style="opacity:0.996;fill:#000000;stroke-width:0.857951;stroke-linecap:round;stroke-linejoin:round"
d="m 90.000146,169.99963 a 30.000001,30.000001 0 0 0 29.999714,30.00023 v -20.00033 a 10,10 0 0 1 -9.99939,-9.9999 z" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1282-5"
width="10.000138"
height="20.00033"
x="-130"
y="-199.99986"
transform="scale(-1)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.264583"
id="rect1284-1"
width="20.000944"
height="24.999762"
x="-110.00047"
y="-169.99962"
transform="scale(-1)" />
<rect
style="fill:#000000;fill-rule:evenodd;stroke-width:0.259485"
id="rect1286-5"
width="15.7732"
height="20"
x="-80.000145"
y="-134.99997"
transform="scale(-1)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

BIN
Artbook/AnPv1.xcf Executable file

Binary file not shown.

68
Artbook/images.svg Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 29 KiB

BIN
Artbook/images.xcf Executable file

Binary file not shown.

4
JSON/AnP.routes.json Normal file
View File

@ -0,0 +1,4 @@
[
"get:/ /Public",
"post:/ai/new_message ai@new_message"
]

87
JSON/AnP.settings.json Normal file
View File

@ -0,0 +1,87 @@
{
"AnP_start" : null,
"end_print_types" : ["UNKN", "EXCE", "ERRO"],
"root_projects_paths" : [],
"print_format" : "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}",
"exception_format" : " '[{line}]{file}({method})'{lines}\n\n{exception_message}",
"AnP_end" : null,
"AnP_SettingsManager_start" : null,
"default_settings_files" : "/JSON/AnP.settings.json",
"default_secrets_files" : "/JSON/AnP.secrets.json",
"AnP_SettingsManager_end" : null,
"AnP_I18NManager_start" : null,
"default_i18n_files" : [
"/JSON/I18N/AnP.i18n.english.json",
"/JSON/I18N/AnP.i18n.espanol.json",
"/JSON/I18N/AnP.i18n.galego.json",
"/JSON/I18N/AnP.i18n.nihongo.json",
"/JSON/I18N/AnP.i18n.russkiy.json"
],
"default_language" : "english",
"language" : "english",
"AnP_I18NManager_end" : null,
"AnP_PrintTypesManager_start" : null,
"default_print_types" : [
["unkn", "unknown"],
["info", "information"],
["warn", "warning"],
["erro", "error", "no", "wrong", "bad", "fail", "incorrect"],
[" ok ", "ok", "success", "good", "correct", "right", "yes"],
["exce", "exception", "traceback", "trace"],
["test", "debug", "comment", "log", "print"]
],
"AnP_PrintTypesManager_end" : null,
"AnP_TerminalManager_start" : null,
"AnP_TerminalManager_end" : null,
"AnP_ModelsManager_start" : null,
"AnP_ModelsManager_end" : null,
"AnP_ControllersManager_start" : null,
"default_controllers" : {
"ai" : "AIController"
},
"AnP_ControllersManager_end" : null,
"AnP_IndexesManager_start" : null,
"default_indexes" : [
["index.html", "index.htm", "index.w.md", "index.md"]
],
"AnP_IndexesManager_end" : null,
"AnP_RoutesManager_start" : null,
"default_routes_files" : "/JSON/AnP.routes.json",
"AnP_RoutesManager_end" : null,
"AnP_HTTPServer_start" : null,
"http_server_host" : "",
"http_server_port" : 18000,
"AnP_HTTPServer_end" : null,
"AnP_WebSocketServer_start" : null,
"web_socket_server_host" : "",
"web_socket_server_port" : 18765,
"AnP_WebSocketServer_end" : null,
"AnP_TitlesManager_start" : null,
"default_titles_files" : [
"/JSON/AnP.titles.json",
"/JSON/AnP.titles.secrets.json"
],
"AnP_TitlesManager_end" : null,
"AnP_AIModel_start" : null,
"titles_model" : "gemma3:1b",
"titles_temperature" : 0.0,
"titles_prompt_file" : "/MD/AnP.titles-prompt.md",
"responses_model" : "gemma3:1b",
"responses_temperature" : 7.0,
"response_with_titles_prompt_file" : "/MD/AnP.response-with-titles.md",
"AnP_AIModel_end" : null
}

View File

@ -0,0 +1,3 @@
{
"english" : {}
}

View File

@ -0,0 +1,47 @@
{
"espanol" : {
"AnP_start" : null,
"AnP_end" : null,
"AnP_SettingsManager_start" : null,
"AnP_SettingsManager_end" : null,
"AnP_I18NManager_start" : null,
"AnP_I18NManager_end" : null,
"AnP_PrintTypesManager_start" : null,
"AnP_PrintTypesManager_end" : null,
"AnP_TerminalManager_start" : null,
"terminal_manager_unknown_command" : "El comando '{command}' es desconocido.",
"terminal_manager_exception" : "Hubo una excepción al intentar procesar el comando '{command}'.",
"AnP_TerminalManager_end" : null,
"AnP_ModelsManager_start" : null,
"AnP_ModelsManager_end" : null,
"AnP_ControllersManager_start" : null,
"AnP_ControllersManager_end" : null,
"AnP_IndexesManager_start" : null,
"AnP_IndexesManager_end" : null,
"AnP_RoutesManager_start" : null,
"AnP_RoutesManager_end" : null,
"AnP_WebSocketServerDriver_start" : null,
"web_socket_server_client_close_exception" : "El Web Socket Servidor '{host}:{port}' ha cerrado la conexión con el cliente '{key}'.",
"web_socket_server_client_connected" : "El cliente '{key}' se ha conectado al Web Socket Servidor '{host}:{port}' desde '{client_host}:{client_port}'.",
"web_socket_server_client_exception" : "Excepción al intentar procesar un mensaje de recepción del cliente '{key}' en el Web Socket Servidor '{host}:{port}'.",
"web_socket_server_client_disconnected" : "El cliente '{key}' se ha desconectado del Web Socket Servidor '{host}:{port}'.",
"AnP_WebSocketServerDriver_end" : null,
"AnP_TitlesManager_start" : null,
"AnP_TitlesManager_end" : null,
"AnP_AIModel_start" : null,
"AnP_AIModel_end" : null
}
}

View File

@ -0,0 +1,3 @@
{
"galego" : {}
}

View File

@ -0,0 +1,3 @@
{
"nihongo" : {}
}

View File

@ -0,0 +1,3 @@
{
"russkiy" : {}
}

View File

@ -0,0 +1,191 @@
"use strict";
import {FilesDriver} from "../Drivers/FilesDriver.ecma.js";
import {PrintTypesManager} from "../Managers/PrintTypesManager.ecma.js";
import {SettingsManager} from "../Managers/SettingsManager.ecma.js";
import {I18NManager} from "../Managers/I18NManager.ecma.js";
import {ThreadsManager} from "../Managers/ThreadsManager.ecma.js";
import {UniqueKeysManager} from "../Managers/UniqueKeysManager.ecma.js";
import {SessionsManager} from "../Managers/SessionsManager.ecma.js";
import {ModelsManager} from "../Managers/ModelsManager.ecma.js";
import {ViewsManager} from "../Managers/ViewsManager.ecma.js";
import {RoutesManager} from "../Managers/RoutesManager.ecma.js";
import {Components} from "./Components.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @class AnP
* @constructor
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @param {?simple_callback} [callback = null]
* @returns {void}
* @access private
* @static
*/
export const AnP = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs AnP
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @param {?simple_callback} [callback = null]
* @returns {void}
* @access private
* @static
*/
const AnP = function(inputs = null, callback = null){
/** @type {AnP} */
const self = this;
/** @type {boolean} */
let started = false;
/** @type {FilesDriver} */
this.files = new FilesDriver(self);
/** @type {PrintTypesManager} */
this.print_types = new PrintTypesManager(self);
/** @type {SettingsManager} */
this.settings = new SettingsManager(self, inputs);
/** @type {I18NManager} */
this.i18n = new I18NManager(self);
/** @type {ThreadsManager} */
this.threads = new ThreadsManager(self);
/** @type {UniqueKeysManager} */
this.unique_keys = new UniqueKeysManager(self);
/** @type {SessionsManager} */
this.sessions = new SessionsManager(self);
/** @type {ModelsManager} */
this.models = new ModelsManager(self);
/** @type {Components} */
this.components = new Components(self);
/** @type {ViewsManager} */
this.views = new ViewsManager(self);
/** @type {RoutesManager} */
this.routes = new RoutesManager(self);
/**
* @returns {void}
* @access private
*/
const constructor = () => {
self.settings.get("autostart", null, true) && self.start(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array([
"files", "settings", "print_types", "i18n", "threads", "models", "views", "routes"
], (key, next) => {
self[key].update(next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.execute_array([
"files", "settings", "print_types", "i18n", "threads", "models", "views", "routes"
], (key, next) => {
self[key].reset(next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(ok => {
if(ok !== false && self.settings.get("build_base_gui")){
Common.preload(self.settings.get("position"), (position, asynchronous, ok) => {
if(position){
Common.HTML(position, self.components.base.build());
end(true);
}else
end(false);
});
}else
end(ok);
});
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {!string} type
* @param {!(string|Array.<string>)} message
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @param {!number} [i = 0]
* @return {void}
* @access public
*/
this.print = (type, message, inputs = null, i = 0) => {};
/**
* @param {!Error} exception
* @param {!(string|Array.<string>)} message
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @param {!number} [i = 0]
* @return {void}
* @access public
*/
this.exception = (exception, message, inputs = null, i = 0) => {};
constructor();
};
return AnP;
})();

View File

@ -0,0 +1,357 @@
"use strict";
import {BaseComponent} from "../Components/BaseComponent.ecma.js";
import {FormsComponent} from "../Components/FormsComponent.ecma.js";
import {DatesComponent} from "../Components/DatesComponent.ecma.js";
import {SelectsComponent} from "../Components/SelectsComponent.ecma.js";
import {TablesComponent} from "../Components/TablesComponent.ecma.js";
import {SessionMiniComponent} from "../Components/SessionMiniComponent.ecma.js";
import {LicensesComponent} from "../Components/LicensesComponent.ecma.js";
import {I18NComponent} from "../Components/I18NComponent.ecma.js";
import { AIChatComponent } from "../Components/AIChatComponent.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
import {
Span, Img, Button, Label, Input, Textarea, Div
} from "../Utils/HTMLDSL.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class Components
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const Components = (function(){
/**
* @callback event_callback
* @param {!HTMLElement} element
* @param {!Event} event
* @return {any|null|void}
*/
/**
* @constructs Components
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const Components = function(anp){
/** @type {Components} */
const self = this;
/** @type {BaseComponent} */
this.base = new BaseComponent(anp);
/** @type {FormsComponent} */
this.forms = new FormsComponent(anp);
/** @type {DatesComponent} */
this.dates = new DatesComponent(anp);
/** @type {SelectsComponent} */
this.selects = new SelectsComponent(anp);
/** @type {TablesComponent} */
this.tables = new TablesComponent(anp);
/** @type {SessionMiniComponent} */
this.session_mini = new SessionMiniComponent(anp);
/** @type {LicensesComponent} */
this.licenses = new LicensesComponent(anp);
/** @type {I18NComponent} */
this.i18n_selector = new I18NComponent(anp);
/** @type {AIChatComponent} */
this.aichat = new AIChatComponent(anp);
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {!(string|Array.<string>)} keys
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @returns {Object.<string, any>}
* @access public
*/
this.set_attributes = (keys, inputs) => Common.get_array(keys).reduce((attributes, key) => {
/** @type {any|null} */
const value = Common.get_value(key, inputs, null);
value !== null && (attributes[Common.get_array(key)[0]] = value);
return attributes;
}, {});
/**
*
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @returns {Array.<any|None>}
*/
this.image = (inputs = null) => {
/** @type {string|null} */
const i18n = Common.get_value("i18n", inputs, null),
/** @type {string|null} */
alternative = Common.get_value(["alt", "alternative"], inputs, null),
/** @type {string|null} */
text = i18n ? anp.i18n.get([alternative, i18n], inputs) : alternative;
/** @type {Array.<string>|string} */
let sources = Common.get_value(["src", "source", "sources"], inputs, null);
return Span({
class : "image",
data_i : 0,
data_data : Common.base64_encode(Check.is_array(sources) ? sources : sources = [sources])
}, [
Img({
src : sources[0],
on_load : (item, event) => {
item.parentNode.querySelector("span").style.backgroundImage = `url(${item.getAttribute("src")})`;
},
on_error : (item, event) => {
const i = Number(item.parentNode.getAttribute("data_i")) + 1;
item.setAttribute("src", Common.json_decode(Common.base64_decode(item.parentNode.getAttribute("data-data")))[i]);
item.parentNode.setAttribute("data_i", i);
},
...(i18n ? {data_i18n : i18n, data_i18n_without : true, alt : text} : text ? {alt : text} : {})
}),
Span()
]);
};
this.i18n = (i18n, tag = "span", variables = null) => [tag, {
data_i18n : i18n,
...(variables ? {data_i18n_variables : Common.data_encode(variables)} : {})
}, anp.i18n.get(i18n, variables)];
this.icon = (icon, tag = "span") => [tag, {data_icon : icon}];
this.button = (name, action, inputs = null) => {
const text = anp.i18n.get(name, (
Check.is_bool(inputs) ? {toogled : inputs} :
Check.is_string(inputs) ? {type : inputs} :
inputs)),
has_action = Check.is_function(action),
type = Check.is_string(action) ? action : Common.get_value("type", inputs, "button"),
toggled = Common.get_value("toggled", inputs, null);
has_action || (action = null);
return Button({
type : type,
data_i18n : name,
data_i18n_without : true,
title : text,
...(
toggled !== null ? {
data_toggled : toggled,
on_click : (button, event) => {
button.setAttribute("data_toggled", button.getAttribute("data_toggled") != "true");
Common.execute(action, (button, event));
}
} :
has_action ? {on_click : action} :
{}),
}, [
self.icon(name),
self.i18n(name)
]);
};
this.checkbox = (name, inputs = null) => Label({
class : "checkbox",
data_i18n : name,
data_i18n_without : true,
title : anp.i18n.get(name),
}, [
Input({
type : "checkbox",
name : name,
checked : Common.get_value("checked", inputs, false),
...self.set_attributes([
["on_change", "onchange"],
["id", "identifier"]
], inputs)
}),
self.icon("checkbox"),
self.i18n(name)
]);
this.radio = (name, inputs = null) => {
const set = Common.get_value("set", inputs);
return Label({
class : "radio radio-button",
data_i18n : name,
data_i18n_without : true,
title : anp.i18n.get(name),
}, [
Input({
type : "radio",
name : set ? set + "[]" : name,
value : name,
checked : Common.get_value("checked", inputs, false),
...self.set_attributes([
["on_change", "onchange"],
["id", "identifier"]
], inputs)
}),
self.icon("radio"),
self.i18n(name)
]);
};
this.text = (name, inputs = null) => {
const text = anp.i18n.get(name),
minimum_length = Common.get_value("minimum_length", inputs, null),
maximum_length = Common.get_value("maximum_length", inputs, null);
return Span({
class : "input input-text",
data_i18n : name,
data_i18n_without : true,
title : text
}, [
Common.get_value("multiline", inputs, false) ? Textarea({
name : name,
data_i18n : name,
data_i18n_without : true,
placeholder : text + "...",
...self.set_attributes([
["id", "identifier"],
["maxlength", "maximum_length"],
"pattern",
"value"
], inputs)
}) : Input({
type : "text",
name : name,
data_i18n : name,
data_i18n_without : true,
placeholder : text + "...",
...self.set_attributes([
["id", "identifier"],
["maxlength", "maximum_length"],
"pattern",
"value"
], inputs)
}),
Span({class : "minimum", data_minimum : minimum_length}, "" + minimum_length),
Span({class : "length"}, "" + Common.get_value("value", inputs, "").length),
Span({class : "maximum", data_maximum : maximum_length}, "" + maximum_length)
]);
};
this.password = (name, inputs = null) => {
const text = anp.i18n.get(name),
minimum_length = Common.get_value("minimum_length", inputs, 0),
maximum_length = Common.get_value("maximum_length", inputs, 0);
return Span({
data_i18n : name,
data_i18n_without : true,
title : text
}, [
Input({
type : "password",
name : name,
data_i18n : name,
data_i18n_without : true,
placeholder : text + "...",
...self.set_attributes([
["id", "identifier"],
["maxlength", "maximum_length"],
"pattern",
"value"
], inputs)
}),
Span({class : "minimum", data_minimum : minimum_length}, "" + minimum_length),
Span({class : "length"}, "" + Common.get_value("value", inputs, "").length),
Span({class : "maximum", data_maximum : maximum_length}, "" + maximum_length)
]);
};
this.email = (name, inputs = null) => {
const text = anp.i18n.get(name);
return Span({
data_i18n : name,
data_i18n_without : true,
title : text
}, [
Input({
type : "email",
name : name,
data_i18n : name,
data_i18n_without : true,
placeholder : text + "...",
pattern : "[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$"
})
]);
};
this.number = (name, inputs = null) => {
const text = anp.i18n.get(name),
minimum = Common.get_value("minimum", inputs, 0),
maximum = Common.get_value("maximum", inputs, 0),
value = Common.get_value("value", inputs, 0);
return Span({
data_i18n : name,
data_i18n_without : true,
title : text
}, [
Input({
type : "number",
name : name,
data_i18n : name,
data_i18n_without : true,
placeholder : text + "...",
...self.set_attributes([
["id", "identifier"],
["min", "minimum"],
["max", "maximum"],
"step",
"value"
], inputs)
}),
Span({class : "minimum", data_minimum : minimum}, "" + minimum),
Span({class : "value"}, "" + value),
Span({class : "maximum", data_maximum : maximum}, "" + maximum)
]);
};
/**
* @param {!Array.<Array.<[string, string|event_callback, Object.<string, any|null>|Array.<any|null>]>>} buttons
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @returns {Array.<any|null>}
*/
this.buttons = (buttons, inputs = null) => Div({
class : ["buttons"].concat(Common.get_array(Common.get_value("class", inputs, []))).join(" ").trim(),
...Common.get_dictionary(inputs, false, ["class"])
}, buttons.map(([name, action, inputs]) => (
self.button(name, action, inputs)
)));
constructor();
};
return Components;
})();

View File

@ -0,0 +1,97 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @class Event
* @constructor
* @param {boolean} [once = false]
* @param {boolean} [autoexecute = false]
* @returns {void}
* @access public
* @static
*/
export const Event = (function(){
/**
* @callback event_callback
* @param {...(any|null)} parameters
* @return {void}
*/
/**
* @constructs Event
* @param {boolean} [once = false]
* @param {boolean} [autoexecute = false]
* @returns {void}
* @access public
* @static
*/
const Event = function(once = false, autoexecute = false){
/** @type {Event} */
const self = this,
/** @type {Object.<number, event_callback>} */
events = {},
/** @type {number} */
id_i = 0;
/** @type {boolean} */
this.once = once;
/** @type {boolean} */
this.autoexecute = autoexecute;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {...(any|null)} parameters
* @returns {Array.<any|null>}
* @access public
*/
this.execute = (...parameters) => [...Object.entries(events)].map(([id, callback]) => {
/** @type {any|null} */
const response = Common.execute(callback, ...parameters);
if(self.once)
delete events[id];
return response;
});
/**
* @param {!event_callback} callback
* @returns {number|null}
* @access public
*/
this.add = callback => {
if(Check.is_function(callback)){
events[++ id_i] = callback;
return id_i;
};
return null;
};
/**
* @param {!number} id
* @returns {boolean}
* @access public
*/
this.remove = id => {
if(events[id]){
delete events[id];
return true;
};
return false;
};
};
return Event;
})();

View File

@ -0,0 +1,88 @@
"use strict";
import {Fieldset, Section, Form, Div} from "../Utils/HTMLDSL.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class AIChatComponent
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const AIChatComponent = (function(){
/**
* @constructs AIChatComponent
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const AIChatComponent = function(anp){
/** @type {AIChatComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
this.build = (inputs = null) => {
const name = Common.get_value("name", inputs, "aichat");
return Fieldset({class : "aichat"}, [
anp.components.i18n(name, "legend"),
Section({class : "messages"}),
Form({
method : "post",
action : "#",
on_submit : send,
on_key_down : check_keys
}, [
anp.components.text("message", {
multiline : true
}),
anp.components.button("send", "submit")
])
]);
};
const send = (item, event) => {
const text_box = item.querySelector("[name=message]"),
text = text_box.value.trim();
event.preventDefault();
if(text){
Common.HTML(".aichat .messages", Fieldset({
class : "message",
data_type : "user"
}, [
anp.components.i18n("user", "legend"),
Div({class : "content"}, text)
]));
text_box.value = "";
};
return false;
};
const check_keys = (item, event) => {
event.key == "Enter" && !event.shiftKey && send(item, event);
};
constructor();
};
return AIChatComponent;
})();

View File

@ -0,0 +1,279 @@
"use strict";
import {RE} from "../Utils/Patterns.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
import {
Div, Span, A, Img, Header, Footer, Main, H1, Nav, UL, LI
} from "../Utils/HTMLDSL.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class BaseComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const BaseComponent = (function(){
/**
* @constructs BaseComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const BaseComponent = function(anp){
/** @type {BaseComponent} */
const self = this,
/** @type {Object.<number, Object.<string, number>>} */
caches = {};
/** @type {integer|null} */
let thread = null,
/** @type {Array.<number>} */
zooms = [.25, .5, .75, 1.0, 1.5, 2.0];
/**
* @returns {void}
* @access private
*/
const constructor = () => {
thread = anp.threads.add(thread_method, {
autostart : true,
bucle : true
});
};
/**
* @returns {void}
* @access private
*/
const thread_method = () => {
Object.entries(caches).forEach(([i, cache]) => {
/** @type {HTMLDivElement} */
const base = document.querySelector(".anp[data-i='" + i + "']"),
date = Date.now();
if(!base){
delete caches[i];
return;
};
/** @type {number} */
const cells = Number(base.getAttribute("data-cells")),
/** @type {number} */
zoom = Number(base.getAttribute("data-zoom"));
if(
cache.x != base.offsetWidth ||
cache.y != base.offsetHeight ||
cache.cells != cells ||
cache.zoom != zoom ||
false){
cache.x = base.offsetWidth;
cache.y = base.offsetHeight;
cache.cells = cells;
cache.zoom = zoom;
base.style.fontSize = ((cache.x < cache.y ? cache.x : cache.y) / (cells / zoom)) + "px";
};
if(date - cache.last_time > 2000){
/** @type {string} */
const gui_mode = Check.is_dark_mode() ? "dark" : "light",
/** @type {boolean} */
is_mobile = Check.is_mobile();
cache.last_time = date;
if(cache.gui_mode != gui_mode || cache.mobile != is_mobile){
cache.gui_mode = gui_mode;
cache.mobile = is_mobile;
base.setAttribute("data-gui-mode", gui_mode);
base.setAttribute("data-is-mobile", is_mobile);
};
};
});
};
/**
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @return {Array.<any|null>}
* @access public
*/
this.build = (inputs = null) => {
/** @type {string} */
const name = anp.settings.get(["application_name", "name"], inputs, "AnP"),
/** @type {string} */
link = anp.settings.get(["application_link", "link"], inputs, "https://anp.k3y.pw/"),
/** @type {string} */
git = anp.settings.get(["application_git", "git"], inputs, "https://git.k3y.pw/KyMAN/AnP/"),
/** @type {string} */
logo = anp.settings.get(["application_logo", "logo"], inputs, "images/logo.webp"),
/** @type {string} */
id = anp.unique_keys.create(),
/** @type {string} */
gui_mode = Check.is_dark_mode() ? "dark" : "light",
/** @type {boolean} */
is_mobile = Check.is_mobile();
/** @type {number} */
let i;
while(caches[i = Math.random() * (1 << 28) | 0]);
caches[i] = {
x : 0,
y : 0,
cells : anp.settings.get(["application_cells", "cells"], inputs, 40),
zoom : anp.settings.get(["application_zoom", "zoom"], inputs, 1.0),
gui_mode : gui_mode,
mobile : is_mobile,
last_time : Date.now()
};
return Div({
id : id,
class : Common.unique(["anp", id].concat(anp.settings.get([
"application_class", "class"
], inputs, "").split(RE.WHITE_SPACES))).join(" ").trim(),
data_hash : id,
data_i : i,
data_cells : caches[i].cells,
data_zoom : caches[i].zoom,
data_forced_gui_mode : anp.settings.get(["application_gui_mode", "gui_mode"], inputs, "default"), // default, light, dark
data_gui_mode : gui_mode, // default, light, dark
data_is_mobile : is_mobile,
data_name : name,
data_link : link,
data_git : git,
data_logo : logo
}, [
Header(null, [
H1({title : name}, [
A({href : link, target : "_blank"}, [
anp.components.image({sources : [logo], alt : name}),
Span({class : "text"}, name)
])
]),
Nav({class : "top-menu"}, [
UL(null, anp.settings.get("main_menu", inputs, [
["home", "#"],
["git", git, "_blank"]
]).map(([name, link, target]) => LI({
data_i18n : name,
data_i18n_without : true,
title : anp.i18n.get(name, inputs)
}, [
A({
href : link,
target : target || "_self"
}, [
anp.components.icon(name),
anp.components.i18n(name)
])
])))
]),
anp.components.session_mini.build()
]),
Main(null, [
anp.components.aichat.build(inputs)
]),
Footer(null, [
anp.components.buttons([
["zoom", change_zoom],
["reset_zoom", reset_zoom],
["gui_mode", change_gui_mode]
], {class : "gui-controls"}),
anp.components.licenses.build(anp.settings.get(["application_licenses", "licenses"], inputs, {
copyright : [[2019, 2027], "KyMAN"],
cc_by_nc_sa_4 : []
})),
anp.components.i18n_selector.build()
]),
Div({class : "preloader"})
]);
};
/**
* @param {!HTMLElement} item
* @returns {HTMLDivElement|null}
* @access public
*/
this.get_from = item => {
if(item)
while(
!item.classList.contains("anp") &&
(item = item.parentElement)
);
return item;
};
/**
* @param {!HTMLElement} item
* @param {!Event} event
* @return {void}
* @access private
*/
const change_zoom = (item, event) => {
/** @type {HTMLDivElement} */
const base = self.get_from(item),
/** @type {number} */
i = zooms.indexOf(Number(base.getAttribute("data-zoom")));
if(isNaN(i))
base.setAttribute("data-zoom", 1.0);
else
base.setAttribute("data-zoom", zooms[(i + 1) % zooms.length]);
};
/**
* @param {!HTMLElement} item
* @param {!Event} event
* @return {void}
* @access private
*/
const reset_zoom = (item, event) => {
self.get_from(item).setAttribute("data-zoom", 1.0);
};
/**
* @param {!HTMLElement} item
* @param {!Event} event
* @return {void}
* @access private
*/
const change_gui_mode = (item, event) => {
/** @type {HTMLDivElement} */
const base = self.get_from(item);
base.setAttribute("data-forced-gui-mode", {
default : "light",
light : "dark",
dark : "default"
}[base.getAttribute("data-forced-gui-mode")]);
};
constructor();
};
return BaseComponent;
})();

View File

@ -0,0 +1,49 @@
"use strict";
/**
* @class DatesComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
export const DatesComponent = (function(){
/**
* @constructs DatesComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const DatesComponent = function(anp){
/** @type {DatesComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
setTimeout(() => {
anp.components.dates = self;
anp.components.date = self.build;
}, 0);
};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @access public
*/
this.build = inputs => {};
constructor();
};
return DatesComponent;
})();

View File

@ -0,0 +1,152 @@
"use strict";
import {Fieldset, Div, Form, UL} from "../Utils/HTMLDSL.ecma.js";
/**
* @class FormsComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
export const FormsComponent = (function(){
/**
* @callback form_submit_callback
* @param {!HTMLElement} form
* @param {!Event} event
* @return {any|null|void}
*/
/**
* @constructs FormsComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const FormsComponent = function(anp){
/** @type {FormsComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
setTimeout(() => {
anp.components.forms = self;
anp.components.form = self.build;
}, 0);
};
/**
* @param {string} name
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @access public
*/
this.build = (name, inputs) => {
/** @type {form_submit_callback|null} */
const submit = Common.get_value("submit", inputs, null);
return Form({
data_name : name,
method : Common.get_value("method", inputs, "post"),
action : Common.get_value("action", inputs, "#"),
...(submit ? {on_submit : submit} : {})
}, [
Fieldset({class : "form"}, [
anp.components.i18n(name, "legend"),
anp.components.i18n(name + "_description", "p"),
Div({class : "form-fields"}, Common.get_value("structure", inputs, []).map(([type, name, ...inputs], i) => {
/** @type {string} */
let id = anp.unique_keys.create(true),
/** @type {number} */
l = inputs.length - 1;
if(!Check.is_dictionary(inputs[l])){
inputs.push({});
l ++;
};
inputs[l].id = id;
return Div({
data_field : name,
data_i : i
}, [
Label({
for : id,
data_i18n : name,
data_i18n_without : true,
title : anp.components.i18n(name, "label")
}, [
anp.components.i18n(name),
anp.components.i18n(name + "_description"),
]),
Span({class : "value"}, [
anp.components[type](name, ...inputs)
]),
UL({class : "errors"})
]);
})),
UL({class : "global-errors"}),
Div({class : "buttons"}, Common.get_value(["actions", "buttons"], inputs, []).concat(
anp.components.button(Common.get_value("submit_reset", inputs, "reset"), "reset"),
submit ? anp.components.button(Common.get_value("submit_name", inputs, "submit"), "submit") : null
))
])
]);
};
this.get = item => {
if(item)
while(item.tagName.toLowerCase() != "form" && (item = item.parentElement));
return item;
};
this.get_values = form => [...self.get(form).querySelectorAll("[name]")].reduce((values, field) => {
let name = field.getAttribute("name");
const is_array = self.is_array(field),
tag = field.tagName.toLowerCase(),
type = field.getAttribute("type").toLowerCase().trim();
if(is_array){
(values[name = name.slice(0, -2)] = values[name] || []).push(self.get_value(field));
}else
values[name] = self.get_value(field);
return values;
}, {});
this.is_array = input => input.getAttribute("name").endsWith("[]");
this.get_value = input => {
switch(input.tagName.toLowerCase()){
case "select":
return input.multiple ? [...input.options].filter(option => option.selected).map(option => option.value) : input.value;
};
switch(input.getAttribute("type")){
case "checkbox":
case "radio":
return self.is_array(input) ? input.checked ? input.value : null : input.checked;
case "number":
return parseFloat(input.value) || 0;
};
return input.value;
};
constructor();
};
return FormsComponent;
})();

View File

@ -0,0 +1,83 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Nav, Span, Img, UL, LI} from "../Utils/HTMLDSL.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @constructs I18NComponent
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const I18NComponent = (function(){
/**
* @constructs I18NComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const I18NComponent = function(anp){
/** @type {I18NComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @returns {Array.<any|null>}
* @access public
*/
this.build = () => Nav({class : "i18n-selector"}, [
UL(null, anp.settings.get("i18n_selector").map(([name, text, flag]) => LI({
data_language : name,
data_selected : anp.i18n.is_language_selected(name),
on_click : change,
data_role : "link",
title : text
}, [
Img({src : flag, alt : text}),
Span(null, text)
])))
]);
/**
* @param {!HTMLElement} item
* @param {!Event} event
* @return {void}
* @access private
*/
const change = (item, event) => {
if(anp.i18n.change(item.getAttribute("data-language"))){
item.parentNode.childNodes.forEach(option => {
option.setAttribute("data-selected", option === item ? "true" : "false");
});
anp.components.base.get_from(item).querySelectorAll("[data-i18n]").forEach(element => {
/** @type {string} */
const text = anp.i18n.get(element.getAttribute("data-i18n"), Common.data_decode(element.getAttribute("data-i18n-variables")));
element.getAttribute("data-i18n-without") != "true" && (element.innerText = text);
element.hasAttribute("title") && (element.setAttribute("title", text));
element.hasAttribute("placeholder") && (element.setAttribute("placeholder", text + "..."));
element.hasAttribute("alt") && (element.setAttribute("alt", text));
});
};
};
constructor();
};
return I18NComponent;
})();

View File

@ -0,0 +1,81 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Div, A} from "../Utils/HTMLDSL.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @constructs LicensesComponent
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const LicensesComponent = (function(){
/**
* @constructs LicensesComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const LicensesComponent = function(anp){
/** @type {LicensesComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {!Object.<string, any|null>} licenses
* @returns {Array.<any|null>}
* @access public
*/
this.build = licenses => Div({
class : "licenses",
}, Object.entries(licenses).map(([name, inputs]) => (
self[name] ? self[name](...Common.get_array(inputs)) :
null)));
/**
* @param {!(number|[number, number])} years
* @param {!(string|Array.<string>)} authors
* @returns {Array.<any|null>}
* @access public
*/
this.copyright = (years, authors) => anp.components.i18n("copyright", "span", {
authors : Common.get_array(authors).join(", "),
years : Common.get_array(years).join("-")
});
/**
* @returns {Array.<any|null>}
* @access public
*/
this.cc_by_nc_sa_4 = () => A({
href : anp.settings.get("cc_by_nc_sa_4_link", null, "https://creativecommons.org/licenses/by-nc-sa/4.0/"),
target : "_blank",
data_i18n : "cc_by_nc_sa_4",
data_i18n_without : true,
title : anp.i18n.get("cc_by_nc_sa_4")
}, [
anp.components.i18n("cc_by_nc_sa_4"),
anp.components.image({
i18n : "cc_by_nc_sa_4",
sources : [anp.settings.get("cc_by_nc_sa_4_icon", null, "https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png")],
})
])
constructor();
};
return LicensesComponent;
})();

View File

@ -0,0 +1,49 @@
"use strict";
/**
* @class SelectsComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
export const SelectsComponent = (function(){
/**
* @constructs SelectsComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const SelectsComponent = function(anp){
/** @type {SelectsComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
setTimeout(() => {
anp.components.dates = self;
anp.components.date = self.build;
}, 0);
};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @access public
*/
this.build = inputs => {};
constructor();
};
return SelectsComponent;
})();

View File

@ -0,0 +1,79 @@
"use strict";
import {Div, UL, LI, Span, Nav, A} from "../Utils/HTMLDSL.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class SessionMiniComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
export const SessionMiniComponent = (function(){
/**
* @constructs SessionMiniComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const SessionMiniComponent = function(anp){
/** @type {SessionMiniComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @returns {Array.<any|null>}
* @access public
*/
this.build = () => Div({
class : "sessions-mini",
data_status : "unlogged"
}, [
anp.components.image({}),
UL({class : "info"}, Object.entries({
user : "Guest",
ip : "::1"
}).map(([field, _default]) => LI({
class : field,
data_i18n : field,
data_i18n_without : true,
title : anp.i18n.get(field),
}, [
anp.components.icon(field),
anp.components.i18n(field),
Span({class : "value"}, _default)
]))),
Nav({class : "actions"}, [
UL(null, ["login", "register", "logout"].map(action => LI({class : action}, [
A({
href : "#/" + action,
data_i18n : action,
data_i18n_without : true,
title : anp.i18n.get(action)
}, [
anp.components.icon(action),
anp.components.i18n(action)
])
])))
])
]);
constructor();
};
return SessionMiniComponent;
})();

View File

@ -0,0 +1,49 @@
"use strict";
/**
* @class TablesComponent
* @constructor
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
export const TablesComponent = (function(){
/**
* @constructs TablesComponent
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const TablesComponent = function(anp){
/** @type {TablesComponent} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
setTimeout(() => {
anp.components.tables = self;
anp.components.table = self.build;
}, 0);
};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {Array.<any|null>}
* @access public
*/
this.build = inputs => {};
constructor();
};
return TablesComponent;
})();

View File

@ -0,0 +1,39 @@
"use strict";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class AIChat
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const AIChat = (function(){
/**
* @constructs AIChat
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const AIChat = function(anp){
/** @type {AIChat} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
constructor();
};
return AIChat;
})();

View File

@ -0,0 +1,45 @@
"use strict";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class SessionsController
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const SessionsController = (function(){
/**
* @constructs SessionsController
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const SessionsController = function(anp){
/** @type {SessionsController} */
const self = this;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
this.login = () => {};
this.logout = () => {};
this.register = () => {};
constructor();
};
return SessionsController;
})();

View File

@ -0,0 +1,310 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class FilesDriver
* @constructor
* @param {!AnP} anp
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @returns {void}
* @access private
* @static
*/
export const FilesDriver = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @callback ok_callback
* @param {!boolean} ok
* @return {void}
*/
/**
* @callback load_callback
* @param {?string} content
* @param {!boolean} ok
* @return {void}
*/
/**
* @callback load_json_callback
* @param {!Array.<Object.<string, any|null>|Array.<any|null>>} results
* @return {void}
*/
/**
* @constructs FilesDriver
* @param {!AnP} anp
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @returns {void}
* @access private
* @static
*/
const FilesDriver = function(anp, inputs = null){
/** @type {FilesDriver} */
const self = this;
/** @type {Array.<string>} */
let default_root_urls = [""],
/** @type {number} */
default_timeout = 2000,
/** @type {boolean} */
default_asynchronous = true,
/** @type {string} */
default_method = "get",
/** @type {boolean} */
started = false;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
default_timeout = anp.settings.get(["files_driver_timeout", "timeout"], inputs, default_timeout);
default_asynchronous = anp.settings.get(["files_driver_asynchronous", "asynchronous"], inputs, default_asynchronous);
default_method = anp.settings.get(["files_driver_method", "method"], inputs, default_method);
Common.execute(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
default_root_urls = [""];
default_timeout = 2000;
default_asynchronous = true;
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {!string} method
* @param {!string} url
* @param {!boolean} asynchronous
* @param {!number} timeout
* @param {?load_callback} [callback = null]
* @param {!Array.<string>} root_urls
* @param {!number} [i = 0]
* @param {!Array.<string>} [root_urls_done = []]
* @return {void}
* @access public
*/
const load_url_route = (method, url, asynchronous, timeout, callback, root_urls, i = 0, root_urls_done = []) => {
if(i == root_urls.length){
Common.execute(callback, null, false);
return;
};
/** @type {simple_callback} */
const next = () => {
load_url_route(method, url, asynchronous, timeout, callback, root_urls, i + 1, root_urls_done.concat(root_urls[i]));
};
if(root_urls_done.includes(root_urls[i])){
next();
return;
};
/** @type {boolean} */
let ended = false;
/** @type {XMLHttpRequest} */
const ajax = new XMLHttpRequest(),
/** @type {ok_callback} */
end = (ok = false) => {
if(ended)
return;
ended = true;
if(ok)
Common.execute(callback, ajax.responseText, true);
else
next();
},
/** @type {number} */
date = Date.now();
ajax.open(method, root_urls[i] + url, asynchronous);
ajax.timeout = timeout;
ajax.onreadystatechange = () => {
if(ended)
return;
if(ajax.readyState == 4)
end((ajax.status >= 200 && ajax.status < 300) || [301, 302, 304].includes(ajax.status));
else if(Date.now() - date >= timeout)
end(false);
};
ajax.send(null);
ajax.onload = end;
ajax.onerror = end;
ajax.ontimeout = end;
};
/**
* @param {!string} url
* @param {?load_callback} [callback = null]
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @return {void}
* @access public
*/
this.load = (url, callback, inputs = null) => {
load_url_route(
Common.get_value(["files_driver_method", "method"], inputs, "get").toLowerCase(),
url,
Common.get_value(["files_driver_asynchronous", "asynchronous"], inputs, default_asynchronous),
Common.get_value(["files_driver_timeout", "timeout"], inputs, default_timeout),
callback,
Common.get_value(["files_driver_root_urls", "root_urls"], inputs, []).concat(default_root_urls)
);
};
/**
* @param {?any} data
* @param {!load_json_callback} callback
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @return {void}
* @access public
*/
this.load_json = (data, callback, inputs = null) => {
if(Check.is_bool(inputs))
inputs = {only_dictionaries : inputs};
/** @type {boolean} */
const only_dictionaries = Common.get_value([
"files_driver_load_json_only_dictionaries",
"load_json_only_dictionaries",
"only_dictionaries"
], Check.is_bool(inputs) ? inputs = {
only_dictionaries : inputs
} : inputs, false),
/** @type {Array.<Object.<string, any|null>|Array.<any|null>>} */
results = [],
/** @type {simple_callback} */
end = () => {
Common.execute(callback, results);
};
if(Check.is_dictionary(data)){
results.push(data);
end();
}else if(Check.is_array(data)){
if(only_dictionaries){
/** @type {number} */
const l = data.length;
/** @type {number} */
let loaded = 0;
for(let item of data)
self.load_json(item, subresults => {
results.push(...subresults);
++ loaded == l && end();
}, inputs);
}else{
results.push(data);
end();
};
}else if(Check.is_string(data)){
/** @type {Object.<string, any|null>|Array.<any|null>|null} */
let json;
if(Check.is_json(data, false) && (json = JSON.parse(data)) !== null)
self.load_json(json, subresults => {
results.push(...subresults);
end();
}, inputs);
else
self.load(data, (content, ok) => {
self.load_json(content, subresults => {
results.push(...subresults);
end();
}, inputs);
}, inputs);
}else
end();
};
constructor();
};
return FilesDriver;
})();

View File

@ -0,0 +1,18 @@
"use strict";
export const WebSocketsDriver = (function(){
const WebSocketsDriver = function(anp){
const self = this,
clients = {};
let client_i = 0;
const constructor = () => {};
constructor();
};
return WebSocketsDriver;
})();

View File

@ -0,0 +1,157 @@
"use strict";
import {Check} from "../Utils/Checks.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class ControllersManager
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const ControllersManager = (function(){
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @callback action_callback
* @param {...(any|null)} parameters
* @return {void}
*/
/**
* @constructs ControllersManager
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const ControllersManager = function(anp){
/** @type {ControllersManager} */
const self = this,
/** @type {Object.<string, Object.<string, action_callback>>} */
controllers = {};
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.clear_dictionary(controllers);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(end);
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
*
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?default_callback} [callback = null]
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
Object.entries(data).forEach(([key, Controller]) => {
if(!Controller || (!overwrite && controllers[key]))
return;
if(Check.is_function(Controller))
controllers[key] = new Controller(anp);
else if(Check.is_object(Controller))
controllers[key] = Controller;
else if(Check.is_string(Controller)){
/** @type {Object.<string, any|null>|Function|null} */
const Model = anp.models.get(Controller);
if(Check.is_object(Model))
controllers[key] = Model;
else if(Check.is_function(Model))
controllers[key] = new Model(anp);
};
});
Common.execute(callback);
}, true);
};
this.execute = (name, action, ...parameters) => {};
constructor();
};
return ControllersManager;
})();

View File

@ -0,0 +1,224 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class I18NManager
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const I18NManager = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs I18NManager
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const I18NManager = function(anp){
/** @type {!AnP} */
const self = this,
/** @type {Object.<string, Object.<string, string|Array.<string>>>} */
sentences = {};
/** @type {boolean} */
let started = false,
/** @type {string} */
language = "english",
/** @type {string} */
default_language = "english";
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array(["default_i18n_files", "i18n_files", "default_i18n", "i18n"], (key, next) => {
self.add(anp.settings.get(key), true, next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.clear_dictionary(sentences);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {!(string|Array.<string>)} texts
* @param {?(string|Array.<string>)} languages
* @returns {string|Array.<string>|null}
* @access private
*/
const get_sentence = (texts, languages) => {
/** @type {Array.<string>} */
const keys = Common.get_keys(texts);
if(keys.length){
/** @type {Array.<string>} */
const languages_done = [];
for(let language_key of Common.get_keys(languages).concat(
[language, default_language],
Object.keys(sentences)
)){
if(languages_done.includes(language_key))
continue;
languages_done.push(language_key);
if(!sentences[language_key])
continue;
for(let key of keys)
if(sentences[language_key][key] !== undefined)
return sentences[language_key][key];
};
};
return Common.get_texts(texts)
};
/**
* @param {!(string|Array.<string>)} texts
* @param {?(Object.<string, any|null>|Array<any|null>)} [subinputs = null]
* @param {?(string|Array.<string>)} [languages = null]
* @returns {any|null}
* @access public
*/
this.get = (texts, inputs = null, languages = null) => {
/** @type {string|Array.<string>|null} */
const sentence = get_sentence(texts, languages);
return Common.string_variables((
Check.is_array(sentence) ? sentence.join("") :
sentence), inputs);
};
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?simple_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
for(let subinputs of data)
Object.entries(subinputs).forEach(([new_language, new_sentences]) => {
sentences[new_language] || (sentences[new_language] = {});
Check.is_dictionary(new_sentences) &&
Object.entries(new_sentences).filter(([key, _]) => !Check.is_mark_key(key)).forEach(([key, sentence]) => {
sentences[new_language][key] = sentence;
});
});
Common.execute(callback);
}, true);
};
/**
* @param {!string} new_language
* @return {boolean}
* @access public
*/
this.change = new_language => {
if(sentences[new_language] && new_language != language){
language = new_language;
return true;
};
return false;
};
/**
* @param {!string} check_language
* @returns {boolean}
* @access public
*/
this.is_language_selected = check_language => language == check_language;
constructor();
};
/** @type {Object.<string, any|null>} */
I18NManager.DEFAULT_SETTINGS = {};
return I18NManager;
})();

View File

@ -0,0 +1,148 @@
"use strict";
import {Check} from "../Utils/Checks.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class ModelsManager
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const ModelsManager = (function(){
/**
* @callback default_callback
* @return {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs ModelsManager
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const ModelsManager = function(anp){
/** @type {ModelsManager} */
const self = this,
/** @type {Object.<string, Object.<string, any|null>|Function>} */
models = {};
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.clear_dictionary(models);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(end);
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?default_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
Object.entries(data).forEach(([key, Model]) => {
Model &&
(overwrite || !models[key]) &&
(Check.is_function(Model) || Check.is_object(Model)) &&
(models[key] = Model);
});
Common.execute(callback);
}, true);
};
/**
* @param {!string} name
* @returns {Object.<string, any|null>|Function|null}
*/
this.get = name => models[name] || null;
constructor();
};
return ModelsManager;
})();

View File

@ -0,0 +1,185 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class PrintTypesManager
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const PrintTypesManager = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs PrintTypesManager
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const PrintTypesManager = function(anp){
/** @type {!AnP} */
const self = this,
/** @type {Array.<Array.<string>>} */
types = [
["unkn", "unknown"]
];
/** @type {boolean} */
let started = false;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array(["default_print_types_files", "print_types_files", "default_print_types", "print_types"], (key, next) => {
self.add(anp.settings.get(key), true, next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
types.splice(0, types.length);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {!(string|Array.<string>)} texts
* @param {?(Object.<string, any|null>|Array<any|null>)} [subinputs = null]
* @param {?(string|Array.<string>)} [languages = null]
* @returns {any|null}
* @access public
*/
this.get = type => {
type = type.toLowerCase();
for(let group of types)
if(group.includes(type))
return group[0];
return types[0][0];
};
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?simple_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
if(Check.is_array(data)){
if(data.length && data.every(Check.is_key)){
/** @type {number} */
let i = -1;
/** @type {number} */
const l = types.length;
data = data.map(type => type.toLowerCase())
for(; i < l; i ++)
if(data[0] == types[i][0]){
types.push(...data.filter(type => !types.includes(type)));
break;
};
i == l && types.push(data);
Common.execute(callback);
}else{
Common.execute_array(data.filter(subitem => !Check.is_dictionary(subitem)), (block, next) => {
self.add(block, overwrite, next);
}, callback);
};
}else
Common.execute(callback);
}, false);
};
constructor();
};
/** @type {Object.<string, any|null>} */
PrintTypesManager.DEFAULT_SETTINGS = {};
return PrintTypesManager;
})();

View File

@ -0,0 +1,151 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {RouteModel} from "../Models/RouteModel.ecma.js";
/**
* @typedef {import("../AnP.ecma.js").AnP} AnP
*/
/**
* @class RoutesManager
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const RoutesManager = (function(){
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs RoutesManager
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const RoutesManager = function(anp){
/** @type {RoutesManager} */
const self = this,
/** @type {Array.<RouteModel>} */
routes = [];
/** @type {boolean} */
let started = false,
/** @type {string} */
last_url = "",
/** @type {number|null} */
thread = null;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
thread = anp.threads.add(thread_method, {
bucle : true,
autoplay : true
});
};
/**
* @returns {void}
* @access private
*/
const thread_method = () => {
/** @type {string} */
const current_url = window.location.hash.substring(1);
if(last_url != current_url){
last_url = current_url;
self.go(last_url);
};
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array(["default_routes_files", "routes_files", "default_routes", "routes"], (key, next) => {
self.add(anp.settings.get(key), true, next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
routes.splice(0, routes.length);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
this.add = (inputs, overwrite = false, callback = null) => {
Common.execute(callback, true);
};
this.go = path => {};
constructor();
};
return RoutesManager;
})();

View File

@ -0,0 +1,81 @@
"use strict";
import {SessionModel} from "../Models/SessionModel.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class SessionsManager
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const SessionsManager = (function(){
/**
* @constructs SessionsManager
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const SessionsManager = function(anp){
/** @type {SessionsManager} */
const self = this,
/** @type {Object.<number, SessionModel>} */
sessions = {};
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {number}
* @access public
*/
this.set = inputs => {
/** @type {number} */
let i;
while(sessions[i = Math.random() * (1 << 28) | 0]);
return (sessions[i] = new SessionModel(i, inputs)).i;
};
/**
* @param {!(number|Array.<number>)} ids
* @param {!(string|Array.<string>)} permissions
* @returns {boolean}
* @access public
*/
this.check_permissions = (ids, permissions) => Common.get_array(ids).some(id => (
sessions[id] && sessions[id].check_permissions(permissions)
));
/**
* @param {!number} id
* @returns {boolean}
* @access public
*/
this.close = id => {
if(sessions[id]){
delete sessions[id];
return true;
};
return false;
};
constructor();
};
return SessionsManager;
})();

View File

@ -0,0 +1,189 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class SettingsManager
* @constructor
* @param {!AnP} anp
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @returns {void}
* @access private
* @static
*/
export const SettingsManager = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs SettingsManager
* @param {!AnP} anp
* @param {?(Object.<string, any|null>|Array<any|null>)} [inputs = null]
* @returns {void}
* @access private
* @static
*/
const SettingsManager = function(anp, inputs = null){
/** @type {!AnP} */
const self = this,
/** @type {Object.<string, any|null>} */
settings = {},
/** @type {Object.<string, any|null>} */
secrets = {};
/** @type {boolean} */
let started = false;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array(["default_settings_files", "settings_files", "default_settings", "settings"], (key, next) => {
self.add(self.get(key), true, next);
}, () => {
Common.execute_array(["default_secrets_files", "secrets_files", "default_secrets", "secrets"], (key, next) => {
self.add_secrets(self.get(key), true, next);
}, callback, true);
}, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
[settings, secrets].forEach(Common.clear_dictionary);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {!(string|Array.<string>)} keys
* @param {?(Object.<string, any|null>|Array<any|null>)} [subinputs = null]
* @param {?any} [_default = null]
* @returns {any|null}
* @access public
*/
this.get = (keys, subinputs = null, _default = null) => Common.get_value(keys, [
subinputs, inputs, secrets, settings, SettingsManager.DEFAULT_SETTINGS
], _default);
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?simple_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
for(let subinputs of data)
Object.entries(subinputs).filter(([key, _]) => (
!Check.is_mark_key(key) &&
(overwrite || settings[key] === undefined)
)).forEach(([key, value]) => {
settings[key] = value;
});
Common.execute(callback);
}, true);
};
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?simple_callback} [callback = null]
* @return {void}
* @access public
*/
this.add_secrets = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
for(let subinputs of data)
Object.entries(subinputs).filter(([key, _]) => (
!Check.is_mark_key(key) &&
(overwrite || secrets[key] === undefined))
).forEach(([key, value]) => {
secrets[key] = value;
});
Common.execute(callback);
}, true);
};
constructor();
};
/** @type {Object.<string, any|null>} */
SettingsManager.DEFAULT_SETTINGS = {
autostart : true,
default_settings_files : "/json/AnP.settings.json"
};
return SettingsManager;
})();

View File

@ -0,0 +1,258 @@
"use strict";
import {ThreadModel} from "../Models/ThreadModel.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class ThreadsManager
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
export const ThreadsManager = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs ThreadsManager
* @param {!AnP} anp
* @returns {void}
* @access private
* @static
*/
const ThreadsManager = function(anp){
/** @type {!AnP} */
const self = this,
/** @type {Object.<number, Array.<string>>} */
threads = {};
/** @type {boolean} */
let started = false,
/** @type {number} */
thread_i = 0,
/** @type {number} */
interval = null,
/** @type {string} */
mode = "interval",
/** @type {number} */
frames_per_second = 60,
/** @type {number} */
timer = 1000 / frames_per_second;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
self.start();
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
mode = anp.settings.get("threads_mode", null, mode);
Common.execute(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.clear_dictionary(threads);
mode = "interval";
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => {
executor();
end(true);
});
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @returns {void}
* @access private
*/
const execute = () => {
/** @type {number} */
const time = Date.now();
[...Object.entries(threads)].forEach(([i, thread]) => {
if(!thread.stopped && (
!thread.frames_per_second || time - thread.last >= thread.timer
)){
thread.callback(thread);
if(thread.bucle)
thread.last = time;
else
delete threads[i];
};
});
};
/**
* @returns {void}
* @access private
*/
const executor = () => {
if(!started)
return;
switch(mode){
case "interval":
interval = setInterval(execute, timer);
break;
case "timeout":
setTimeout(() => {
execute();
executor();
}, timer);
break;
case "animation":
/** @type {number} */
const time = Date.now();
requestAnimationFrame(() => {
execute();
setTimeout(executor, timer - (Date.now() - time));
});
break;
case "only_animation":
requestAnimationFrame(() => {
execute();
executor();
});
break;
};
};
/**
* @param {?any} inputs
* @param {!boolean} [overwrite = false]
* @param {?simple_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (callback, inputs = null) => {
if(!Check.is_function(callback))
return null;
threads[++ thread_i] = new ThreadModel(callback, thread_i, inputs);
return thread_i;
};
/**
* @param {!number} i
* @return {void}
* @access public
*/
this.play = i => {
threads[i] && threads[i].stopped && (threads[i].stopped = false);
};
/**
* @param {!number} i
* @return {void}
* @access public
*/
this.stop = i => {
threads[i] && !threads[i].stopped && (threads[i].stopped = true);
};
/**
* @param {!number} i
* @return {boolean}
* @access public
*/
this.close = i => {
if(threads[i]){
delete threads[i];
return true;
};
return false;
};
constructor();
};
/** @type {Object.<string, any|null>} */
ThreadsManager.DEFAULT_SETTINGS = {};
return ThreadsManager;
})();

View File

@ -0,0 +1,221 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
import {Check} from "../Utils/Checks.ecma.js";
import {RE} from "../Utils/Patterns.ecma.js";
import {UniqueKeyModel} from "../Models/UniqueKeyModel.ecma.js";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class UniqueKeysManager
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const UniqueKeysManager = (function(){
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs UniqueKeysManager
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const UniqueKeysManager = function(anp){
/** @type {UniqueKeysManager} */
const self = this,
/** @type {Object.<number, UniqueKeyModel>} */
keys = {},
/** @type {Array.<string>} */
alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".split("");
/** @type {boolean} */
let started = false,
/** @type {number} */
length = 13,
/** @type {number} */
keys_i = 0,
/** @type {number|null} */
thread = null;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
/** @type {string|Array.<string>} */
const new_alphabet = anp.settings.get("unique_keys_alphabet", null, alphabet);
alphabet.splice(0, keys.length, ...Common.unique(
Check.is_string(new_alphabet) ? new_alphabet.split("") :
Check.is_array(new_alphabet) ? new_alphabet :
alphabet));
length = anp.settings.get("unique_keys_length", null, length);
Common.execute(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
keys.splice(0, keys.length);
alphabet.splice(0, keys.length, ..."123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".split(""));
length = 13;
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => {
thread = anp.threads.add(thread_method);
end(true);
});
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @returns {void}
* @access private
*/
const thread_method = () => {
[...Object.entries(keys)].forEach(([i, model]) => {
if(model.is_html_item){
if(model.loaded){
if(!document.querySelector("#" + model.key + ",." + model.key + ",[name=" + model.key + "]"))
delete keys[i];
}else if(document.querySelector("#" + model.key + ",." + model.key + ",[name=" + model.key + "]"))
model.loaded = true;
};
});
};
/**
* @param {!string} key
* @returns {boolean}
* @access public
*/
this.exists = key => Object.values(keys).some(k => k.key === key);
/**
* @param {!boolean} [is_html_item = false]
* @return {string}
* @access public
*/
this.create = (is_html_item = false) => {
/** @type {string} */
let key;
/** @type {number} */
const l = alphabet.length,
/** @type {number} */
shift = Math.ceil(Math.log2(alphabet.length));
do{
key = "";
do{
/** @type {number} */
let random = (Math.random() * (1 << 28)) | 0;
while(random && (key += alphabet[random % l]).length < length)
random >>= shift;
}while(key.length < length);
}while(
!RE.KEY.test(key) ||
document.querySelector("#" + key + ",." + key + ",[name=" + key + "]") ||
self.exists(key)
);
keys[++ keys_i] = new UniqueKeyModel(key, is_html_item, keys_i);
return key;
};
/**
* @param {!string} key
* @returns {boolean}
* @access public
*/
this.remove = key => {
return [...Object.entries(keys)].some(([i, model]) => {
if(model.key == key){
delete keys[i];
return true;
};
return false;
});
};
constructor();
};
return UniqueKeysManager;
})();

View File

@ -0,0 +1,138 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
/**
* @typedef {import("../AnP.ecma.js").AnP} AnP
*/
/**
* @class ViewsManager
* @constructor
* @param {!AnP} anp
* @return {void}
* @access public
* @static
*/
export const ViewsManager = (function(){
/**
* @callback continue_callback
* @param {!boolean} ok
* @return {boolean}
*/
/**
* @constructs ViewsManager
* @param {!AnP} anp
* @return {void}
* @access private
* @static
*/
const ViewsManager = function(anp){
/** @type {ViewsManager} */
const self = this,
/** @type {Object.<string, Object.<string, any|null>>} */
views = {};
/** @type {boolean} */
let started = false;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.update = (callback = null) => {
Common.execute_array(["default_views_files", "views_files", "default_views", "views"], (key, next) => {
self.add(self.get(key), true, next);
}, callback, true);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.reset = (callback = null) => {
Common.clear_dictionary(views);
self.update(callback);
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(started){
end(false);
return false;
};
started = true;
self.update(() => end(true));
return true;
};
/**
* @param {?continue_callback} callback
* @returns {boolean}
* @access public
*/
this.close = (callback = null) => {
/** @type {continue_callback} */
const end = ok => Common.execute(callback, ok);
if(!started){
end(false);
return false;
};
started = false;
end(true);
return true;
};
/**
* @param {?(Object.<string, any|null>|Array.<any|null>)} inputs
* @param {!boolean} [overwrite = false]
* @param {?continue_callback} [callback = null]
* @return {void}
* @access public
*/
this.add = (inputs, overwrite = false, callback = null) => {
anp.files.load_json(inputs, data => {
data.forEach(set => {
Object.entries(set).forEach(([key, value]) => {
if(overwrite || !views[key])
views[key] = value;
});
});
Common.execute(callback, true);
}, true);
};
this.get = (key, inputs = null) => {};
constructor();
};
return ViewsManager;
})();

View File

@ -0,0 +1,59 @@
"use strict";
import {Check} from "../Utils/Checks.ecma.js";
import {Common} from "../Utils/Common.ecma.js";
/**
* @class RouteModel
* @constructor
* @param {!(string|RegExp)} route
* @param {!string} view
* @returns {void}
* @access public
* @static
*/
export const RouteModel = (function(){
/**
* @constructs RouteModel
* @param {!(string|RegExp)} route
* @param {!string} view
* @returns {void}
* @access private
* @static
*/
const RouteModel = function(route, view){
/** @type {RouteModel} */
const self = this;
/** @type {RegExp|null} */
this.route = null;
/** @type {Array.<string>} */
this.variables = [];
/** @type {string} */
this.view = view;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
if(Check.is_string(route))
route = new RegExp("^" + Common.to_regular_expression(route.replace(RE.STRING_VARIABLES, (_, key) => {
self.variables.push(key);
return "#######";
})).replace(/#{7}/g, "([^\\/]+)") + "\\/?$", "i");
else if(Check.is_regular_expression(route))
(this.route = route).source.replace(/\([^\(\)]+\)/g, all => {
self.variables.push("" + self.variables.length);
return all;
});
};
constructor();
};
return RouteModel;
})();

View File

@ -0,0 +1,70 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
/**
* @class SessionModel
* @constructor
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {void}
* @access private
* @static
*/
export const SessionModel = (function(){
/**
* @constructs SessionModel
* @param {!number} i
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {void}
* @access private
* @static
*/
const SessionModel = function(i, inputs){
/** @type {SessionModel} */
const self = this;
/** @type {number|null} */
let id = null,
/** @type {Array.<string>} */
permissions = [],
/** @type {number} */
last_check = 0;
/** @type {string|null} */
this.nick = null;
/** @type {number} */
this.type = SessionModel.LOCAL;
/** @type {number} */
this.i = i;
/**
* @returns {void}
* @access private
*/
const constructor = () => {
id = Common.get_value("id", inputs, null);
permissions = Common.get_value("permissions", inputs, []);
self.nick = Common.get_value("nick", inputs, null);
self.type = Common.get_value("type", inputs, self.type);
last_check = Date.now();
};
/**
* @param {!(string|Array.<string>)} permissions
* @returns {boolean}
* @access public
*/
this.check_permissions = permissions => permissions.some(self.permissions.includes);
constructor();
};
/** @type {number} */
SessionModel.LOCAL = 1 << 0;
/** @type {number} */
SessionModel.REMOTE = 1 << 1;
return SessionModel;
})();

View File

@ -0,0 +1,53 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
/**
* @class ThreadModel
* @constructor
* @param {!thread_callback} callback
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {void}
* @access public
* @static
*/
export const ThreadModel = (function(){
/**
* @callback thread_callback
* @param {!ThreadModel} thread
* @return {void}
*/
/**
* @constructs ThreadModel
* @param {!thread_callback} callback
* @param {!number} i
* @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null]
* @return {void}
* @access private
* @static
*/
const ThreadModel = function(callback, i, inputs = null){
/** @type {number} */
this.i = i;
/** @type {thread_callback} */
this.callback = callback;
/** @type {boolean} */
this.autoplay = Common.get_value("autoplay", inputs, true);
/** @type {boolean} */
this.play_immediately = Common.get_value("play_immediately", inputs, false);
/** @type {number} */
this.last = this.play_immediately ? 0 : Date.now();
/** @type {boolean} */
this.stopped = Common.get_value("stopped", inputs, false);
/** @type {number} */
this.frames_per_second = Common.get_value(["frames_per_second", "fps"], inputs, 0);
/** @type {number} */
this.timer = this.frames_per_second > 0 ? 1000 / this.frames_per_second : 0;
/** @type {boolean} */
this.bucle = Common.get_value("bucle", inputs, false);
};
return ThreadModel;
})();

View File

@ -0,0 +1,45 @@
"use strict";
import {Common} from "../Utils/Common.ecma.js";
/**
* @class ThreadModel
* @constructor
* @param {!thread_callback} callback
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @return {void}
* @access public
* @static
*/
export const UniqueKeyModel = (function(){
/**
* @callback thread_callback
* @param {!UniqueKeyModel} thread
* @return {void}
*/
/**
* @constructs UniqueKeyModel
* @param {!string} key
* @param {!boolean} is_html_item
* @param {!number} i
* @return {void}
* @access private
* @static
*/
const UniqueKeyModel = function(key, is_html_item, i){
/** @type {number} */
this.i = i;
/** @type {string} */
this.key = key;
/** @type {boolean} */
this.is_html_item = is_html_item;
/** @type {boolean} */
this.loaded = false;
/** @type {number} */
this.date = Date.now();
};
return UniqueKeyModel;
})();

View File

@ -0,0 +1,147 @@
"use strict";
import {RE} from "./Patterns.ecma.js";
import {Common} from "./Common.ecma.js";
/**
* @class Check
* @constructor
* @returns {void}
* @access private
* @static
*/
export const Check = (function(){
/**
* @constructs Check
* @returns {void}
* @access private
* @static
*/
const Check = function(){};
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_string = item => typeof item == "string";
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_key = item => typeof item == "string" && RE.KEY.test(item);
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_object = item => item && typeof item == "object";
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_dictionary = item => item && item.constructor == Object;
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_array = item => item instanceof Array;
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_function = item => typeof item == "function";
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_bool = item => typeof item == "boolean";
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_json_item = item => Check.is_dictionary(item) || Check.is_array(item);
/**
* @param {?any} item
* @param {!boolean} [full_check = null]
* @returns {boolean}
* @access public
* @static
*/
Check.is_json = (item, full_check = true) => (
item && Check.is_string(item) &&
["[]", "{}"].includes((item = item.trim())[0] + item[item.length - 1]) &&
(!full_check || JSON.parse(item, () => null) !== null)
);
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_html_item = item => item && (item.tagName || item.nodeName);
/**
* @param {?any} item
* @returns {boolean}
* @access public
* @static
*/
Check.is_regular_expression = item => item instanceof RegExp;
/**
* @param {!string} key
* @param {!(string|Array.<string>)} [marks = "AnP"]
* @returns {boolean}
* @access public
* @static
*/
Check.is_mark_key = (key, marks = "AnP") => (
Check.is_key(key) &&
Common.get_keys(marks).some(mark => key.startsWith(mark + "_")) &&
["end", "start"].some(close => key.endsWith("_" + close))
);
/**
* @returns {boolean}
* @access public
* @static
*/
Check.is_mobile = () => ((a) => (
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) ||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))
))(navigator.userAgent || navigator.vendor || window.opera);
/**
* @returns {boolean}
* @access public
* @static
*/
Check.is_dark_mode = () => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
return Check;
})();

View File

@ -0,0 +1,471 @@
"use strict";
import {Check} from "./Checks.ecma.js";
import {RE} from "./Patterns.ecma.js";
/**
* @class Common
* @constructor
* @returns {void}
* @access private
* @static
*/
export const Common = (function(){
/**
* @callback execute_callback
* @param {...(any|null)} parameters
* @returns {any|null}
*/
/**
* @callback simple_callback
* @returns {void}
*/
/**
* @callback each_item_callback
* @param {?any} item
* @param {!simple_callback} next
* @return {void}
*/
/**
* @callback preload_callback
* @param {?HTMLElement} item
* @param {!boolean} asynchronous
* @param {!boolean} ok
* @return {void}
*/
/**
* @constructs Common
* @returns {void}
* @access private
* @static
*/
const Common = function(){};
/** @type {Object.<string, Object.<string, string>>} */
Common.REGULAR_EXPRESSION = {
TO : {
"\n" : "n",
"\r" : "r",
"\t" : "t"
},
FROM : {
n : "\n",
r : "\r",
t : "\t"
}
};
/**
* @param {...(any|null)} items
* @returns {Array.<string>}
* @access public
* @static
*/
Common.get_keys = (...items) => items.reduce((keys, item) => {
if(Check.is_key(item))
keys.includes(item) || keys.push(item);
else if(Check.is_array(item))
keys.push(...Common.get_keys(...item).filter(key => !keys.includes(key)));
return keys;
}, []);
/**
* @param {...(any|null)} items
* @returns {Array.<string>}
* @access public
* @static
*/
Common.get_texts = (...items) => items.reduce((texts, item) => {
if(Check.is_string(item))
texts.includes(item) || texts.push(item);
else if(Check.is_array(item))
texts.push(...Common.get_texts(...item));
return texts;
}, []);
/**
* @param {...(any|null)} items
* @returns {Array.<Object.<string, any|null>>}
* @access public
* @static
*/
Common.get_dictionaries = (...items) => items.reduce((dictionaries, item) => {
if(Check.is_dictionary(item))
dictionaries.push(item);
else if(Check.is_array(item))
dictionaries.push(...Common.get_dictionaries(...item));
return dictionaries;
}, []);
/**
* @param {any|null} items
* @param {!boolean} [overwrite = false]
* @param {!Array.<string>} [except = []]
* @returns {Object.<string, any|null>}
* @access public
* @static
*/
Common.get_dictionary = (items, overwrite = false, except = []) => {
if(Check.is_dictionary(items))
return Object.entries(items).filter(([key, _]) => !except.includes(key)).reduce((dictionary, [key, value]) => {
dictionary[key] = value;
return dictionary;
}, {});
if(Check.is_array(items))
return items.reduce((dictionary, item) => {
if(Check.is_dictionary(item))
Object.keys(item).filter(key => (
overwrite || dictionary[key] === undefined
) && !except.includes(key)).forEach(key => {
dictionary[key] = item[key];
});
else if(Check.is_array(item))
Object.entries(Common.get_dictionary(item, overwrite, except)).filter(([key, _]) => (
overwrite || dictionary[key] === undefined
) && !except.includes(key)).forEach(([key, value]) => {
dictionary[key] = value;
});
return dictionary;
}, {});
return {};
};
/**
* @param {?any} items
* @returns {Array.<any|null>}
* @access public
* @static
*/
Common.get_array = items => Check.is_array(items) ? items : [items];
/**
* @param {!(string|Array.<string>)} keys
* @param {!(Object.<string, any|null>|Array<any|null>)} inputs
* @param {?any} [_default = null]
* @returns {any|null}
* @access public
* @static
*/
Common.get_value = (keys, inputs, _default = null) => {
if((keys = Common.get_keys(keys)).length)
for(let subinputs of Common.get_dictionaries(inputs))
for(let key of keys)
if(subinputs[key] !== undefined)
return subinputs[key];
return _default;
};
/**
* @param {!string} string
* @param {!(Object.<string, any|null>|Array<any|null>)} inputs
* @param {?any} [_default = null]
* @returns {string}
* @access public
* @static
*/
Common.string_variables = (string, inputs, _default = null) => {
inputs = Common.get_dictionary(inputs);
return ("" + string).replace(RE.STRING_VARIABLES, (all, key) => (
inputs[key] !== undefined ? inputs[key] :
_default !== null ? _default :
all));
};
/**
* @param {!execute_callback} callback
* @param {...(any|null)} parameters
* @returns {any|null}
* @access public
* @static
*/
Common.execute = (callback, ...parameters) => Check.is_function(callback) ? callback(...parameters) : null;
/**
* @param {!Array.<any|null>} array
* @param {!each_item_callback} each_callback
* @param {?simple_callback} end_callback
* @param {!number} [i = null]
* @returns {void}
* @access private
* @static
*/
const execute_array_ordered = (array, each_callback, end_callback, i = 0) => {
if(i == array.length)
Common.execute(end_callback);
else
Common.execute(each_callback, array[i], () => {
execute_array_ordered(array, each_callback, end_callback, i + 1);
});
};
/**
* @param {!Array.<any|null>} array
* @param {!each_item_callback} each_callback
* @param {?simple_callback} end_callback
* @returns {void}
* @access private
* @static
*/
const execute_array_unordered = (array, each_callback, end_callback) => {
/** @type {number} */
const l = array.length;
/** @type {number} */
let i = 0;
if(array.length){
for(let item of array)
Common.execute(each_callback, item, () => {
++ i == l && Common.execute(end_callback);
});
}else
Common.execute(end_callback);
};
/**
* @param {!Array.<any|null>} array
* @param {!each_item_callback} each_callback
* @param {?simple_callback} end_callback
* @param {!boolean} [ordered = false]
* @returns {void}
* @access public
* @static
*/
Common.execute_array = (array, each_callback, end_callback = null, ordered = false) => {
if(ordered)
execute_array_ordered(array, each_callback, end_callback);
else
execute_array_unordered(array, each_callback, end_callback);
};
/**
* @param {!Object.<string, any|null>} dictionary
* @returns {void}
* @access public
* @static
*/
Common.clear_dictionary = dictionary => {
[...Object.keys(dictionary)].forEach(key => {
delete dictionary[key];
});
};
/**
* @param {!string} string
* @returns {string}
* @access public
* @static
*/
Common.to_kebab = string => string.replace(RE.TO_KEBAB, (_, capital, rest, special) => (
capital ? "-" + (capital + rest).toLowerCase() :
special ? "-" :
"")).toLowerCase();
/**
* @param {!(string|HTMLElement)} selector
* @param {!preload_callback} callback
* @param {!number} [timeout = 2000]
* @param {!number} [fps = 10]
* @returns {void}
* @access public
* @static
*/
Common.preload = (selector, callback, timeout = 2000, fps = 10) => {
if(!Check.is_function(callback))
return;
if(Check.is_html_item(selector))
return callback(selector, false, true);
if(!Check.is_string(selector))
return callback(null, false, false);
/** @type {HTMLElement|null} */
let item;
try{
if(item = document.querySelector(selector))
try{
return callback(item, false, true);
}catch(exception){
console.error(exception);
};
}catch(exception){
return callback(null, false, false);
};
/** @type {number} */
const date = Date.now(),
/** @type {number} */
interval = setInterval(() => {
if(item = document.querySelector(selector)){
clearInterval(interval);
return callback(item, true, true);
};
if(Date.now() - date > timeout){
clearInterval(interval);
return callback(null, true, false);
};
}, 1000 / fps);
};
/**
* @param {...(HTMLElement|string|Array.<any|null>)} inputs
* @returns {Array.<HTMLElement>}
* @access public
* @static
*/
Common.HTML = (...inputs) => {
/** @type {DocumentFragment} */
const fragment = new DocumentFragment(),
/** @type {HTMLElement|null} */
master = (
Check.is_html_item(inputs[0]) ? inputs[0] :
Check.is_string(inputs[0]) ? document.querySelector(inputs[0]) :
null);
(master ? inputs.slice(1) : inputs).forEach(subinputs => {
if(Check.is_html_item(subinputs))
fragment.appendChild(subinputs);
else if(Check.is_string(subinputs))
fragment.appendChild(document.createTextNode(subinputs));
else if(Check.is_array(subinputs)){
/** @type {[string, Object.<string, any|null>|null, any|null]} */
const [tag, attributes, children] = subinputs.concat([null, null]).slice(0, 3),
/** @type {HTMLElement} */
item = document.createElement(tag);
Check.is_dictionary(attributes) && Object.entries(attributes).forEach(([key, value]) => {
if(RE.ON_ATTRIBUTE.test(key) && Check.is_function(value))
item.addEventListener(key.replace(RE.ON_ATTRIBUTE, "").replace(RE.SPECIAL_HTML_EVENT_CHARACTERS, "").toLowerCase(), event => {
value(item, event);
});
else if(value !== null)
item.setAttribute(Common.to_kebab(key), value);
});
if(Check.is_array(children))
Common.HTML(...children).forEach(child => item.appendChild(child));
else if(Check.is_string(children))
item.innerHTML += children;
fragment.appendChild(item);
};
});
master && master.appendChild(fragment);
return [...fragment.childNodes];
};
/**
* @param {?any} value
* @returns {any|null}
* @access public
* @static
*/
Common.unique = value => (
Check.is_string(value) ? value.split("").filter((char, i, array) => array.indexOf(char) == i).join("") :
Check.is_array(value) ? value.filter((item, i, array) => array.indexOf(item) == i) :
value);
/**
* @param {?any} value
* @return {string|null}
* @access public
* @static
*/
Common.json_encode = value => {
try{
return JSON.stringify(value);
}catch(exception){};
return null;
};
/**
* @param {?any} value
* @returns {Object.<string, any|null>|Array.<any|null>|null}
* @access public
* @static
*/
Common.json_decode = value => {
try{
return JSON.parse(value);
}catch(exception){};
return null;
};
/**
* @param {?any} value
* @returns {string|null}
* @access public
* @static
*/
Common.base64_encode = value => {
if(Check.is_json_item(value))
return btoa(JSON.stringify(value));
try{
return btoa(value);
}catch(exception){};
return null;
};
/**
* @param {?any} value
* @returns {string|null}
* @access public
* @static
*/
Common.base64_decode = value => {
try{
return atob(value);
}catch(exception){};
return null;
};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} data
* @returns {string}
* @access public
* @static
*/
Common.data_encode = data => Common.base64_encode(Common.json_encode(data));
/**
* @param {!string} data
* @returns {(Object.<string, any|null>|Array.<any|null>)}
* @access public
* @static
*/
Common.data_decode = data => Common.json_decode(Common.base64_decode(data));
/**
* @param {!string} string
* @returns {string}
* @access public
* @static
*/
Common.to_regular_expression = string => string.replace(RE.TO_REGULAR_EXPRESSION, character => (
"\\" + (Common.REGULAR_EXPRESSION.FROM[character] || character)
));
return Common;
})();

View File

@ -0,0 +1,349 @@
"use strict";
/**
* @callback element_callback
* @param {!Object.<string, any|null>} [attributes = {}]
* @param {!Array.<any|null>} [children = []]
* @returns {!Array.<any>}
*/
/** @type {element_callback} */
export const Div = (attributes = {}, children = []) => ["div", attributes, children];
/** @type {element_callback} */
export const Span = (attributes = {}, children = []) => ["span", attributes, children];
/** @type {element_callback} */
export const Footer = (attributes = {}, children = []) => ["footer", attributes, children];
/** @type {element_callback} */
export const Header = (attributes = {}, children = []) => ["header", attributes, children];
/** @type {element_callback} */
export const Main = (attributes = {}, children = []) => ["main", attributes, children];
/** @type {element_callback} */
export const H1 = (attributes = {}, children = []) => ["h1", attributes, children];
/** @type {element_callback} */
export const H2 = (attributes = {}, children = []) => ["h2", attributes, children];
/** @type {element_callback} */
export const H3 = (attributes = {}, children = []) => ["h3", attributes, children];
/** @type {element_callback} */
export const H4 = (attributes = {}, children = []) => ["h4", attributes, children];
/** @type {element_callback} */
export const H5 = (attributes = {}, children = []) => ["h5", attributes, children];
/** @type {element_callback} */
export const H6 = (attributes = {}, children = []) => ["h6", attributes, children];
/** @type {element_callback} */
export const Heading1 = H1;
/** @type {element_callback} */
export const Heading2 = H2;
/** @type {element_callback} */
export const Heading3 = H3;
/** @type {element_callback} */
export const Heading4 = H4;
/** @type {element_callback} */
export const Heading5 = H5;
/** @type {element_callback} */
export const Heading6 = H6;
/** @type {element_callback} */
export const Heading = (level, attributes = {}, children = []) => {
const tag = "h" + Math.min(Math.max(1, level), 6);
return [tag, attributes, children];
};
/** @type {element_callback} */
export const H = Heading;
/** @type {element_callback} */
export const A = (attributes = {}, children = []) => ["a", attributes, children];
/** @type {element_callback} */
export const Anchor = A;
/** @type {element_callback} */
export const Img = (attributes = {}, children = []) => ["img", attributes, children];
/** @type {element_callback} */
export const Image = Img;
/** @type {element_callback} */
export const P = (attributes = {}, children = []) => ["p", attributes, children];
/** @type {element_callback} */
export const Paragraph = P;
/** @type {element_callback} */
export const Section = (attributes = {}, children = []) => ["section", attributes, children];
/** @type {element_callback} */
export const Article = (attributes = {}, children = []) => ["article", attributes, children];
/** @type {element_callback} */
export const Aside = (attributes = {}, children = []) => ["aside", attributes, children];
/** @type {element_callback} */
export const Label = (attributes = {}, children = []) => ["label", attributes, children];
/** @type {element_callback} */
export const Form = (attributes = {}, children = []) => ["form", attributes, children];
/** @type {element_callback} */
export const Fieldset = (attributes = {}, children = []) => ["fieldset", attributes, children];
/** @type {element_callback} */
export const Legend = (attributes = {}, children = []) => ["legend", attributes, children];
/** @type {element_callback} */
export const Input = (attributes = {}, children = []) => ["input", attributes, children];
/** @type {element_callback} */
export const Checkbox = (attributes = {}, children = []) => ["input", Object.assign({type : "checkbox"}, attributes), children];
/** @type {element_callback} */
export const Radio = (attributes = {}, children = []) => ["input", Object.assign({type : "radio"}, attributes), children];
/** @type {element_callback} */
export const Submit = (attributes = {}, children = []) => ["input", Object.assign({type : "submit"}, attributes), children];
/** @type {element_callback} */
export const Reset = (attributes = {}, children = []) => ["input", Object.assign({type : "reset"}, attributes), children];
/** @type {element_callback} */
export const Hidden = (attributes = {}, children = []) => ["input", Object.assign({type : "hidden"}, attributes), children];
/** @type {element_callback} */
export const Text = (attributes = {}, children = []) => ["input", Object.assign({type : "text"}, attributes), children];
/** @type {element_callback} */
export const Date = (attributes = {}, children = []) => ["input", Object.assign({type : "date"}, attributes), children];
/** @type {element_callback} */
export const File = (attributes = {}, children = []) => ["input", Object.assign({type : "file"}, attributes), children];
/** @type {element_callback} */
export const Password = (attributes = {}, children = []) => ["input", Object.assign({type : "password"}, attributes), children];
/** @type {element_callback} */
export const Email = (attributes = {}, children = []) => ["input", Object.assign({type : "email"}, attributes), children];
/** @type {element_callback} */
export const Number = (attributes = {}, children = []) => ["input", Object.assign({type : "number"}, attributes), children];
/** @type {element_callback} */
export const Integer = (attributes = {}, children = []) => ["input", Object.assign({type : "number", step : 1}, attributes), children];
/** @type {element_callback} */
export const Float = Number;
/** @type {element_callback} */
export const Range = (attributes = {}, children = []) => ["input", Object.assign({type : "range"}, attributes), children];
/** @type {element_callback} */
export const Color = (attributes = {}, children = []) => ["input", Object.assign({type : "color"}, attributes), children];
/** @type {element_callback} */
export const RadioButton = Radio;
/** @type {element_callback} */
export const Button = (attributes = {}, children = []) => ["button", attributes, children];
/** @type {element_callback} */
export const Textarea = (attributes = {}, children = []) => ["textarea", attributes, children];
/** @type {element_callback} */
export const Select = (attributes = {}, children = []) => ["select", attributes, children];
/** @type {element_callback} */
export const Option = (attributes = {}, children = []) => ["option", attributes, children];
/** @type {element_callback} */
export const Optgroup = (attributes = {}, children = []) => ["optgroup", attributes, children];
/** @type {element_callback} */
export const OptionGroup = Optgroup;
/** @type {element_callback} */
export const Table = (attributes = {}, children = []) => ["table", attributes, children];
/** @type {element_callback} */
export const TBody = (attributes = {}, children = []) => ["tbody", attributes, children];
/** @type {element_callback} */
export const THead = (attributes = {}, children = []) => ["thead", attributes, children];
/** @type {element_callback} */
export const TFoot = (attributes = {}, children = []) => ["tfoot", attributes, children];
/** @type {element_callback} */
export const TR = (attributes = {}, children = []) => ["tr", attributes, children];
/** @type {element_callback} */
export const TD = (attributes = {}, children = []) => ["td", attributes, children];
/** @type {element_callback} */
export const TH = (attributes = {}, children = []) => ["th", attributes, children];
/** @type {element_callback} */
export const TableBody = TBody;
/** @type {element_callback} */
export const TableHead = THead;
/** @type {element_callback} */
export const TableFoot = TFoot;
/** @type {element_callback} */
export const TableRow = TR;
/** @type {element_callback} */
export const TableCell = TD;
/** @type {element_callback} */
export const TableHeaderCell = TH;
/** @type {element_callback} */
export const UL = (attributes = {}, children = []) => ["ul", attributes, children];
/** @type {element_callback} */
export const OL = (attributes = {}, children = []) => ["ol", attributes, children];
/** @type {element_callback} */
export const LI = (attributes = {}, children = []) => ["li", attributes, children];
/** @type {element_callback} */
export const DL = (attributes = {}, children = []) => ["dl", attributes, children];
/** @type {element_callback} */
export const DT = (attributes = {}, children = []) => ["dt", attributes, children];
/** @type {element_callback} */
export const DD = (attributes = {}, children = []) => ["dd", attributes, children];
/** @type {element_callback} */
export const Nav = (attributes = {}, children = []) => ["nav", attributes, children];
/** @type {element_callback} */
export const UnorderedList = UL;
/** @type {element_callback} */
export const OrderedList = OL;
/** @type {element_callback} */
export const ListItem = LI;
/** @type {element_callback} */
export const DescriptionList = DL;
/** @type {element_callback} */
export const DescriptionTerm = DT;
/** @type {element_callback} */
export const DescriptionDetails = DD;
/** @type {element_callback} */
export const Navigation = Nav;
/** @type {element_callback} */
export const I = (attributes = {}, children = []) => ["i", attributes, children];
/** @type {element_callback} */
export const Italic = I;
/** @type {element_callback} */
export const B = (attributes = {}, children = []) => ["b", attributes, children];
/** @type {element_callback} */
export const Strong = B;
/** @type {element_callback} */
export const Bold = B;
/** @type {element_callback} */
export const U = (attributes = {}, children = []) => ["u", attributes, children];
/** @type {element_callback} */
export const Underline = U;
/** @type {element_callback} */
export const S = (attributes = {}, children = []) => ["s", attributes, children];
/** @type {element_callback} */
export const Strike = S;
/** @type {element_callback} */
export const StrikeThrough = S;
/** @type {element_callback} */
export const Mark = (attributes = {}, children = []) => ["mark", attributes, children];
/** @type {element_callback} */
export const Small = (attributes = {}, children = []) => ["small", attributes, children];
/** @type {element_callback} */
export const Sub = (attributes = {}, children = []) => ["sub", attributes, children];
/** @type {element_callback} */
export const Subscript = Sub;
/** @type {element_callback} */
export const Sup = (attributes = {}, children = []) => ["sup", attributes, children];
/** @type {element_callback} */
export const Superscript = Sup;
/** @type {element_callback} */
export const BR = (attributes = {}, children = []) => ["br", attributes, children];
/** @type {element_callback} */
export const Break = BR;
/** @type {element_callback} */
export const HR = (attributes = {}, children = []) => ["hr", attributes, children];
/** @type {element_callback} */
export const HorizontalRule = HR;
/** @type {element_callback} */
export const Datalist = (attributes = {}, children = []) => ["datalist", attributes, children];
/** @type {element_callback} */
export const Output = (attributes = {}, children = []) => ["output", attributes, children];
/** @type {element_callback} */
export const Progress = (attributes = {}, children = []) => ["progress", attributes, children];
/** @type {element_callback} */
export const Meter = (attributes = {}, children = []) => ["meter", attributes, children];
/** @type {element_callback} */
export const Details = (attributes = {}, children = []) => ["details", attributes, children];
/** @type {element_callback} */
export const Summary = (attributes = {}, children = []) => ["summary", attributes, children];
/** @type {element_callback} */
export const Dialog = (attributes = {}, children = []) => ["dialog", attributes, children];
/** @type {element_callback} */
export const Menu = (attributes = {}, children = []) => ["menu", attributes, children];
/** @type {element_callback} */
export const Menuitem = (attributes = {}, children = []) => ["menuitem", attributes, children];
/** @type {element_callback} */
export const Menuitemcheckbox = (attributes = {}, children = []) => ["menuitemcheckbox", attributes, children];
/** @type {element_callback} */
export const Menuitemradio = (attributes = {}, children = []) => ["menuitemradio", attributes, children];
/** @type {element_callback} */
export const Slot = (attributes = {}, children = []) => ["slot", attributes, children];
/** @type {element_callback} */
export const Template = (attributes = {}, children = []) => ["template", attributes, children];
/** @type {element_callback} */
export const Canvas = (attributes = {}, children = []) => ["canvas", attributes, children];
/** @type {element_callback} */
export const SVG = (attributes = {}, children = []) => ["svg", attributes, children];
/** @type {element_callback} */
export const MathML = (attributes = {}, children = []) => ["math", attributes, children];
/** @type {element_callback} */
export const Audio = (attributes = {}, children = []) => ["audio", attributes, children];
/** @type {element_callback} */
export const Video = (attributes = {}, children = []) => ["video", attributes, children];
/** @type {element_callback} */
export const Source = (attributes = {}, children = []) => ["source", attributes, children];
/** @type {element_callback} */
export const Track = (attributes = {}, children = []) => ["track", attributes, children];
/** @type {element_callback} */
export const Iframe = (attributes = {}, children = []) => ["iframe", attributes, children];
/** @type {element_callback} */
export const Embed = (attributes = {}, children = []) => ["embed", attributes, children];
/** @type {element_callback} */
export const Object = (attributes = {}, children = []) => ["object", attributes, children];
/** @type {element_callback} */
export const Param = (attributes = {}, children = []) => ["param", attributes, children];
/** @type {element_callback} */
export const Picture = (attributes = {}, children = []) => ["picture", attributes, children];
/** @type {element_callback} */
export const SourceElement = (attributes = {}, children = []) => ["source", attributes, children];
/** @type {element_callback} */
export const Map = (attributes = {}, children = []) => ["map", attributes, children];
/** @type {element_callback} */
export const Area = (attributes = {}, children = []) => ["area", attributes, children];
/** @type {element_callback} */
export const Meta = (attributes = {}, children = []) => ["meta", attributes, children];
/** @type {element_callback} */
export const Link = (attributes = {}, children = []) => ["link", attributes, children];
/** @type {element_callback} */
export const Base = (attributes = {}, children = []) => ["base", attributes, children];
/** @type {element_callback} */
export const Head = (attributes = {}, children = []) => ["head", attributes, children];
/** @type {element_callback} */
export const Body = (attributes = {}, children = []) => ["body", attributes, children];
/** @type {element_callback} */
export const HTML = (attributes = {}, children = []) => ["html", attributes, children];

View File

@ -0,0 +1,12 @@
"use strict";
/** @type {Object.<string, RegExp>} */
export const RE = {
KEY : /^[a-z_][a-z0-9_]*$/i,
STRING_VARIABLES : /\{([a-z_][a-z0-9_]*)\}/gi,
TO_KEBAB : /[\-_]?([A-Z])([A-Z0-9]*|[a-z0-9]*)|([^a-z0-9]+)/g,
ON_ATTRIBUTE : /^on[\-_]?/i,
SPECIAL_HTML_EVENT_CHARACTERS : /[^a-z0-9]+/gi,
WHITE_SPACES : /(?:\s+|[\r\n]+)+/g,
TO_REGULAR_EXPRESSION : /[\.\-\^\$\\\/\[\]\(\)\{\}\!\?\*\+\n\r\t]/g
};

BIN
Public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
Public/images/AnP-180.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
Public/images/AnP-192.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Public/images/AnP-270.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Public/images/AnP-32.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
Public/images/AnP-512.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
Public/images/AnP.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
Public/images/default_avatar.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="flag_english.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.7500982"
inkscape:cx="173.31064"
inkscape:cy="281.96308"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg5" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient945"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop941" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.20887271"
id="stop2636" /><stop
style="stop-color:#e5e5e5;stop-opacity:0.21659547;"
offset="0.85605043"
id="stop949" /><stop
style="stop-color:#3c3c3c;stop-opacity:0.26710457;"
offset="0.94723415"
id="stop951" /><stop
style="stop-color:#292929;stop-opacity:0.76282448;"
offset="0.99964374"
id="stop943" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient945"
id="radialGradient3957"
cx="100"
cy="100"
fx="100"
fy="100"
r="100"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2627"
id="linearGradient2629"
x1="100.74469"
y1="5.484745"
x2="100.27773"
y2="95.039955"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1666667,0,0,1.0982583,-16.66666,-0.4912933)" /><linearGradient
inkscape:collect="always"
id="linearGradient2627"><stop
style="stop-color:#ffffff;stop-opacity:0.66302198;"
offset="0"
id="stop2623" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2625" /></linearGradient></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Circled"
style="display:inline"><g
inkscape:groupmode="layer"
id="g2395"
inkscape:label="english"
style="display:inline"><path
id="rect1711-8"
style="display:inline;fill:#000080;stroke-width:0.755231"
inkscape:label="Blue"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z" /><path
id="rect1711-9-7"
style="display:inline;fill:#ffffff;stroke-width:0.755231"
inkscape:label="WhiteBackCross"
d="M 166.38674,25.222233 99.99493,75.009892 33.651693,25.258923 A 100,100 0 0 0 9.6283529,57.241467 L 66.65898,100.00888 9.634554,142.77165 a 100,100 0 0 0 24.027991,31.97944 l 66.332385,-49.74322 66.33755,49.74684 a 100,100 0 0 0 24.03058,-31.97686 L 133.3314,100.00888 190.38424,57.224414 a 100,100 0 0 0 -23.9975,-32.002181 z" /><path
id="rect2163-9"
style="display:inline;fill:#ff0000;stroke-width:0.208525"
inkscape:label="RedBackCross"
d="m 170.82213,29.412675 -73.376398,54.054065 5.930908,8.051188 74.17273,-54.640592 a 100,100 0 0 0 -6.72724,-7.464661 z M 17.033069,44.214355 a 100,100 0 0 0 -5.140772,8.633582 l 58.217635,42.887305 5.931421,-8.051188 z m 109.648091,57.142245 -5.93091,8.05119 62.45097,46.00598 a 100,100 0 0 0 5.11338,-8.65322 z m -26.63817,5.00538 -77.362721,56.99032 a 100,100 0 0 0 6.777364,7.42797 l 76.516257,-56.3671 z" /><path
id="rect2134-2"
style="display:inline;fill:#ffffff;stroke-width:0.282642"
inkscape:label="WhiteMainCross"
d="M 100.0001,0 A 100,100 0 0 0 79.999768,2.0810099 V 79.999768 H 2.0810099 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 2.0810099,119.99991 H 79.999768 v 77.91876 a 100,100 0 0 0 20.000332,2.08153 100,100 0 0 0 19.99981,-2.08153 v -77.91876 h 77.91876 A 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 197.97448,79.999768 H 119.99991 V 2.0257161 A 100,100 0 0 0 100.0001,0 Z" /><path
id="rect2269-0"
style="display:inline;fill:#ff0000;stroke-width:0.227362"
inkscape:label="RedMainCross"
d="M 100.0001,0 A 100,100 0 0 0 90.000191,0.56430664 V 90.000191 H 0.56430664 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 0.56430664,110 H 90.000191 v 89.43589 A 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 110,199.43589 V 110 h 89.43589 a 100,100 0 0 0 0.56431,-9.9999 100,100 0 0 0 -0.50488,-9.999909 H 110 V 0.50487874 A 100,100 0 0 0 100.0001,0 Z" /></g></g><g
inkscape:label="Crystal"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true"><path
id="path3947"
style="fill:url(#radialGradient3957);fill-opacity:1;fill-rule:nonzero;stroke-width:0.252389"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z m 0,5.0002116 A 70,50 0 0 1 169.99996,54.999744 70,50 0 0 1 100.0001,104.99979 70,50 0 0 1 30.000236,54.999744 70,50 0 0 1 100.0001,5.0002116 Z"
inkscape:label="Sphera" /><ellipse
style="display:inline;fill:url(#linearGradient2629);fill-opacity:1;stroke-width:0.381538"
id="path1679-3"
cx="100"
cy="55"
rx="70"
ry="50"
inkscape:label="Brightness" /></g></svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="flag_espanol.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.7500982"
inkscape:cx="173.31064"
inkscape:cy="281.96308"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg5" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient945"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop941" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.20887271"
id="stop2636" /><stop
style="stop-color:#e5e5e5;stop-opacity:0.21659547;"
offset="0.85605043"
id="stop949" /><stop
style="stop-color:#3c3c3c;stop-opacity:0.26710457;"
offset="0.94723415"
id="stop951" /><stop
style="stop-color:#292929;stop-opacity:0.76282448;"
offset="0.99964374"
id="stop943" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient945"
id="radialGradient3957"
cx="100"
cy="100"
fx="100"
fy="100"
r="100"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2627"
id="linearGradient2629"
x1="100.74469"
y1="5.484745"
x2="100.27773"
y2="95.039955"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1666667,0,0,1.0982583,-16.66666,-0.4912933)" /><linearGradient
inkscape:collect="always"
id="linearGradient2627"><stop
style="stop-color:#ffffff;stop-opacity:0.66302198;"
offset="0"
id="stop2623" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2625" /></linearGradient></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Circled"
style="display:inline"><g
inkscape:groupmode="layer"
id="layer2-5"
inkscape:label="espanol"
sodipodi:insensitive="true"
style="display:inline"><path
id="rect2710-3"
style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke-width:0.239436"
inkscape:label="RedUp"
d="M 100.0001,0 A 100,100 0 0 0 6.3758382,65.000167 H 193.67138 A 100,100 0 0 0 100.0001,0 Z" /><path
id="rect2710-7-5"
style="fill:#ffff00;fill-opacity:1;fill-rule:nonzero;stroke-width:0.248475"
inkscape:label="Yellow"
d="M 6.3758382,65.000167 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 6.3758382,135.00003 H 193.62436 a 100,100 0 0 0 6.37584,-34.99993 100,100 0 0 0 -6.32882,-34.999933 z" /><path
id="rect2710-6-6"
style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke-width:0.239436"
inkscape:label="RedDown"
d="M 6.3758382,135.00003 A 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 193.62436,135.00003 Z" /></g></g><g
inkscape:label="Crystal"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true"><path
id="path3947"
style="fill:url(#radialGradient3957);fill-opacity:1;fill-rule:nonzero;stroke-width:0.252389"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z m 0,5.0002116 A 70,50 0 0 1 169.99996,54.999744 70,50 0 0 1 100.0001,104.99979 70,50 0 0 1 30.000236,54.999744 70,50 0 0 1 100.0001,5.0002116 Z"
inkscape:label="Sphera" /><ellipse
style="display:inline;fill:url(#linearGradient2629);fill-opacity:1;stroke-width:0.381538"
id="path1679-3"
cx="100"
cy="55"
rx="70"
ry="50"
inkscape:label="Brightness" /></g></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="flag_galego.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.7500982"
inkscape:cx="173.31064"
inkscape:cy="281.96308"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer4" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient945"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop941" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.20887271"
id="stop2636" /><stop
style="stop-color:#e5e5e5;stop-opacity:0.21659547;"
offset="0.85605043"
id="stop949" /><stop
style="stop-color:#3c3c3c;stop-opacity:0.26710457;"
offset="0.94723415"
id="stop951" /><stop
style="stop-color:#292929;stop-opacity:0.76282448;"
offset="0.99964374"
id="stop943" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient945"
id="radialGradient3957"
cx="100"
cy="100"
fx="100"
fy="100"
r="100"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2627"
id="linearGradient2629"
x1="100.74469"
y1="5.484745"
x2="100.27773"
y2="95.039955"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1666667,0,0,1.0982583,-16.66666,-0.4912933)" /><linearGradient
inkscape:collect="always"
id="linearGradient2627"><stop
style="stop-color:#ffffff;stop-opacity:0.66302198;"
offset="0"
id="stop2623" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2625" /></linearGradient></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Circled"
style="display:inline"><g
inkscape:groupmode="layer"
id="layer5-3"
inkscape:label="galego"
style="display:inline"><path
id="rect3345-6"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke-width:0.263577"
inkscape:label="Background"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z" /><path
id="path3683-0"
style="fill:#00ccff;fill-opacity:1;fill-rule:nonzero;stroke-width:0.264583"
inkscape:label="Line"
d="M 34.194812,24.791252 A 100,100 0 0 0 8.0579061,60.841764 L 165.80487,175.20894 a 100,100 0 0 0 26.13794,-36.05103 z" /></g></g><g
inkscape:label="Crystal"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true"><path
id="path3947"
style="fill:url(#radialGradient3957);fill-opacity:1;fill-rule:nonzero;stroke-width:0.252389"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z m 0,5.0002116 A 70,50 0 0 1 169.99996,54.999744 70,50 0 0 1 100.0001,104.99979 70,50 0 0 1 30.000236,54.999744 70,50 0 0 1 100.0001,5.0002116 Z"
inkscape:label="Sphera" /><ellipse
style="display:inline;fill:url(#linearGradient2629);fill-opacity:1;stroke-width:0.381538"
id="path1679-3"
cx="100"
cy="55"
rx="70"
ry="50"
inkscape:label="Brightness" /></g></svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="flag_nihongo.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.7500982"
inkscape:cx="3.9994763"
inkscape:cy="281.96308"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer4" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient945"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop941" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.20887271"
id="stop2636" /><stop
style="stop-color:#e5e5e5;stop-opacity:0.21659547;"
offset="0.85605043"
id="stop949" /><stop
style="stop-color:#3c3c3c;stop-opacity:0.26710457;"
offset="0.94723415"
id="stop951" /><stop
style="stop-color:#292929;stop-opacity:0.76282448;"
offset="0.99964374"
id="stop943" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient945"
id="radialGradient3957"
cx="100"
cy="100"
fx="100"
fy="100"
r="100"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2627"
id="linearGradient2629"
x1="100.74469"
y1="5.484745"
x2="100.27773"
y2="95.039955"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1666667,0,0,1.0982583,-16.66666,-0.4912933)" /><linearGradient
inkscape:collect="always"
id="linearGradient2627"><stop
style="stop-color:#ffffff;stop-opacity:0.66302198;"
offset="0"
id="stop2623" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2625" /></linearGradient></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Circled"
style="display:inline"><g
inkscape:groupmode="layer"
id="g2368"
inkscape:label="nihongo"
style="display:inline"><path
id="rect3689-2"
style="display:inline;fill:#ffffff;stroke-width:1.61192"
inkscape:label="Background"
d="M 100.0001 0 A 100 100 0 0 0 0 100.0001 A 100 100 0 0 0 100.0001 200.0002 A 100 100 0 0 0 200.0002 100.0001 A 100 100 0 0 0 100.0001 0 z " /><circle
style="display:inline;fill:#ff0000;stroke-width:0.274979"
id="path689-3"
cx="100"
cy="100"
r="60"
inkscape:label="Sun" /></g></g><g
inkscape:label="Crystal"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true"><path
id="path3947"
style="fill:url(#radialGradient3957);fill-opacity:1;fill-rule:nonzero;stroke-width:0.252389"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z m 0,5.0002116 A 70,50 0 0 1 169.99996,54.999744 70,50 0 0 1 100.0001,104.99979 70,50 0 0 1 30.000236,54.999744 70,50 0 0 1 100.0001,5.0002116 Z"
inkscape:label="Sphera" /><ellipse
style="display:inline;fill:url(#linearGradient2629);fill-opacity:1;stroke-width:0.381538"
id="path1679-3"
cx="100"
cy="55"
rx="70"
ry="50"
inkscape:label="Brightness" /></g></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200mm"
height="200mm"
viewBox="0 0 200 200"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09, custom)"
sodipodi:docname="flag_russkiy.svg"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.7500982"
inkscape:cx="173.31064"
inkscape:cy="281.96308"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer4" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient945"><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0"
id="stop941" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="0.20887271"
id="stop2636" /><stop
style="stop-color:#e5e5e5;stop-opacity:0.21659547;"
offset="0.85605043"
id="stop949" /><stop
style="stop-color:#3c3c3c;stop-opacity:0.26710457;"
offset="0.94723415"
id="stop951" /><stop
style="stop-color:#292929;stop-opacity:0.76282448;"
offset="0.99964374"
id="stop943" /></linearGradient><radialGradient
inkscape:collect="always"
xlink:href="#linearGradient945"
id="radialGradient3957"
cx="100"
cy="100"
fx="100"
fy="100"
r="100"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2627"
id="linearGradient2629"
x1="100.74469"
y1="5.484745"
x2="100.27773"
y2="95.039955"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1666667,0,0,1.0982583,-16.66666,-0.4912933)" /><linearGradient
inkscape:collect="always"
id="linearGradient2627"><stop
style="stop-color:#ffffff;stop-opacity:0.66302198;"
offset="0"
id="stop2623" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2625" /></linearGradient></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Circled"
style="display:inline"><g
inkscape:groupmode="layer"
id="g2379"
inkscape:label="russkiy"
style="display:inline"><path
id="rect2693-2"
style="display:inline;fill:#ffffff;stroke-width:0.296264"
inkscape:label="White"
d="M 100.0001,0 A 100,100 0 0 0 5.6761393,67.000045 H 194.3964 A 100,100 0 0 0 100.0001,0 Z" /><path
id="rect2693-6-6"
style="display:inline;fill:#ff0000;stroke-width:0.296264"
inkscape:label="Red"
d="M 5.6761393,133.00015 A 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 194.32406,133.00015 Z" /><path
id="rect2722-1"
style="display:inline;fill:#0000ff;stroke-width:0.33979"
inkscape:label="Blue"
d="M 5.6761393,67.000045 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 5.6761393,133.00015 H 194.32406 a 100,100 0 0 0 5.67614,-33.00005 100,100 0 0 0 -5.6038,-33.000055 z" /></g></g><g
inkscape:label="Crystal"
inkscape:groupmode="layer"
id="layer1"
style="display:inline"
sodipodi:insensitive="true"><path
id="path3947"
style="fill:url(#radialGradient3957);fill-opacity:1;fill-rule:nonzero;stroke-width:0.252389"
d="M 100.0001,0 A 100,100 0 0 0 0,100.0001 100,100 0 0 0 100.0001,200.0002 100,100 0 0 0 200.0002,100.0001 100,100 0 0 0 100.0001,0 Z m 0,5.0002116 A 70,50 0 0 1 169.99996,54.999744 70,50 0 0 1 100.0001,104.99979 70,50 0 0 1 30.000236,54.999744 70,50 0 0 1 100.0001,5.0002116 Z"
inkscape:label="Sphera" /><ellipse
style="display:inline;fill:url(#linearGradient2629);fill-opacity:1;stroke-width:0.381538"
id="path1679-3"
cx="100"
cy="55"
rx="70"
ry="50"
inkscape:label="Brightness" /></g></svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

52
Public/index.html Normal file
View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>AnP</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="UTF-8" />
<meta name="description" content="AnP is a very simple AI Chat Tests Application with custom dev LORaS." />
<meta name="keywords" content="AnP,AI Chat,Test,Web Application,LORaS" />
<meta name="author" content="KyMAN" />
<meta name="generator" content="KyMAN's AnP Generator" />
<meta name="application-name" content="AnP" />
<meta name="xdoc:name" content="AnP" />
<meta name="xdoc:link" content="https://anp.k3y.pw/" />
<meta name="xdoc:git" content="https://git.k3y.pw/KyMAN/AnP/" />
<meta name="xdoc:author" content="KyMAN" />
<meta name="xdoc:access" content="public" />
<style type="text/css" data-type="text/css;charset=utf-8" data-css-map="/scss/AnP.css.map" data-scss="/scss/AnP.scss" data-crossorigin="anonymous" charset="utf-8">
@import url("/scss/AnP.css");
html,body{
height : 100%;
margin: 0;
padding: 0;
}
</style>
<script type="module" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
"use strict";
import {AnP} from "./ecma/Application/AnP.ecma.js";
import {SessionsController} from "./ecma/Controllers/SessionsController.ecma.js";
import {AIChat} from "./ecma/Controllers/AIChatController.ecma.js";
/** @type {AnP} */
const anp = new AnP({
models : {
"sessions" : SessionsController,
"aichat" : AIChat
}
});
</script>
</head>
<body></body>
</html>

View File

@ -0,0 +1,28 @@
{
"autostart" : true,
"application_name" : "AnP",
"application_link" : "https://anp.k3y.pw/",
"application_git" : "https://git.k3y.pw/KyMAN/AnP",
"application_logo" : "/images/AnP.png",
"default_settings_files" : "/json/AnP.settings.json",
"default_secrets_files" : "/json/AnP.secrets.json",
"default_i18n_files" : [
"/json/i18n/AnP.i18n.english.json",
"/json/i18n/AnP.i18n.espanol.json",
"/json/i18n/AnP.i18n.galego.json",
"/json/i18n/AnP.i18n.nihongo.json",
"/json/i18n/AnP.i18n.russkiy.json"
],
"cells" : 40,
"position" : "body",
"build_base_gui" : true,
"cc_by_nc_sa_4_link" : "https://creativecommons.org/licenses/by-nc-sa/4.0/",
"cc_by_nc_sa_4_icon" : "https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png",
"i18n_selector" : [
["english", "English", "/images/flags/english.svg"],
["espanol", "Español", "/images/flags/espanol.svg"],
["galego", "Galego", "/images/flags/galego.svg"],
["nihongo", "日本語", "/images/flags/nihongo.svg"],
["russkiy", "Русский", "/images/flags/russkiy.svg"]
]
}

View File

@ -0,0 +1,19 @@
{
"english" : {
"home" : "Home",
"git" : "Git",
"user" : "User",
"ip" : "IP",
"login" : "Login",
"logout" : "Logout",
"register" : "Register",
"copyright" : "© Copyright {years} {authors}",
"cc_by_nc_sa_4" : "CC-BY-NC-SA-4.0: Creative Commons Attribution, Non-Commercial and Share Alike, version 4.0.",
"zoom" : "Zoom",
"reset_zoom" : "Reset Zoom",
"gui_mode" : "GUI Mode",
"aichat" : "AIChat",
"message" : "Message",
"send" : "Send"
}
}

View File

@ -0,0 +1,19 @@
{
"espanol" : {
"home" : "Principal",
"git" : "Git",
"user" : "Usuario",
"ip" : "IP",
"login" : "Acceder",
"logout" : "Salir",
"register" : "Registrarse",
"copyright" : "© Copyright {years} {authors}",
"cc_by_nc_sa_4" : "CC-BY-NC-SA-4.0: Creative Commons de Atribución, No Comercial y Permitido el Compartir, versión 4.0.",
"zoom" : "Zoom",
"reset_zoom" : "Reiniciar Zoom",
"gui_mode" : "Modo del GUI",
"aichat" : "AIChat",
"message" : "Mensaje",
"send" : "Enviar"
}
}

View File

@ -0,0 +1,3 @@
{
"galego" : {}
}

View File

@ -0,0 +1,3 @@
{
"nihongo" : {}
}

View File

@ -0,0 +1,3 @@
{
"russkiy" : {}
}

View File

@ -0,0 +1,25 @@
{
"login" : {
"type" : "form",
"submit" : "login@sessions",
"structure" : [
["username", "text"],
["password", "password"]
]
},
"unloggin" : {
"type" : "form",
"submit" : "logout@sessions",
"structure" : []
},
"register" : {
"type" : "form",
"submit" : "register@sessions",
"structure" : [
["username", "text"],
["password", "password"],
["confirm_password", "password"],
["email", "email"]
]
}
}

264
Public/scss/AnP.base.scss Normal file
View File

@ -0,0 +1,264 @@
@mixin main_color_web($mode){
background-color : map-deep-get($color, $mode, "back");
color : map-deep-get($color, $mode, "fore");
a[href],[data-role=link],button,[type=submit],[type=button],[type=reset],[role=button]{
color : map-deep-get($color, $mode, "primary");
&:hover{color : map-deep-get($color, $mode, "secondary");}
}
button,[type=submit],[type=button],[type=reset],[role=button]{
border-color : map-deep-get($color, $mode, "primary");
box-shadow : 0em 0em .2em inset map-deep-get($color, $mode, "primary");
&:hover{
border-color : map-deep-get($color, $mode, "secondary");
box-shadow : 0em 0em .2em inset map-deep-get($color, $mode, "secondary");
}
}
}
.anp{
position : relative;
top : 0em;
left : 0em;
width : 100%;
height : 100%;
overflow : hidden;
&,input,textarea,select,button{font-family : $font-normal;}
button,input,textarea,select{font-size : 1em;}
a[href]{text-decoration : none;}
a[href],[data-role=link],button,[type=submit],[type=button],[type=reset],[role=button]{
cursor : pointer;
transition-duration : $transition-out;
transition-property : color;
&:hover{transition-duration : $transition-in;}
}
button,[type=submit],[type=button],[type=reset],[role=button]{
cursor : pointer;
border-width : .1em;
border-style : solid;
border-radius : $border-radius;
transition-property : color, border-color, box-shadow;
}
.buttons{
text-align : center;
button{border-radius : 0em;}
&>:first-child{
border-top-left-radius : $border-radius;
border-bottom-left-radius : $border-radius;
}
&>:last-child{
border-top-right-radius : $border-radius;
border-bottom-right-radius : $border-radius;
}
}
header,main,footer{
position : absolute;
left : 0em;
width : 100%;
}
header{
display : flex;
align-items : center;
top : 0em;
height : $header-height;
z-index : 20;
}
main{
top : $header-height;
bottom : $footer-height;
z-index : 10;
}
footer{
display : flex;
align-items : center;
bottom : 0em;
height : $footer-height;
z-index : 30;
}
&[data-forced-gui-mode=default][data-gui-mode=default]{
@include main_color_web(light);
}
@each $key in (dark, light){
&[data-forced-gui-mode=#{$key}],&[data-forced-gui-mode=default][data-gui-mode=#{$key}]{
@include main_color_web($key);
}
}
.input{
display : inline-block;
position : relative;
width : 100%;
min-width : 0%;
&>textarea{
width : 100%;
height : 5em;
min-width : 0%;
min-height : 0%;
resize : none;
}
}
h1{
flex-grow : 0;
font-size : 1em;
margin : 0em;
white-space : nowrap;
a>*,.image>*{vertical-align : middle;}
img{
width : auto;
height : .8 * $header-height;
margin-top : .1 * $header-height;
margin-left : 1em + .1 * $header-height;
margin-right : .1 * $header-height;
&+span{display : none;}
}
.text{
font-size : .8 * $header-height;
font-weight : 900;
}
}
.top-menu{
flex-grow : 1;
&>ul{
margin : 0em;
padding : 0em;
text-align : center;
list-style-type : none;
li{
display : inline-block;
margin : 0em 1em;
}
}
}
.sessions-mini{
flex-grow : 0;
display : relative;
width : 3 * $header-height;
height : 100%;
.image{
position : absolute;
top : 0em;
right : 0em;
width : $header-height;
height : $header-height;
cursor : pointer;
background-color : $color-grey;
overflow : hidden;
border-radius : 0% 0% 0% 50%;
transition-duration : $transition-out;
transition-property : border-radius;
&:hover{
border-radius : 0% 0% 0% 10%;
transition-duration : $transition-in;
}
}
img{
width : auto;
height : 100%;
&+span{display : none;}
}
.info{
position : absolute;
top : .2em;
right : $header-height + .5em;
margin : 0em;
padding : 0em;
text-align : right;
list-style-type : none;
li{font-size : .85em;}
[data-icon]+[data-i18n]{display : none;}
}
nav{
position : absolute;
bottom : .5em;
right : $header-height + .5em;
text-align : right;
ul{
margin : 0em;
padding : 0em;
text-align : center;
list-style-type : none;
li{
display : inline-block;
margin : 0em .2em;
}
}
[data-icon]{
&::before{margin : 0em;}
&+[data-i18n]{display : none;}
}
}
}
.gui-controls{
flex-grow : 0;
white-space : nowrap;
[data-icon]{
&::before{margin : 0em;}
&+[data-i18n]{display : none;}
}
}
.licenses{
display : flex;
align-items : center;
flex-grow : 1;
&>*{
margin : 0em .3em;
text-align : center;
font-size : .7em;
font-weight : 900;
}
&>[data-i18n=cc_by_nc_sa_4]{
display : flex;
align-items : center;
span{flex-grow : 1;}
img{
flex-grow : 0;
width : auto;
height : $footer-height;
margin : 0em .3em;
}
}
}
.i18n-selector{
flex-grow : 0;
width : 10em;
white-space : nowrap;
ul{
position : absolute;
bottom : 0em;
right : 0em;
margin : 0em;
padding : 0em .3em;
text-align : right;
list-style-type : none;
&:hover li{
margin-top : 0em;
opacity : 1;
transition-duration : $transition-in;
}
}
li{
position : relative;
margin-top : -1em - .28em;
transition-duration : $transition-out;
transition-property : margin-top, opacity;
&>*{vertical-align : middle;}
}
[data-selected=false]{opacity : 0;}
img{
width : auto;
height : 1em;
margin-right : .3em;
}
}
}

View File

@ -0,0 +1,19 @@
// @use "sass:map";
// @use "sass:list";
// @use "sass:meta";
@function unicode($code){
@return unquote("\"") + unquote(str-insert($code, "\\", 1)) + unquote("\"");
}
@function map-deep-get($scope, $keys...){
$i : 1;
@while (type-of($scope) == map) and ($i <= length($keys)){
$scope : map-get($scope, nth($keys, $i));
$i : $i + 1;
}
@return $scope;
}

1057
Public/scss/AnP.css Normal file

File diff suppressed because it is too large Load Diff

7
Public/scss/AnP.css.map Normal file

File diff suppressed because one or more lines are too long

893
Public/scss/AnP.fonts.scss Normal file
View File

@ -0,0 +1,893 @@
@font-face {
font-family : "FA6FB";
font-style : normal;
font-weight : 400;
font-display : block;
src :
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-brands-400.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-brands-400.ttf") format("truetype");
}
@font-face {
font-family : "FA6FR";
font-style : normal;
font-weight : 400;
font-display : block;
src :
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-regular-400.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-regular-400.ttf") format("truetype");
}
@font-face {
font-family : "FA6FS";
font-style : normal;
font-weight : 900;
font-display : block;
src :
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-solid-900.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/webfonts/fa-solid-900.ttf") format("truetype");
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEz0dL_nz.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEzQdL_nz.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEzwdL_nz.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEzMdL_nz.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEz8dL_nz.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEz4dL_nz.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOiCnqEu92Fr1Mu51QrEzAdLw.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1Mu51xIIzI.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc3CsTKlA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc-CsTKlA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc2CsTKlA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc5CsTKlA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc1CsTKlA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc0CsTKlA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51S7ACc6CsQ.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc3CsTKlA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc-CsTKlA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc2CsTKlA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc5CsTKlA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc1CsTKlA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc0CsTKlA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : italic;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc6CsQ.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxFIzIFKw.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxMIzIFKw.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxEIzIFKw.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxLIzIFKw.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxHIzIFKw.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxGIzIFKw.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 100;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOkCnqEu92Fr1MmgVxIIzI.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 300;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmSU5fBBc4.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu72xKOzY.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu5mxKOzY.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7mxKOzY.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4WxKOzY.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7WxKOzY.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu7GxKOzY.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 400;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCRc4EsA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fABc4EsA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCBc4EsA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBxc4EsA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fCxc4EsA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 500;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmWUlfBBc4.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfCRc4EsA.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfABc4EsA.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfCBc4EsA.woff2") format("woff2");
unicode-range : U+1F00-1FFF;
}
/* greek */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfBxc4EsA.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfCxc4EsA.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfChc4EsA.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto";
font-style : normal;
font-weight : 900;
font-display : swap;
src : url("https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmYUtfBBc4.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm3CWWoKC.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm3mWWoKC.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm36WWoKC.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm3KWWoKC.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm3OWWoKC.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto Mono";
font-style : italic;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x7DF4xlVMF-BfR8bXMIjhOm32WWg.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhGq3-OXg.woff2") format("woff2");
unicode-range : U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhPq3-OXg.woff2") format("woff2");
unicode-range : U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhIq3-OXg.woff2") format("woff2");
unicode-range : U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhEq3-OXg.woff2") format("woff2");
unicode-range : U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhFq3-OXg.woff2") format("woff2");
unicode-range : U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face{
font-family : "Roboto Mono";
font-style : normal;
font-weight : 100 700;
font-display : swap;
src : url("https://fonts.gstatic.com/s/robotomono/v23/L0x5DF4xlVMF-BfR8bXMIjhLq38.woff2") format("woff2");
unicode-range : U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@ -0,0 +1,16 @@
.anp{
[data-icon]::before{
margin-right : .3em;
font-family : $font-icon;
}
[data-icon=home]::before{content : unicode("f015");}
[data-icon=git]::before{content : unicode("f841"); font-family : "FA6FB";}
[data-icon=user]::before{content : unicode("f007");}
[data-icon=ip]::before{content : "IP"; font-weight : 900; font-family : $font-normal;}
[data-icon=login]::before{content : unicode("f090");}
[data-icon=register]::before{content : unicode("f234");}
[data-icon=logout]::before{content : unicode("f08b");}
[data-icon=zoom]::before{content : unicode("f002");}
[data-icon=reset_zoom]::before{content : unicode("f689");}
[data-icon=gui_mode]::before{content : unicode("f043");}
}

1
Public/scss/AnP.scss Normal file
View File

@ -0,0 +1 @@
@import "AnP.fonts.scss", "AnP.settings.scss", "AnP.common.scss", "AnP.base.scss", "AnP.icons.scss";

View File

@ -0,0 +1,47 @@
// Colors
$color-fore : #222;
$color-back : #EFEFEF;
$color-primary : #2272D4;
$color-secondary : #D47222;
$color-full-fore : #000;
$color-full-back : #FFF;
$color-grey : mix($color-fore, $color-back, 50%);
$color : (
light : (
fore : $color-fore,
back : $color-back,
primary : mix($color-primary, $color-fore, 80%),
secondary : mix($color-secondary, $color-fore, 80%),
full : $color-full-back,
input-back : mix($color-back, $color-full-back, 80%),
transparent : rgba(255, 255, 255, 0)
),
dark : (
fore : $color-back,
back : $color-fore,
primary : mix($color-primary, $color-back, 80%),
secondary : mix($color-secondary, $color-back, 80%),
full : $color-full-fore,
input-back : mix($color-back, $color-full-fore, 80%),
transparent : rgba(0, 0, 0, 0)
)
);
// Sizes
$header-height : 4em;
$footer-height : 2em;
$border-radius : .3em;
$margin : .5em;
// Fonts
// $font-normal : Arial, Helvetica, Sans;
// $font-mono : Consolas, "Courier New", Courier, monospace;
// $font-icon : Arial, Helvetica, Sans;
$font-normal : "Roboto";
$font-mono : "Roboto Mono";
$font-icon : "FA6FS";
// Transitions
$transition-in : .35s;
$transition-out : 1s;
$transition : .5s;

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any, Optional, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
from Abstracts.ModelAbstract import ModelAbstract
class ControllerAbstract(ModelAbstract):
def __init__(self:Self,
anp:AnPInterface,
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
) -> None:
self.anp:AnPInterface = anp

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any, Optional, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
from Abstracts.ModelAbstract import ModelAbstract
class DispatchAbstract(ModelAbstract):
def __init__(self:Self,
anp:AnPInterface,
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
) -> None:
self.anp:AnPInterface = anp

View File

@ -0,0 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class ModelAbstract:pass

View File

@ -0,0 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class RouteAbstract:pass

148
Python/Application/AnP.py Normal file
View File

@ -0,0 +1,148 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any, Optional, Sequence
import datetime
from re import Match as REMatch
from traceback import extract_tb as extract_traceback, format_stack as trace_format_stack
from Managers.I18NManager import I18NManager
from Managers.SettingsManager import SettingsManager
from Managers.PrintTypesManager import PrintTypesManager
from Managers.TerminalManager import TerminalManager
from Managers.ModelsManager import ModelsManager
from Managers.ControllersManager import ControllersManager
from Managers.DispatchesManager import DispatchesManager
from Managers.IndexesManager import IndexesManager
from Managers.RoutesManager import RoutesManager
from Drivers.HTTPDriver import HTTPDriver
from Utils.Common import Common
from Utils.Patterns import RE
class AnP:
def __own_update(self:Self) -> None:
self.__end_print_types = [
print_type.upper() for print_type in Common.get_keys(self.settings.get("end_print_types", None, self.__end_print_types))
]
self.__root_projects_paths = Common.get_texts(self.settings.get("root_projects_paths", None, self.__root_projects_paths))
self.__print_format = self.settings.get("print_format", None, self.__print_format)
self.__exception_format = self.settings.get("exception_format", None, self.__exception_format)
def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
self.__working:bool = True
self.settings:SettingsManager = SettingsManager(self, inputs)
self.i18n:I18NManager = I18NManager(self)
self.print_types:PrintTypesManager = PrintTypesManager(self)
self.__end_print_types:list[str] = ["UNKN", "EXCE", "ERRO"]
self.__root_projects_paths:list[str] = []
self.__print_format:str = "[{type}] {yyyy}{mm}{dd} {hh}{ii}{ss} [{line}]{file}({method}): {message}"
self.__exception_format:str = " '[{line}]{file}({method})'{lines}\n\n{exception_message}"
self.__own_update()
self.terminal:TerminalManager = TerminalManager(self)
self.models:ModelsManager = ModelsManager(self)
self.controllers:ControllersManager = ControllersManager(self)
self.dispatches:DispatchesManager = DispatchesManager(self)
self.indexes:IndexesManager = IndexesManager(self)
self.routes:RoutesManager = RoutesManager(self)
self.http_server:HTTPDriver = HTTPDriver(self)
def update(self:Self) -> None:
self.settings.update()
self.i18n.update()
self.print_types.update()
self.__own_update()
self.terminal.update()
self.models.update()
self.controllers.update()
self.dispatches.update()
self.indexes.update()
self.routes.update()
self.http_server.update()
def reset(self:Self) -> None:
self.settings.reset()
self.i18n.reset()
self.print_types.reset()
self.__own_update()
self.terminal.reset()
self.models.reset()
self.controllers.reset()
self.dispatches.reset()
self.indexes.reset()
self.routes.reset()
self.http_server.reset()
def close(self:Self) -> None:
self.__working = False
self.http_server.close()
def working(self:Self) -> bool:
return self.__working
def print(self:Self,
_type:str,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:
date:datetime.datetime = datetime.datetime.now()
own:dict[str, Any] = {
"raw_type" : _type,
"type": self.print_types.get(_type),
"message": self.i18n.get(message, inputs),
**Common.get_dictionary(inputs),
**Common.get_action_data(i + 1)
}
for key in ("year", "month", "day", "hour", "minute", "second"):
k:str = "i" if key == "minute" else key[0]
own[k] = own[key] = getattr(date, key)
own[k + k] = ("00" + str(own[key]))[-2:]
own["yyyy"] = ("0000" + str(own["year"]))[-4:]
for root_path in self.__root_projects_paths:
if own["file"].startswith(root_path):
own["file"] = own["file"][len(root_path):]
break
if any(own["type"].startswith(end_type) for end_type in self.__end_print_types) and "end" in own:
own["message"] += own["end"]
print(Common.string_variables(self.__print_format, own))
def exception(self:Self,
exception:Exception,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:
lines:list[str] = extract_traceback(exception.__traceback__).format()
matches:REMatch = RE.EXCEPTION.match(lines[-1])
data:dict[str, Any|None] = {
**Common.get_dictionary(inputs),
"lines" : "",
"exception_message" : str(exception),
"method" : matches.group(3),
"line" : matches.group(2),
"file" : matches.group(1)
}
block:str
j:int
for root_path in self.__root_projects_paths:
if data["file"] and data["file"].startswith(root_path):
data["file"] = data["file"][len(root_path):]
for j, block in enumerate(trace_format_stack()[:-2] + lines):
if block:
data["lines"] += "\n " + str(j) + " - " + RE.NEW_LINE.split(block.strip())[0]
data["end"] = Common.string_variables(self.__exception_format, data)
message and self.print("exception", message, data, i + 2)

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Callable, Any, Optional
class Event:
def __init__(self:Self) -> None:
self.__events:dict[int, Callable[[Optional[Any]], Any|None]] = {}
def execute(self:Self, *inputs:Any|None) -> None:
results:dict[int, Any|None] = {}
for i, event in self.__events.items():
results[i] = event(*inputs)
return results
def add(self:Self, event:Callable[[Optional[Any]], Any|None]) -> int:
i:int = 0
l:int = len(self.__events)
while i < l:
if i not in self.__events:
break
i += 1
self.__events[i] = event
return i
def remove(self:Self, i:int) -> None:
if i in self.__events:
del self.__events[i]

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self
from Abstracts.ModelAbstract import ModelAbstract
from Interfaces.Application.AnPInterface import AnPInterface
from Models.RequestModel import RequestModel
class AIController(ModelAbstract):
def __init__(self:Self, anp:AnPInterface) -> None:
self.anp: AnPInterface = anp
def new_message(self:Self, request:RequestModel) -> None:
pass

View File

@ -0,0 +1,131 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Self, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
from Models.RequestModel import RequestModel
from Utils.Common import Common
from threading import Thread
from http.server import BaseHTTPRequestHandler, HTTPServer
class HTTPDriver:
class HTTPRequestHandler(BaseHTTPRequestHandler):
def __process(self:Self, method:str) -> None:
anp:AnPInterface = self.server.anp
request:RequestModel = RequestModel()
request.method = method
request.path = self.path
request.headers = dict(self.headers)
request.client_host = self.client_address[0]
request.client_port = self.client_address[1]
anp.routes.go(method, self.path, request)
self.send_response(request.response_code)
self.send_header("Content-Type", request.response_mime)
self.send_header("Content-Length", str(len(request.response)))
self.end_headers()
self.wfile.write(
request.response.encode() if isinstance(request.response, str) else
request.response)
def do_GET(self:Self) -> None:
self.__process("get")
def do_POST(self:Self) -> None:
self.__process("post")
def do_PUT(self:Self) -> None:
self.__process("put")
def do_DELETE(self:Self) -> None:
self.__process("delete")
def do_PATCH(self:Self) -> None:
self.__process("patch")
def do_HEAD(self:Self) -> None:
self.__process("head")
def do_OPTIONS(self:Self) -> None:
self.__process("options")
def do_CONNECT(self:Self) -> None:
self.__process("connect")
def do_TRACE(self:Self) -> None:
self.__process("trace")
def do_COPY(self:Self) -> None:
self.__process("copy")
def do_MOVE(self:Self) -> None:
self.__process("move")
def do_PROPFIND(self:Self) -> None:
self.__process("propfind")
def do_PROPPATCH(self:Self) -> None:
self.__process("proppatch")
def do_LOCK(self:Self) -> None:
self.__process("lock")
def do_UNLOCK(self:Self) -> None:
self.__process("unlock")
def do_REPORT(self:Self) -> None:
self.__process("report")
def do_MKCOL(self:Self) -> None:
self.__process("mkcol")
def __init__(self:Self,
anp:AnPInterface,
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
) -> None:
self.anp:AnPInterface = anp
self.__inputs:dict[str, Any|None] = Common.get_dictionary(inputs)
self.__port:int = 8000
self.__host:str = ""
self.__server:HTTPServer|None = None
self.__thread:Thread|None = None
self.update()
def start(self:Self) -> None:
if self.__server is None:
self.__thread = Thread(target = self.__run_service)
self.__thread.start()
def close(self:Self) -> None:
if self.__server is not None:
self.__server.shutdown()
self.__server = None
def update(self:Self) -> None:
self.close()
self.__port = self.anp.settings.get(("http_server_port", "http_port", "port"), self.__inputs, self.__port)
self.__host = self.anp.settings.get(("http_server_host", "http_host", "host"), self.__inputs, self.__host)
self.start()
def reset(self:Self) -> None:
self.__port = 8000
self.__host = ""
self.update()
def __run_service(self:Self) -> None:
self.__server = HTTPServer((self.__host, self.__port), self.HTTPRequestHandler)
self.__server.anp = self.anp
self.__server.serve_forever()

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Self, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
class OllamaDriver:
def __init__(self:Self,
anp:AnPInterface,
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
) -> None:
self.anp:AnPInterface = anp

View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self, Sequence, Optional
from websockets.sync.server import serve as server_serve
from websockets import ServerConnection as WebSocketServer, ClientConnection as WebSocketClient
from Application.Event import Event
from Interfaces.Application.AnPInterface import AnPInterface
class WebSocketServerDriver:
def __init__(self:Self, anp:AnPInterface, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
self.anp:AnPInterface = anp
self.on_new_client:Event = Event()
self.on_message:Event = Event()
self.on_close:Event = Event()
self.on_error:Event = Event()
self.__server:WebSocketServer
self.__clients:dict[str, WebSocketClient] = {}
self.__host:str = anp.settings.get(("web_socket_server_host", "host"), inputs, "")
self.__port:int = anp.settings.get(("web_socket_server_port", "port"), inputs, 8765)
with server_serve(self.__handler, self.__host, self.__port) as self.__server:
self.__server.serve_forever()
def close(self:Self) -> None:
id:str
for id in tuple(self.__clients.keys()):
self.close_client(id)
self.__server.close()
def close_client(self:Self, id:str, show_exception:bool = True) -> None:
if id in self.__clients:
try:
self.__clients[id].close()
except Exception as exception:
show_exception and self.anp.exception(exception, "web_socket_server_client_close_exception", {
"client": id,
"port": self.__port,
"host": self.__host
})
del self.__clients[id]
def __handler(self:Self, client:WebSocketClient) -> None:
id:str = str(id(client))
self.__clients[id] = client
self.on_new_client.execute(client, id)
self.anp.print("info", "web_socket_server_client_connected", {
"client": id,
"port": self.__port,
"host": self.__host,
"client_host" : client.remote_address[0],
"client_port" : client.remote_address[1]
})
try:
while self.anp.working():
message:str = client.recv()
if message is None:
break
self.on_message.execute(client, message)
except Exception as exception:
self.anp.exception(exception, "web_socket_server_client_exception", {
"client": id,
"port": self.__port,
"host": self.__host
})
self.on_error.execute(client, exception)
finally:
self.close_client(id, False)
self.on_close.execute(client)
self.anp.print("info", "web_socket_server_client_disconnected", {
"client": id,
"port": self.__port,
"host": self.__host
})

View File

@ -0,0 +1,55 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Sequence, Self
from abc import ABC, abstractmethod
from Interfaces.Managers.SettingsManagerInterface import SettingsManagerInterface
from Interfaces.Managers.I18NManagerInterface import I18NManagerInterface
from Interfaces.Managers.PrintTypesManagerInterface import PrintTypesManagerInterface
from Interfaces.Managers.TerminalManagerInterface import TerminalManagerInterface
from Interfaces.Managers.ModelsManagerInterface import ModelsManagerInterface
from Interfaces.Managers.ControllersManagerInterface import ControllersManagerInterface
from Interfaces.Managers.DispatchesManagerInterface import DispatchesManagerInterface
from Interfaces.Managers.IndexesManagerInterface import IndexesManagerInterface
from Interfaces.Managers.RoutesManagerInterface import RoutesManagerInterface
class AnPInterface(ABC):
def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
self.settings:SettingsManagerInterface = None
self.i18n:I18NManagerInterface = None
self.print_types:PrintTypesManagerInterface = None
self.terminal:TerminalManagerInterface = None
self.models:ModelsManagerInterface = None
self.controllers:ControllersManagerInterface = None
self.dispatches:DispatchesManagerInterface = None
self.indexes:IndexesManagerInterface = None
self.routes:RoutesManagerInterface = None
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def close(self:Self) -> None:pass
@abstractmethod
def working(self:Self) -> bool:pass
@abstractmethod
def print(self:Self,
_type:str,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:pass
@abstractmethod
def exception(self:Self,
exception:Exception,
message:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
i:int = 0
) -> None:pass

View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self
from abc import ABC, abstractmethod
from Models.RequestModel import RequestModel
class ControllersManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass
@abstractmethod
def execute(self:Self, key:str, method:str, request:RequestModel) -> bool:pass

View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self
from abc import ABC, abstractmethod
class DispatchesManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass
@abstractmethod
def execute(self:Self, key:str, method:str, *arguments:list[Any|None]) -> bool:pass

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Self, Sequence
from abc import ABC, abstractmethod
class I18NManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def get(self:Self,
keys:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
custom_language:Optional[Any] = None
) -> Any|None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass

View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any
from abc import ABC, abstractmethod
class IndexesManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def add(self:Self, inputs:Any|None) -> None:pass
@abstractmethod
def get(self:Self) -> list[str]:pass

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any, Sequence, TypeVar
from abc import ABC, abstractmethod
T = TypeVar("T")
class ModelsManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def get(self:Self, Type:type[T], keys:str|Sequence[str]) -> T|None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass

View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self, Sequence
from abc import ABC, abstractmethod
class PrintTypesManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def get(self:Self, keys:str|Sequence[str]) -> str:pass
@abstractmethod
def add(self:Self, inputs:Any|None) -> None:pass

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any
from abc import ABC, abstractmethod
from Models.RequestModel import RequestModel
class RoutesManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def go(self:Self, method:str, path:str, request:RequestModel) -> None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass

View File

@ -0,0 +1,26 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Self, Sequence
from abc import ABC, abstractmethod
class SettingsManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def get(self:Self,
keys:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
default:Optional[Any] = None
) -> Any|None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass
@abstractmethod
def add_secret(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any
from abc import ABC, abstractmethod
class TerminalManagerInterface(ABC):
@abstractmethod
def update(self:Self) -> None:pass
@abstractmethod
def reset(self:Self) -> None:pass
@abstractmethod
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:pass

View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
from Abstracts.ControllerAbstract import ControllerAbstract
from Models.RequestModel import RequestModel
from Utils.Common import Common
from Utils.Checks import Check
class ControllersManager:
def __init__(self:Self, anp:AnPInterface) -> None:
self.anp:AnPInterface = anp
self.__controllers:dict[str, ControllerAbstract] = {}
self.update()
def update(self:Self) -> None:
key:str
for key in ("default_controllers_files", "controllers_files", "default_controllers", "controllers"):
self.add(self.anp.settings.get(key), True)
def reset(self:Self) -> None:
self.__controllers = {}
self.update()
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:
subinputs:dict[str, Any|None]
for subinputs in Common.load_json(inputs, True):
for key, controller in subinputs.items():
if Common.is_mark_key(key) and controller is None:
continue
ControllerClass:type[ControllerAbstract]|None
if Check.is_string(controller):
ControllerClass = self.anp.models.get(ControllerAbstract, controller)
elif issubclass(controller, ControllerAbstract):
ControllerClass = controller
elif Check.is_dictionary(controller) and "type" in controller and Check.is_string(controller["type"]):
ControllerClass = self.anp.models.get(ControllerAbstract, controller["type"])
else:
continue
if ControllerClass and (
overwrite or key not in self.__controllers
):
self.__controllers[key] = ControllerClass(
self.anp, controller if Check.is_dictionary(controller) else
None)
def execute(self:Self, key:str, method:str, request:RequestModel) -> bool:
if key in self.__controllers and hasattr(self.__controllers[key], method):
getattr(self.__controllers[key], method)(request)
return True
return False

View File

@ -0,0 +1,63 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Self
from Interfaces.Application.AnPInterface import AnPInterface
from Abstracts.DispatchAbstract import DispatchAbstract
from Utils.Common import Common
from Utils.Checks import Check
class DispatchesManager:
def __init__(self:Self, anp:AnPInterface) -> None:
self.anp:AnPInterface = anp
self.__dispatches:dict[str, DispatchAbstract] = {}
self.update()
def update(self:Self) -> None:
key:str
for key in ("default_dispatches_files", "dispatches_files", "default_dispatches", "dispatches"):
self.add(self.anp.settings.get(key), True)
def reset(self:Self) -> None:
self.__dispatches = {}
self.update()
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:
subinputs:dict[str, Any|None]
for subinputs in Common.load_json(inputs, True):
for key, dispatch in subinputs.items():
if Common.is_mark_key(key) and dispatch is None:
continue
DispatchClass:type[DispatchAbstract]|None
if Check.is_string(dispatch):
DispatchClass = self.anp.models.get(DispatchAbstract, dispatch)
elif issubclass(dispatch, DispatchAbstract):
DispatchClass = dispatch
elif Check.is_dictionary(dispatch) and "type" in dispatch and Check.is_string(dispatch["type"]):
DispatchClass = self.anp.models.get(DispatchAbstract, dispatch["type"])
else:
continue
if DispatchClass and (
overwrite or key not in self.__dispatches
):
self.__dispatches[key] = DispatchClass(
self.anp, dispatch if Check.is_dictionary(dispatch) else
None)
def execute(self:Self, key:str, method:str, *arguments:list[Any|None]) -> bool:
if key in self.__dispatches and hasattr(self.__dispatches[key], method):
getattr(self.__dispatches[key], method)(*arguments)
return True
return False

View File

@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Any, Optional, Self, Sequence
from Interfaces.Application.AnPInterface import AnPInterface
from Utils.Checks import Check
from Utils.Common import Common
class I18NManager:
def __init__(self:Self, anp:AnPInterface) -> None:
self.anp:AnPInterface = anp
self.__sentences:dict[str, dict[str, str|list[str]]] = {
"english" : {}
}
self.__default_language:str = list(self.__sentences.keys())[0]
self.__language:str = self.__default_language
self.update()
def update(self:Self) -> None:
key:str
for key in ("default_i18n_files", "i18n_files", "default_i18n", "i18n"):
self.add(self.anp.settings.get(key), True)
self.__default_language = self.anp.settings.get("language", None, self.__default_language)
self.__language = self.anp.settings.get("language", None, self.__language)
def reset(self:Self) -> None:
self.__sentences = {
"english" : {}
}
self.__default_language = list(self.__sentences.keys())[0]
self.__language = self.__default_language
self.update()
def __get_sentence(self:Self, texts:str|Sequence[str], custom_language:Optional[str] = None) -> str|list[str]|None:
keys:list[str] = Common.get_keys(texts)
if len(keys) != 0:
language:str
done:list[str] = []
for language in (custom_language, self.__language, self.__default_language) + tuple(self.__sentences.keys()):
if language not in done and language in self.__sentences:
key:str
done.append(language)
for key in keys:
if key in self.__sentences[language]:
return self.__sentences[language][key]
return (
(texts[0] if len(texts) > 0 else None) if Check.is_array(texts) else
texts if Check.is_string(texts) else
None)
def get(self:Self,
keys:str|Sequence[str],
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None,
custom_language:Optional[Any] = None
) -> Any|None:
text:str|list[str]|None = self.__get_sentence(keys, custom_language)
return Common.string_variables((
text if Check.is_string(text) else
"".join(text) if Check.is_array(text) else
""), inputs)
def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None:
subinputs:dict[str, Any|None]
for subinputs in Common.load_json(inputs, True):
language:str
sentences:dict[str, str|list[str]]
for language, sentences in subinputs.items():
key:str
sentence:str|list[str]
if language not in self.__sentences:
self.__sentences[language] = {}
for key, sentence in sentences.items():
if Common.is_mark_key(key) and sentence is None:
continue
if overwrite or key not in self.__sentences[language]:
self.__sentences[language][key] = sentence

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Self, Any
from Interfaces.Application.AnPInterface import AnPInterface
from Utils.Checks import Check
class IndexesManager:
def __init__(self:Self, anp:AnPInterface) -> None:
self.anp:AnPInterface = anp
self.__indexes:list[str] = []
self.update()
def update(self:Self) -> None:
key:str
for key in ("default_indexes", "indexes"):
self.add(self.anp.settings.get(key))
def reset(self:Self) -> None:
self.__indexes = []
self.update()
def add(self:Self, inputs:Any|None) -> None:
if Check.is_array(inputs):
item:Any|None
for item in inputs:
self.add(item)
elif (
Check.is_string(inputs) and
(inputs := inputs.strip()) and
inputs not in self.__indexes
):
self.__indexes.append(inputs)
def get(self:Self) -> list[str]:
return [*self.__indexes]

Some files were not shown because too many files have changed in this diff Show More