feat(go|ecma|scss): Fixed some errors, added some modules and mixed some projects.

This commit is contained in:
KyMAN 2025-05-05 06:28:53 +02:00
parent 05749df1bc
commit 685c67240e
34 changed files with 621 additions and 296 deletions

BIN
Bin/AnP.0.0.3.go.linux.386 Executable file

Binary file not shown.

BIN
Bin/AnP.0.0.3.go.linux.arm32 Executable file

Binary file not shown.

BIN
Bin/AnP.0.0.3.go.linux.arm64 Executable file

Binary file not shown.

BIN
Bin/AnP.0.0.3.go.windows.386.exe Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -8,13 +8,12 @@ import (
"mime"
"net/http"
"strconv"
"strings"
)
type HTTPDriver struct {
anp Models.AnPModel
host string
port int16
port int
server *http.Server
listener func(writer http.ResponseWriter, request *http.Request)
autorun bool
@ -28,9 +27,9 @@ func NewHTTPDriver(anp Models.AnPModel, inputs any) *HTTPDriver {
host: Utils.Get(anp.Settings.Get([]string{
"http_driver_host", "http_host", "host",
}, inputs, Utils.GetPointer[any]("")), Utils.GetPointer("")),
port: Utils.Get(anp.Settings.Get([]string{
port: int(Utils.Get(anp.Settings.Get([]string{
"http_driver_port", "http_port", "port",
}, inputs, Utils.GetPointer[any](8080)), Utils.GetPointer[int16](8080)),
}, inputs, Utils.GetPointer[any](28080)), Utils.GetPointer[float64](38080))),
listener: Utils.Get[func(writer http.ResponseWriter, request *http.Request)](anp.Settings.Get([]string{
"http_driver_listener", "http_listener", "listener",
}, inputs, nil), nil),
@ -39,6 +38,8 @@ func NewHTTPDriver(anp Models.AnPModel, inputs any) *HTTPDriver {
}, inputs, Utils.GetPointer[any](true)), Utils.GetPointer(true)),
}
Models.DebugPrint(server.host, ":", server.port)
if server.listener == nil {
server.listener = server.listen
}
@ -52,7 +53,7 @@ func NewHTTPDriver(anp Models.AnPModel, inputs any) *HTTPDriver {
func (_self HTTPDriver) listen(writer http.ResponseWriter, request *http.Request) {
var response map[string]any = _self.anp.Applications.Go(request.Host, strings.ToLower(request.Method), request.RequestURI)
var response map[string]any = _self.anp.Applications.Go(Models.NewRequestModel(request))
var response_bytes []byte = []byte{}
if response["response"] != nil {
@ -65,6 +66,14 @@ func (_self HTTPDriver) listen(writer http.ResponseWriter, request *http.Request
}
writer.Header().Set("Content-Type", Utils.Get[string](response["mime"], nil))
if options, exists := response["options"]; exists {
switch headers := options.(type) {
case map[string]any:
for key, value := range headers {
writer.Header().Set(key, Utils.ToString(value))
}
}
}
writer.WriteHeader(Utils.Get[int](response["code"], nil))
writer.Write(response_bytes)

View File

@ -47,6 +47,8 @@ func NewURLPathDriver(anp Models.AnPModel) URLPathDriver {
}
Models.DebugPrint(driver.root_paths)
return driver
}
@ -72,9 +74,15 @@ func (_self URLPathDriver) FixPath(path string) string {
return Utils.Patterns.RE_SLASH.ReplaceAllString(path, _self.slash)
}
func (_self URLPathDriver) GetAbsolutePath(path string) string {
func (_self URLPathDriver) GetAbsolutePath(path string, roots []string) string {
for _, root := range _self.root_paths {
if roots == nil {
roots = _self.root_paths
} else {
roots = append(roots, _self.root_paths...)
}
for _, root := range roots {
var full_path string = root
@ -95,14 +103,14 @@ func (_self URLPathDriver) GetAbsolutePath(path string) string {
func (_self URLPathDriver) LoadFile(path string) string {
data, _ := os.ReadFile(_self.GetAbsolutePath(path))
data, _ := os.ReadFile(_self.GetAbsolutePath(path, nil))
return string(data)
}
func (_self URLPathDriver) LoadBinaryFile(path string) []byte {
data, _ := os.ReadFile(_self.GetAbsolutePath(path))
data, _ := os.ReadFile(_self.GetAbsolutePath(path, nil))
return data
}

View File

@ -1,5 +1,5 @@
package Interfaces
type ApplicationsInterface interface {
Go(domain string, method string, url string) map[string]any
Go(request_interface RequestModelInterface) map[string]any
}

View File

@ -0,0 +1,6 @@
package Interfaces
type RequestModelInterface interface {
ToJSON(header string) string
ToJSONItem(header string) map[string]string
}

View File

@ -2,5 +2,5 @@ package Interfaces
type RoutesInterface interface {
// Add(inputs any, overwrite bool)
Go(domain string, method string, url string, settings map[string]any) (map[string]any, bool)
Go(request_interface RequestModelInterface, settings map[string]any, paths []string) (map[string]any, bool)
}

View File

@ -2,7 +2,7 @@ package Interfaces
type URLPathInterface interface {
FixPath(path string) string
GetAbsolutePath(path string) string
GetAbsolutePath(path string, roots []string) string
LoadFile(path string) string
LoadBinaryFile(path string) []byte
LoadJSON(inputs any, callback func(any), only_dictionaries bool)

View File

@ -1,6 +1,7 @@
package Managers
import (
"AnP/Interfaces"
"AnP/Models"
"AnP/Utils"
)
@ -38,13 +39,13 @@ func (_self *ApplicationsManager) Add(inputs any, overwrite bool) {
}, true)
}
func (_self ApplicationsManager) Go(domain string, method string, url string) map[string]any {
func (_self ApplicationsManager) Go(request Interfaces.RequestModelInterface) map[string]any {
var response map[string]any = GetDefaultHTTPResponse()
var done bool
for _, application := range _self.applications {
if response, done = application.Routes.Go(domain, method, url, application.GetAttributes()); done {
if response, done = application.Routes.Go(request, application.GetAttributes(), application.Paths); done {
break
}
}

View File

@ -2,6 +2,7 @@ package Managers
import (
"AnP/Drivers"
"AnP/Interfaces"
"AnP/Models"
"AnP/Modules"
"AnP/Utils"
@ -16,6 +17,7 @@ type RoutesManager struct {
routes []Models.RoutesModel
indexes []string
wmarkdown_html_file string
alternative_domains map[string]string
}
var default_indexes []string = []string{"index.w.md", "index.md", "index.html", "index.htm"}
@ -30,6 +32,8 @@ func GetDefaultHTTPResponse() map[string]any {
func NewRoutesManager(anp Models.AnPModel, inputs any) RoutesManager {
var options map[string]map[string]any = nil
var alternative_domains map[string]any = Utils.Get[map[string]any](anp.Settings.Get("alternative_domains", inputs, nil), nil)
var manager RoutesManager = RoutesManager{
anp: anp,
domains: Utils.GetStrings(anp.Settings.Get([]string{
@ -40,20 +44,45 @@ func NewRoutesManager(anp Models.AnPModel, inputs any) RoutesManager {
routes: []Models.RoutesModel{},
indexes: Utils.GetStrings(anp.Settings.Get([]string{}, inputs, Utils.GetPointer[any](default_indexes))),
wmarkdown_html_file: Utils.Get(anp.Settings.Get("wmarkdown_html", inputs, Utils.GetPointer[any](default_wmarkdown_html)), &default_wmarkdown_html),
alternative_domains: nil,
}
if alternative_domains != nil {
manager.alternative_domains = map[string]string{}
for domain, pattern := range alternative_domains {
manager.alternative_domains[domain] = Utils.Get[string](pattern, nil)
}
}
switch value := anp.Settings.Get([]string{"options", "route_options", "routes_options"}, inputs, nil).(type) {
case map[string]any:
for key, value := range value {
switch subvalue := value.(type) {
case map[string]any:
if options == nil {
options = map[string]map[string]any{
key: {},
}
}
for header_key, header_value := range subvalue {
options[key][header_key] = header_value
}
}
}
}
for _, key := range []string{"default_routes_files", "default_routes", "routes_files", "routes"} {
manager.Add(anp.Settings.Get(key, inputs, nil), true)
manager.Add(anp.Settings.Get(key, inputs, nil), true, options)
}
return manager
}
func (_self *RoutesManager) Add(inputs any, overwrite bool) {
func (_self *RoutesManager) Add(inputs any, overwrite bool, options map[string]map[string]any) {
switch group := inputs.(type) {
case string:
var route Models.RoutesModel = Models.NewRoutesModel(group)
var route Models.RoutesModel = Models.NewRoutesModel(group, options)
if route.Ok {
@ -80,13 +109,13 @@ func (_self *RoutesManager) Add(inputs any, overwrite bool) {
} else {
_self.anp.Request.LoadJSON(group, func(data any) {
_self.Add(data, overwrite)
_self.Add(data, overwrite, options)
}, false)
}
case []any:
for _, subinputs := range group {
_self.Add(subinputs, overwrite)
_self.Add(subinputs, overwrite, options)
}
}
}
@ -107,19 +136,34 @@ func (_self RoutesManager) StringVariables(_string string, inputs any) string {
})
}
func (_self RoutesManager) Go(domain string, method string, url string, settings map[string]any) (map[string]any, bool) {
func (_self RoutesManager) GetOwnFullPath(subpath string, roots []string) (string, bool) {
var full_path string = subpath
var exists bool = Drivers.FileExists(full_path)
if !exists && roots != nil {
full_path = _self.anp.Request.GetAbsolutePath(subpath, roots)
exists = Drivers.FileExists(full_path)
}
return full_path, exists
}
func (_self RoutesManager) Go(request_interface Interfaces.RequestModelInterface, settings map[string]any, paths []string) (map[string]any, bool) {
var response map[string]any = GetDefaultHTTPResponse()
var done bool = false
var request Models.RequestModel = request_interface.(Models.RequestModel)
if slices.Contains(_self.domains, domain) || slices.Contains(_self.domains, "") {
if slices.Contains(_self.domains, request.Domain) || slices.Contains(_self.domains, "") {
var code int = 404
response["code"] = 404
done = true
for _, route := range _self.routes {
var matches Utils.PatternMatch = Utils.Patterns.Match(url, route.URL)
var matches Utils.PatternMatch = Utils.Patterns.Match(request.URL, route.URL)
if matches.Ok {
@ -130,45 +174,52 @@ func (_self RoutesManager) Go(domain string, method string, url string, settings
case string:
var slash string = _self.anp.Request.GetSlash()
var full_path string
var exists bool
subpath = route.Path + slash + subpath
var full_path string = _self.anp.Request.GetAbsolutePath(subpath)
var ok bool = Drivers.FileExists(full_path)
if !ok {
if full_path, exists = _self.GetOwnFullPath(subpath, paths); !exists {
for _, index := range _self.indexes {
var temporary_path string = _self.anp.Request.GetAbsolutePath(subpath + slash + index)
ok = Drivers.FileExists(temporary_path)
if ok {
full_path = temporary_path
if full_path, exists = _self.GetOwnFullPath(subpath+slash+index, paths); exists {
break
}
}
}
if ok {
if exists {
if full_path[len(full_path)-3:] == ".md" {
html, subvariables := _self.anp.WMarkDown.Process(_self.anp.Request.LoadFile(full_path), Modules.WMD.HTML, full_path)
var last_date_modified time.Time = *Drivers.LastDateModified(full_path)
var html_file string
var request_domain string = "k3y.pw"
if html_file, exists = _self.GetOwnFullPath(_self.wmarkdown_html_file, paths); !exists {
html_file, exists = _self.GetOwnFullPath(default_wmarkdown_html, paths)
}
if _self.alternative_domains != nil {
for domain, pattern := range _self.alternative_domains {
if request.Domain[len(request.Domain)-len(pattern):] == pattern {
request_domain = domain
break
}
}
}
variables["contents"] = html
variables["version"] = last_date_modified.Format("20060102")
variables["request_domain"] = request_domain
maps.Copy(variables, settings)
for key, value := range subvariables {
variables[key] = value
}
response["ok"] = true
response["code"] = 200
code = 200
response["mime"] = "text/html;charset=" + variables["charset"].(string)
response["response"] = _self.StringVariables(_self.anp.Request.LoadFile(_self.wmarkdown_html_file), variables)
response["response"] = _self.StringVariables(_self.anp.Request.LoadFile(html_file), variables)
} else {
@ -176,7 +227,7 @@ func (_self RoutesManager) Go(domain string, method string, url string, settings
var data []byte = _self.anp.Request.LoadBinaryFile(full_path)
response["ok"] = true
response["code"] = 200
code = 200
response["mime"] = mime_type
if mime_type[:5] == "text/" {
response["response"] = string(data)
@ -188,15 +239,21 @@ func (_self RoutesManager) Go(domain string, method string, url string, settings
}
default:
response["code"] = 501
code = 501
}
} else if route.Type == Models.RouteTypeView {
response["code"] = 503
code = 503
} else if route.Type == Models.RouteTypeController {
response["code"] = 503
code = 503
} else {
response["code"] = 500
code = 500
}
response["code"] = code
if route.Options != nil && (code >= 200 && code < 300) || slices.Contains([]int{301, 302, 304}, code) {
response["options"] = route.Options
}
}
}

View File

@ -7,11 +7,15 @@ import (
var default_settings map[string]any = map[string]any{
"default_settings_files": []any{
"/Public/json/AnP.settings.json",
"/JSON/AnP.settings.json",
"/Public/json/AnP.go.settings.json",
"/JSON/AnP.go.settings.json",
"AnP.go.settings.json",
},
"default_secrets_files": []any{
"/Public/json/AnP.secrets.json",
"/JSON/AnP.secrets.json",
"/Public/json/AnP.go.secrets.json",
"/JSON/AnP.go.secrets.json",
"AnP.go.secrets.json",

View File

@ -12,6 +12,7 @@ type ApplicationModel struct {
anp AnPModel
Attributes map[string]any
Routes Interfaces.RoutesInterface
Paths []string
}
func SetClasses(classes []string) string {
@ -44,24 +45,28 @@ func NewApplicationModel(anp AnPModel, routes Interfaces.RoutesInterface, inputs
}
for key, keys := range map[string][]string{
"git": {"application_git", "git"},
"project": {"application_name", "name", "project"},
"web": {"application_link", "application_url", "application_web", "link", "url", "web"},
"logo": {"application_logo", "logo"},
"snake": {"application_snake", "snake"},
"git": {"application_git", "git"},
"project": {"application_name", "name", "project"},
"web": {"application_link", "application_url", "application_web", "link", "url", "web"},
"logo": {"application_logo", "logo"},
"logo_light": {"application_logo_light", "logo_light", "application_logo", "logo"},
"logo_dark": {"application_logo_dark", "logo_dark", "application_logo", "logo"},
"snake": {"application_snake", "snake"},
} {
attributes[key] = Utils.GetValue[string](keys, inputs, nil)
}
switch logo := attributes["logo"].(type) {
case []string, []any:
attributes["logo_sources"] = logo
case string, any:
attributes["logo_sources"] = []any{logo}
default:
attributes["logo_sources"] = []any{}
for _, key := range []string{"", "_light", "_dark"} {
switch logo := attributes["logo"+key].(type) {
case []string, []any:
attributes["logo"+key+"_sources"] = logo
case string, any:
attributes["logo"+key+"_sources"] = []any{logo}
default:
attributes["logo"+key+"_sources"] = []any{}
}
attributes["logo"+key+"_sources"] = Utils.VariablesEncode(attributes["logo"+key+"_sources"])
}
attributes["logo_sources"] = Utils.VariablesEncode(attributes["logo_sources"])
for key, keys := range map[string][][]string{
"charset": {{"charset"}, {"utf-8"}},
@ -107,6 +112,7 @@ func NewApplicationModel(anp AnPModel, routes Interfaces.RoutesInterface, inputs
anp: anp,
Attributes: attributes,
Routes: routes,
Paths: Utils.GetStrings(Utils.GetValue[any]([]string{"path", "paths"}, inputs, nil)),
}
}

37
Go/Models/RequestModel.go Normal file
View File

@ -0,0 +1,37 @@
package Models
import (
"AnP/Utils"
"net/http"
"strings"
)
type RequestModel struct {
Domain string
Method string
URL string
}
func NewRequestModel(request *http.Request) RequestModel {
return RequestModel{
Domain: request.Host,
Method: strings.ToLower(request.Method),
URL: request.RequestURI,
}
}
func (_self RequestModel) ToJSON(header string) string {
return Utils.JSONEncode(map[string]any{
header + "domain": _self.Domain,
header + "method": _self.Method,
header + "url": _self.URL,
})
}
func (_self RequestModel) ToJSONItem(header string) map[string]string {
return map[string]string{
header + "domain": _self.Domain,
header + "method": _self.Method,
header + "url": _self.URL,
}
}

View File

@ -23,21 +23,24 @@ type RoutesModel struct {
Variables []string
Permissions []string
Type int
Options map[string]any
}
func NewRoutesModel(pattern string) RoutesModel {
func NewRoutesModel(pattern string, options map[string]map[string]any) RoutesModel {
var matches Utils.PatternMatch = Utils.Patterns.Match(pattern, Utils.Patterns.RE_ROUTE)
var route RoutesModel = RoutesModel{
Ok: matches.Ok,
Ok: matches.Ok,
Options: nil,
}
if matches.Ok {
// RE_ROUTE: all, method?, route, (method, controller | view | path), permissions?, options?
var pattern string
route.Variables = []string{}
pattern = `(?i)^` + Utils.Patterns.Replace(matches.Groups[3], Utils.Patterns.RE_ROUTES_FORMAT, func(matches Utils.PatternMatch) string {
pattern = `(?i)^` + Utils.Patterns.Replace(matches.Groups[2], Utils.Patterns.RE_ROUTES_FORMAT, func(matches Utils.PatternMatch) string {
if matches.Groups[1] != "" {
route.Variables = append(route.Variables, matches.Groups[1])
@ -47,21 +50,33 @@ func NewRoutesModel(pattern string) RoutesModel {
return `\` + matches.Groups[2]
})
if matches.Groups[8] != "" {
if matches.Groups[6] != "" {
route.Variables = append(route.Variables, "path")
pattern += `(.*)$`
} else {
pattern += `$`
}
route.Method = strings.ToLower(matches.Groups[2])
route.Method = strings.ToLower(matches.Groups[1])
route.URL = regexp.MustCompile(pattern)
// 5 - 6 == Controller - Method
route.View = matches.Groups[7]
route.Path = matches.Groups[8]
// 3 - 4 == Controller - Method
route.View = matches.Groups[5]
route.Path = matches.Groups[6]
if matches.Groups[10] != "" {
route.Permissions = strings.Split(matches.Groups[10], ",")
if matches.Groups[7] != "" {
route.Permissions = strings.Split(matches.Groups[7], ",")
}
if matches.Groups[8] != "" {
route.Options = map[string]any{}
for _, key := range strings.Split(matches.Groups[8], ",") {
if headers, exists := options[key]; exists {
for key, value := range headers {
if _, exists := route.Options[key]; !exists {
route.Options[key] = value
}
}
}
}
}
if route.Path != "" {

View File

@ -33,7 +33,7 @@ var Patterns PatternsModel = PatternsModel{
RE_KEY: regexp.MustCompile(`(?i)^[a-z0-9_]+$`),
RE_PASCAL_KEY: regexp.MustCompile(`(?i)^[a-z0-9_\-]+$`),
RE_STRING_VARIABLES: regexp.MustCompile(`(?i)\{([a-z0-9_]+)\}`),
RE_ROUTE: regexp.MustCompile(`(?i)^(([^\:]+)\:)?([^ ]+) +(([^ \:]+)\:([^ ]+)|([a-z0-9_]+)|([^ ]+))( +([^\s]+))?$`),
RE_ROUTE: regexp.MustCompile(`(?i)^(?:([^\:]+)\:)?([^ ]+) +(?:([^ \:]+)\:([^ ]+)|([a-z0-9_]+)|([^ ]+))(?: +(?:\*|([^\s]+))(?: ([^\s]+)))?$`),
RE_ROUTES_FORMAT: regexp.MustCompile(`(?i)\{([a-z0-9_]+)\}|([\\\/\-\{\[\]\}\\(\)\*\^\|\!\?\+\.\:\$])`),
RE_TRACE_STACK: regexp.MustCompile(`[\n\r](([^\.\(\s]+|\..)+)\([^\n\r]+[\r\n]+\s+([^\:\s]+)\:([0-9]+)`),
RE_EXTENSION: regexp.MustCompile(`\.([^\.\/\\]+)$`),
@ -42,6 +42,10 @@ var Patterns PatternsModel = PatternsModel{
RE_SPACES: regexp.MustCompile(` +`),
}
/*
RE_ROUTE: all, method?, route, (method, controller | view | path), permissions?, options?
*/
func (_self *PatternsModel) GetMatches(_string string, groups [][]byte) PatternMatch {
var binary []byte = []byte(_string)

View File

@ -0,0 +1,9 @@
{
"routes_options" : {
"cors" : {
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Methods" : "GET, POST, OPTIONS",
"Access-Control-Allow-Headers" : "Content-type"
}
}
}

View File

@ -32,6 +32,9 @@ export const AnPLoader = (function(){
/** @type {AnPLoader} */
const self = this;
/** @type {string} */
this.domain = /^[^\:]+\:\/{2}[^\/]+\.([lg]ocal|anprm(\.[lg]ocal)?)\/?/i.test(window.location.href) ? "local" : "k3y.pw";
/**
* @returns {void}
* @access private
@ -42,11 +45,16 @@ export const AnPLoader = (function(){
let i = 0;
/** @type {anp_loader_default_callback} */
const end = () => {
++ i == 2 && AnPLoader.execute(callback);
};
++ i == 2 && AnPLoader.execute(callback, self);
},
/** @type {Object.<string, any|null>} */
options = {
domain : self.domain = AnPLoader.get_value("domain", inputs, self.domain),
name : AnPLoader.get_value("name", inputs, "AnP")
};
AnPLoader.styles_loader(AnPLoader.get_list_strings(AnPLoader.get_value(["style", "styles"], inputs)), end);
AnPLoader.scripts_loader(AnPLoader.get_list_strings(AnPLoader.get_value(["script", "scripts"], inputs)), end);
AnPLoader.styles_loader(AnPLoader.get_list_strings(AnPLoader.get_value(["style", "styles"], inputs)), end, options);
AnPLoader.scripts_loader(AnPLoader.get_list_strings(AnPLoader.get_value(["script", "scripts"], inputs)), end, options);
};
@ -54,9 +62,6 @@ export const AnPLoader = (function(){
};
/** @type {string} */
AnPLoader.DOMAIN = /^[^\:]+\:\/{2}[^\/]+\.([lg]ocal|anprm(\.[lg]ocal)?)\/?/i.test(window.location.href) ? "local" : "k3y.pw";
/**
* @param {?any} item
* @returns {boolean}
@ -105,6 +110,18 @@ export const AnPLoader = (function(){
*/
AnPLoader.get_array = item => AnPLoader.is_array(item) ? item : [item];
/**
* @param {?any} item
* @param {!boolean} [overwrite = false]
* @returns {Object.<string, any|null>}
* @access public
* @static
*/
AnPLoader.get_dictionary = (item, overwrite = false) => AnPLoader.get_array(item).reduce((dictionary, subitem) => {
AnPLoader.is_array(subitem) && (subitem = AnPLoader.get_dictionary(subitem, overwrite));
return AnPLoader.is_dictionary(subitem) ? overwrite ? {...dictionary, ...subitem} : {...subitem, ...dictionary} : dictionary;
}, {});
/**
* @param {!(string|Array.<string>)} keys
* @returns {Array.<string>}
@ -170,12 +187,13 @@ export const AnPLoader = (function(){
/**
* @param {!Array.<Array.<string>>} scripts
* @param {?anp_loader_default_callback} [callback = null]
* @param {?(Object.<string, any|null>|Array.<any|null>)} [options = null]
* @param {!number} [i = 0]
* @returns {void}
* @access public
* @static
*/
AnPLoader.scripts_loader = (scripts, callback = null, i = 0) => {
AnPLoader.scripts_loader = (scripts, callback = null, options = null, i = 0) => {
if(i == scripts.length){
AnPLoader.execute(callback);
return;
@ -187,7 +205,7 @@ export const AnPLoader = (function(){
const l = scripts[i].length,
/** @type {anp_loader_default_callback} */
end = () => {
++ loaded == l && AnPLoader.scripts_loader(scripts, callback, i + 1);
++ loaded == l && AnPLoader.scripts_loader(scripts, callback, options, i + 1);
},
/** @type {HTMLHeadElement} */
head = document.querySelector("head");
@ -198,6 +216,8 @@ export const AnPLoader = (function(){
/** @type {HTMLScriptElement} */
const item = head.appendChild(document.createElement("script"));
options && (script = AnPLoader.string_variables(script, options));
["load", "error"].forEach(key => {
item.addEventListener(key, event => {
end();
@ -219,12 +239,13 @@ export const AnPLoader = (function(){
/**
* @param {!Array.<Array.<string>>} styles
* @param {?anp_loader_default_callback} [callback = null]
* @param {?(Object.<string, any|null>|Array.<any|null>)} [options = null]
* @param {!number} [i = 0]
* @returns {void}
* @access public
* @static
*/
AnPLoader.styles_loader = (styles, callback = null, i = 0) => {
AnPLoader.styles_loader = (styles, callback = null, options = null, i = 0) => {
if(i == styles.length){
AnPLoader.execute(callback);
return;
@ -236,7 +257,7 @@ export const AnPLoader = (function(){
const l = styles[i].length,
/** @type {anp_loader_default_callback} */
end = () => {
++ loaded == l && AnPLoader.styles_loader(styles, callback, i + 1);
++ loaded == l && AnPLoader.styles_loader(styles, callback, options, i + 1);
},
/** @type {HTMLHeadElement} */
head = document.querySelector("head");
@ -249,6 +270,8 @@ export const AnPLoader = (function(){
/** @type {boolean} */
is_sass = style.slice(-5).toLowerCase() == ".scss";
options && (style = AnPLoader.string_variables(style, options));
["load", "error"].forEach(key => {
item.addEventListener(key, event => {
end();
@ -278,5 +301,23 @@ export const AnPLoader = (function(){
};
/**
* @param {!string} string
* @param {!(Object.<string, any|null>|Array.<any|null>)} variables
* @param {?any} [_default = null]
* @returns {string}
* @access public
* @static
*/
AnPLoader.string_variables = (string, variables, _default = null) => {
variables = AnPLoader.get_dictionary(variables);
return ("" + string).replace(/\{([a-z0-9_]+)\}/ig, (all, key) => (
variables[key] !== undefined ? variables[key] :
_default !== null && _default !== undefined ? _default :
all));
};
return AnPLoader;
})();

View File

@ -4,6 +4,7 @@ import {Utils} from "../Utils/Utils.ecma.js";
import {Check} from "../Utils/Check.ecma.js";
import {Attributes} from "./Attributes.ecma.js";
import {LicensesComponent} from "../Components/LicensesComponent.ecma.js";
import {FormsComponent} from "../Components/FormsComponent.ecma.js";
import {BaseComponent} from "../Components/BaseComponent.ecma.js";
/**
@ -49,7 +50,8 @@ export const Components = (function(){
[
["licenses", LicensesComponent],
["base", BaseComponent]
["base", BaseComponent],
["forms", FormsComponent]
].forEach(([name, Class]) => {
if(Class){
self[name + "_component"] = new Class(anp);
@ -99,7 +101,7 @@ export const Components = (function(){
});
Utils.execute_items([
"licenses", "base"
"licenses", "base", "forms"
], (key, next) => {
self[key + "_component"].start(ok => {
next();

View File

@ -0,0 +1,77 @@
"use strict";
/**
* @typedef {import("../Application/AnP.ecma.js").AnP} AnP
*/
/**
* @class
* @constructor
* @param {!AnP} anp
* @returns {void}
* @access public
*/
export const FormsComponent = (function(){
/**
* @constructs BaseComponent
* @param {!AnP} anp
* @returns {void}
* @access private
*/
const FormsComponent = function(anp){
/** @type {FormsComponent} */
const self = this;
/** @type {boolean} */
let started = false;
/**
* @returns {void}
* @access private
*/
const constructor = () => {};
/**
* @param {?anp_start_callback} callback
* @returns {boolean}
* @access public
*/
this.start = (callback = null) => {
/** @type {!anp_start_callback} */
const end = ok => {
Utils.execute(callback, ok);
return ok;
};
if(started)
return end(false);
return end(started = true);
};
/**
* @param {!(Object.<string, any|null>|Array.<any|null>)} inputs
* @returns {string}
* @access public
*/
this.build = inputs => {
return anp.comp.set(["form", {}, [
["fieldset", null, [
["legend", null, "LEGEND"],
["p", null, "PARAGRAPH"],
["div", {class : "structure"}, Utils.get_value("structure", inputs, []).reduce((structure, item) => {
return structure;
}, [])],
["ul", {class : "errors"}],
anp.comp.buttons()
]]
]]);
};
constructor();
};
return FormsComponent;
})();

View File

@ -1,4 +1,9 @@
{
"default_settings_files" : "/Public/json/AnP.go.settings.json",
"default_settings_files" : [
"/Public/json/AnP.settings.json",
"/JSON/AnP.settings.json",
"/Public/json/AnP.go.settings.json",
"/JSON/AnP.go.settings.json"
],
"test" : "xD"
}

View File

@ -0,0 +1,223 @@
@mixin main_color_web($mode){
background-color : map-deep-get($color, $mode, "back");
color : map-deep-get($color, $mode, fore);
&,button,input,select,textarea{color : map-deep-get($color, $mode, fore);}
button,input,select,textarea{background-color : map-deep-get($color, $mode, input-back);}
[role=link],[data-role=link],a[href]{
&[disabled]{color : map-deep-get($color, grey);}
&[readonly]{color : map-deep-get($color, $mode, fore);}
&:not([disabled],[readonly]){
color : map-deep-get($color, $mode, primary);
&:hover{color : map-deep-get($color, $mode, secondary);}
}
}
[role=button],[data-role=button],button,[type=button],[type=submit],[type=reset]{
&[disabled]{
border-color : map-deep-get($color, grey);
color : map-deep-get($color, grey);
box-shadow : 0em 0em .4em inset map-deep-get($color, grey);
}
&[readonly]{
border-color : map-deep-get($color, $mode, fore);
color : map-deep-get($color, $mode, fore);
box-shadow : 0em 0em .4em inset map-deep-get($color, grey);
}
&:not([disabled],[readonly]){
border-color : map-deep-get($color, $mode, primary);
color : mix(map-deep-get($color, $mode, primary), map-deep-get($color, $mode, fore), 50%);
box-shadow : 0em 0em .4em inset map-deep-get($color, $mode, primary);
&:hover{
border-color : map-deep-get($color, $mode, secondary);
color : mix(map-deep-get($color, $mode, secondary), map-deep-get($color, $mode, fore), 50%);
box-shadow : 0em 0em .4em inset map-deep-get($color, $mode, secondary);
}
}
}
header,footer{box-shadow :
0em 0em 1em map-deep-get($color, $mode, back),
0em 0em 1.25em map-deep-get($color, $mode, back),
0em 0em 1.5em map-deep-get($color, $mode, back),
0em 0em 2em map-deep-get($color, $mode, back);
}
}
@mixin main_web($reverse:false){
position : relative;
top : 0em;
left : 0em;
width : 100%;
height : 100%;
overflow : hidden;
&,button,input,select{font-family : $font-normal;}
textarea,pre{font-family : $font-mono;}
button,input,select,textarea{font-size : 1em;}
[data-icon]::before{
margin-right : .4em;
font-family : $font-icon;
}
a[href]{text-decoration : none;}
[role=link],[role=button],[data-role=link],[data-role=button],a[href],button,[type=button],[type=submit],[type=reset]{&:not([disabled],[readonly]){
cursor : pointer;
transition-duration : $transition-out;
transition-property : color;
&:hover{transition-duration : $transition-in;}
}}
[role=button],[data-role=button],button,[type=button],[type=submit],[type=reset],[type=text],[type=number],[type=date],[type=password],textarea{
padding : .1em .4em;
border-width : .1em;
border-style : solid;
border-color : map-deep-get($color, grey);
border-radius : $border-radius;
box-shadow : 0em 0em .4em inset map-deep-get($color, grey);
}
button,[type=button],[type=submit],[type=reset]{&:not([disabled],[readonly]){
transition-property : color,border-color,background-color,box-shadow;
}}
.group{
&>*{&,&>*{border-radius : 0em;}}
&>:first-child{&,&>:first-child{border-radius : $border-radius 0em 0em $border-radius;}}
&>:last-child{&,&>:last-child{border-radius : 0em $border-radius $border-radius 0em;}}
}
[data-visible=false]{display : none;}
header,main,footer{
position : absolute;
left : 0em;
width : 100%;
}
header{
top : 0em;
height : $header-height;
z-index : 20;
overflow : visible;
}
main{
top : $header-height;
bottom : $footer-height;
z-index : 10;
overflow : auto;
}
footer{
display : flex;
flex-direction : row;
justify-items : center;
bottom : 0em;
height : $footer-height;
z-index : 30;
overflow : visible;
}
@each $key, $option in (dark : true, light : false){
&[data-gui-mode=#{$key}],&[data-gui-mode=default][data-dark-mode=#{$option}]{
@include main_color_web($key);
}
}
&[data-gui-mode=light],&[data-gui-mode=default][data-dark-mode=false]{header>h1{
[data-type=dark]{opacity : 0;}
[data-type=light]{opacity : 1;}
}}
&[data-gui-mode=dark],&[data-gui-mode=default][data-dark-mode=true]{header>h1{
[data-type=dark]{opacity : 1;}
[data-type=light]{opacity : 0;}
}}
h1{
margin : .2em .5em;
padding : 0em;
font-size : 1em;
font-weight : 900;
img{
width : auto;
height : 3.6em;
&+span{display : none;}
}
a>span{vertical-align : middle;}
&,.image{
display : inline-block;
position : relative;
transition-duration : $transition;
transition-property : opacity;
&+.image{
position : absolute;
top : 0em;
left : 0em;
}
}
.text{
margin-left : .2em;
font-size : 3.6em;
}
}
.main-menu{
padding-bottom : .4em;
vertical-align : bottom;
&,ul,li{display : inline-block;}
ul{
margin : 0em;
padding : 0em;
list-style-type : none;
}
li{margin : 0em 1em;}
}
.licenses{
display : flex;
flex-direction : row;
justify-items : center;
align-items : center;
width : 100%;
font-weight : 100;
text-align : center;
img{
width : auto;
height : 1.8em;
}
&>span{
margin : 0em .3em;
vertical-align : middle;
}
.text{font-size : .7em;}
}
.copyright{font-size : .7em;}
.cc-by-nc-sa-4,.gplv3{
display : flex;
flex-direction : row;
justify-items : center;
align-items : center;
&>span{margin : 0em .3em;}
}
.gui-controls{
margin : .2em .5em;
padding : 0em;
border : none;
white-space : nowrap;
font-size : .85em;
&>*{&,&>*{border-radius : 0em;}}
&{&>[data-i18n=less_zoom],.input-number,&>[data-i18n=more_zoom],&>[data-i18n=reset_zoom]{display : none;}}
button[data-i18n=zoom_mode]{&,&>:first-child{border-radius : $border-radius 0em 0em $border-radius;}}
&>:last-child{&,&>:last-child{border-radius : 0em $border-radius $border-radius 0em;}}
legend{display : none;}
[data-icon]{
&::before{margin : 0em;}
&+[data-i18n]{display : none;}
};
}
.wmd-main-menu-button{
position : absolute;
bottom : 0em;
right : 0em;
}
}

View File

@ -1,6 +1,6 @@
@use "sass:map";
@use "sass:list";
@use "sass:meta";
// @use "sass:map";
// @use "sass:list";
// @use "sass:meta";
@function unicode($code){
@return unquote("\"") + unquote(str-insert($code, "\\", 1)) + unquote("\"");
@ -16,204 +16,4 @@
}
@return $scope;
}
@mixin main_color_web($mode){
background-color : map-deep-get($color, $mode, "back");
color : map-deep-get($color, $mode, fore);
&,button,input,select,textarea{color : map-deep-get($color, $mode, fore);}
button,input,select,textarea{background-color : map-deep-get($color, $mode, input-back);}
[role=link],[data-role=link],a[href]{
&[disabled]{color : map-deep-get($color, common, grey);}
&[readonly]{color : map-deep-get($color, $mode, fore);}
&:not([disabled],[readonly]){
color : map-deep-get($color, $mode, primary);
&:hover{color : map-deep-get($color, $mode, secondary);}
}
}
[role=button],[data-role=button],button,[type=button],[type=submit],[type=reset]{
&[disabled]{
border-color : map-deep-get($color, common, grey);
color : map-deep-get($color, common, grey);
box-shadow : 0em 0em .4em inset map-deep-get($color, common, grey);
}
&[readonly]{
border-color : map-deep-get($color, $mode, fore);
color : map-deep-get($color, $mode, fore);
box-shadow : 0em 0em .4em inset map-deep-get($color, common, grey);
}
&:not([disabled],[readonly]){
border-color : map-deep-get($color, $mode, primary);
color : mix(map-deep-get($color, $mode, primary), map-deep-get($color, $mode, fore), 50%);
box-shadow : 0em 0em .4em inset map-deep-get($color, $mode, primary);
&:hover{
border-color : map-deep-get($color, $mode, secondary);
color : mix(map-deep-get($color, $mode, secondary), map-deep-get($color, $mode, fore), 50%);
box-shadow : 0em 0em .4em inset map-deep-get($color, $mode, secondary);
}
}
}
}
@mixin main_web($reverse:false){
position : relative;
top : 0em;
left : 0em;
width : 100%;
height : 100%;
overflow : hidden;
&,button,input,select{font-family : $font-normal;}
textarea,pre{font-family : $font-mono;}
button,input,select,textarea{font-size : 1em;}
[data-icon]::before{
margin-right : .4em;
font-family : $font-icon;
}
a[href]{text-decoration : none;}
[role=link],[role=button],[data-role=link],[data-role=button],a[href],button,[type=button],[type=submit],[type=reset]{&:not([disabled],[readonly]){
cursor : pointer;
transition-duration : $transition-out;
transition-property : color;
&:hover{transition-duration : $transition-in;}
}}
[role=button],[data-role=button],button,[type=button],[type=submit],[type=reset],[type=text],[type=number],[type=date],[type=password],textarea{
padding : .1em .4em;
border-width : .1em;
border-style : solid;
border-color : map-deep-get($color, common, grey);
border-radius : $border-radius;
box-shadow : 0em 0em .4em inset map-deep-get($color, common, grey);
}
button,[type=button],[type=submit],[type=reset]{&:not([disabled],[readonly]){
transition-property : color,border-color,background-color,box-shadow;
}}
.group{
&>*{&,&>*{border-radius : 0em;}}
&>:first-child{&,&>:first-child{border-radius : $border-radius 0em 0em $border-radius;}}
&>:last-child{&,&>:last-child{border-radius : 0em $border-radius $border-radius 0em;}}
}
[data-visible=false]{display : none;}
header,main,footer{
position : absolute;
left : 0em;
width : 100%;
}
header{
top : 0em;
height : $header-height;
z-index : 20;
overflow : visible;
}
main{
top : $header-height;
bottom : $footer-height;
z-index : 10;
overflow : auto;
}
footer{
display : flex;
flex-direction : row;
justify-items : center;
bottom : 0em;
height : $footer-height;
z-index : 30;
overflow : visible;
}
@each $key, $option in (dark : true, light : false){
&[data-gui-mode=#{$key}],&[data-gui-mode=default][data-dark-mode=#{$option}]{
@include main_color_web($key);
}
}
h1{
margin : .2em .5em;
padding : 0em;
font-size : 1em;
font-weight : 900;
img{
width : auto;
height : 3.6em;
&+span{display : none;}
}
a>span{vertical-align : middle;}
&,.image{display : inline-block;}
.text{
margin-left : .2em;
font-size : 3.6em;
}
}
.main-menu{
padding-bottom : .4em;
vertical-align : bottom;
&,ul,li{display : inline-block;}
ul{
margin : 0em;
padding : 0em;
list-style-type : none;
}
li{margin : 0em 1em;}
}
.licenses{
display : flex;
flex-direction : row;
justify-items : center;
align-items : center;
width : 100%;
font-weight : 100;
text-align : center;
img{
width : auto;
height : 1.8em;
}
&>span{
margin : 0em .3em;
vertical-align : middle;
}
.text{font-size : .7em;}
}
.copyright{font-size : .7em;}
.cc-by-nc-sa-4,.gplv3{
display : flex;
flex-direction : row;
justify-items : center;
align-items : center;
&>span{margin : 0em .3em;}
}
.gui-controls{
margin : .2em .5em;
padding : 0em;
border : none;
white-space : nowrap;
font-size : .85em;
&>*{&,&>*{border-radius : 0em;}}
&{&>[data-i18n=less_zoom],.input-number,&>[data-i18n=more_zoom],&>[data-i18n=reset_zoom]{display : none;}}
button[data-i18n=zoom_mode]{&,&>:first-child{border-radius : $border-radius 0em 0em $border-radius;}}
&>:last-child{&,&>:last-child{border-radius : 0em $border-radius $border-radius 0em;}}
legend{display : none;}
[data-icon]{
&::before{margin : 0em;}
&+[data-i18n]{display : none;}
};
}
.wmd-main-menu-button{
position : absolute;
bottom : 0em;
right : 0em;
}
}

View File

@ -10,7 +10,7 @@
"web" : "f0ac",
"menu" : "f0c9"
){
[data-icon=#{$name}]::before{content : unicode($code);}
[data-icon=#{$name}]::before{content : unicode($code); font-family : "FA6FS";}
}
@each $name, $code in (
@ -30,7 +30,7 @@
"dark" : "f3fb",
"light" : "f009",
){
&[data-gui-mode=#{$mode}] [data-icon=gui_mode]::before{content : unicode($code);}
&[data-gui-mode=#{$mode}] [data-icon=gui_mode]::before{content : unicode($code); font-family : "FA6FS";}
}
}

View File

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

View File

@ -9,18 +9,20 @@ $color : (
back : $color-back,
primary : $color-primary,
secondary : $color-secondary,
input-back : mix($color-back, #FFF, 80%)
input-back : mix($color-back, #FFF, 80%),
transparent : rgba(255, 255, 255, 0),
full : #FFF
),
dark : (
fore : $color-back,
back : $color-fore,
primary : mix($color-primary, $color-fore, 80%),
secondary : mix($color-secondary, $color-fore, 80%),
input-back : mix($color-fore, #000, 80%)
primary : mix($color-primary, $color-back, 90%),
secondary : mix($color-secondary, $color-back, 90%),
input-back : mix($color-back, #000, 15%),
transparent : rgba(0, 0, 0, 0),
full : #000
),
common : (
grey : mix($color-fore, $color-back, 50%)
)
grey : mix($color-fore, $color-back, 50%)
);
// Sizes.

12
Tools/compile.all.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
directory=`dirname $(readlink -f "$0")`
version=$(cat $directory/../version)
cd $directory/../Go
GOOS=linux GOARCH=386 go build -o $directory/../Bin/AnP.$version.go.linux.386 Main/Server/Main.go
GOOS=linux GOARCH=amd64 go build -o $directory/../Bin/AnP.$version.go.linux.amd64 Main/Server/Main.go
GOOS=linux GOARCH=arm go build -o $directory/../Bin/AnP.$version.go.linux.arm32 Main/Server/Main.go
GOOS=linux GOARCH=arm64 go build -o $directory/../Bin/AnP.$version.go.linux.arm64 Main/Server/Main.go
GOOS=windows GOARCH=386 go build -o $directory/../Bin/AnP.$version.go.windows.386.exe Main/Server/Main.go
GOOS=windows GOARCH=amd64 go build -o $directory/../Bin/AnP.$version.go.windows.amd64.exe Main/Server/Main.go
GOOS=windows GOARCH=arm go build -o $directory/../Bin/AnP.$version.go.windows.arm32.exe Main/Server/Main.go
cd $directory/../Tools

7
Tools/compile.linux.amd64.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
directory=`dirname $(readlink -f "$0")`
version=$(cat $directory/../version)
cd $directory/../Go
rm $directory/../Bin/AnP.$version.go.linux.amd64
GOOS=linux GOARCH=amd64 go build -o $directory/../Bin/AnP.$version.go.linux.amd64 Main/Server/Main.go
cd $directory/../Tools

View File

@ -1 +1 @@
0.0.2
0.0.3