From 64237712f9525ca309c136e93ea2ea5fb9eedf45 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Sun, 29 May 2022 18:16:54 +0300 Subject: [PATCH] scrollbar app remaked with cgi backend --- backend/.gitignore | 2 + backend/Makefile | 30 +++++ backend/config.mk | 26 ++++ backend/src/main.c | 86 +++++++++++++ backend/src/query.c | 70 ++++++++++ backend/src/query.h | 46 +++++++ backend/src/routes.c | 70 ++++++++++ backend/src/routes.h | 74 +++++++++++ backend/src/server.h | 30 +++++ backend/src/template.c | 60 +++++++++ backend/src/template.h | 35 +++++ backend/src/utils.c | 35 +++++ backend/src/utils.h | 24 ++++ src/pages/index.scm | 1 + src/pages/webapps/scrollbar.scm | 90 ++++++++++--- src/scripts/webapps/scrollbar.js | 212 ++++++------------------------- src/styles/webapps/scrollbar.scm | 31 +---- src/templates/clean.scm | 17 ++- src/templates/default.scm | 12 +- 19 files changed, 720 insertions(+), 231 deletions(-) create mode 100644 backend/.gitignore create mode 100644 backend/Makefile create mode 100644 backend/config.mk create mode 100644 backend/src/main.c create mode 100644 backend/src/query.c create mode 100644 backend/src/query.h create mode 100644 backend/src/routes.c create mode 100644 backend/src/routes.h create mode 100644 backend/src/server.h create mode 100644 backend/src/template.c create mode 100644 backend/src/template.h create mode 100644 backend/src/utils.c create mode 100644 backend/src/utils.h diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..caa3563 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,2 @@ +*.o +*cgi diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 0000000..3ffd432 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,30 @@ +# Copyright (C) 2022 Ivan Polyakov +# +# This file is part of vilor's website. +# +# Vilor's website is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Vilor's website is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +include config.mk + +all: wwwvilorcgi + +wwwvilorcgi: query.o template.o routes.o utils.o main.o + $(CC) $^ -o $@ $(LDFLAGS) + +%.o: src/%.c + $(CC) $(CFLAGS) $^ -c -fPIC + +clean: + rm -f *.o wwwvilorcgi + +.PHONY: all clean diff --git a/backend/config.mk b/backend/config.mk new file mode 100644 index 0000000..c42a695 --- /dev/null +++ b/backend/config.mk @@ -0,0 +1,26 @@ +# Copyright (C) 2022 Ivan Polyakov +# +# This file is part of vilor's website. +# +# Vilor's website is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Vilor's website is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +CC=cc +CFLAGS=-ansi -pedantic +LDFLAGS=-lfcgi + +DEBUG= +ifdef DEBUG + CFLAGS+=-Wall -g -DDEBUG_MODE +else + CFLAGS+=-O3 +endif diff --git a/backend/src/main.c b/backend/src/main.c new file mode 100644 index 0000000..eeaf557 --- /dev/null +++ b/backend/src/main.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include "server.h" +#include "routes.h" +#include "utils.h" + +static int socketId; + +static int send_response(FCGX_Request *req, struct route *route) +{ + char resbuff[FBUFFSZ]; + + memset(resbuff, '\0', FBUFFSZ); + + if (route->resh(route, req, resbuff)) { + fputs("Can't create response\n", stderr); + return 2; + } + + /* sending response */ + FCGX_PutS("Content-type: text/html" CRLF CRLF, req->out); + FCGX_PutS(resbuff, req->out); + FCGX_PutS(CRLF CRLF, req->out); + + return 0; +} + +int main() +{ + FCGX_Request req; + + FCGX_Init(); + + if ((socketId = FCGX_OpenSocket(SOCKET_PATH, 20)) < 0) { + return 1; + } + + if (FCGX_InitRequest(&req, socketId, 0)) { + fputs("Can't init request\n", stderr); + return 2; + } + + while (1) { + int rc; + struct route *route; + + rc = FCGX_Accept_r(&req); + + if (rc < 0) { + fputs("Can't accept new request\n", stderr); + break; + } + + if (!(route = find_route(&req))) { + fputs("Invalid URI\n", stderr); + continue; + } + + send_response(&req, route); + + FCGX_Finish_r(&req); + } + + return 0; +} diff --git a/backend/src/query.c b/backend/src/query.c new file mode 100644 index 0000000..bbe12dc --- /dev/null +++ b/backend/src/query.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include "query.h" +#include "utils.h" +#include +#include + +void read_params(char *query, struct param *params) +{ + struct param *param = NULL; + + query = strtok(query, PARAM_DEL); + while (query) { + if ((param = find_param_by_key(params, query))) { + size_t valsz = 0; + + if (!(query = strtok(NULL, PARAM_DEL))) { + break; + } + + valsz = strlen(query) + 1; + if (valsz <= MAX_PARAMVAL_SZ) { + memcpy(param->val, query, valsz); + strreplace(param->val, "%23", "#"); + } + } + + query = strtok(NULL, PARAM_DEL); + } +} + +struct param *find_param_by_key(struct param *params, const char *key) +{ + int i = 0; + + while (params[i].key) { + if (!strcmp(key, params[i].key)) { + return ¶ms[i]; + } + + i++; + } + + return NULL; +} + +void reset_params(struct param *params) +{ + int i = 0; + while (params[i].key) { + strcpy(params[i].val, params[i].defaultval); + i++; + } +} diff --git a/backend/src/query.h b/backend/src/query.h new file mode 100644 index 0000000..4274d2e --- /dev/null +++ b/backend/src/query.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef QUERY_H_ENTRY +#define QUERY_H_ENTRY + +#ifdef __cplusplus +extern "C" { +#endif + +#define PARAM_DEL "&=" +#define PARAM_BUFFSZ 100 +#define MAX_PARAMVAL_SZ 10 + +struct param { + const char *key; + char *defaultval; + char val[MAX_PARAMVAL_SZ]; +}; + +struct param *find_param_by_key(struct param *params, const char *key); + +void read_params(char *query, struct param *params); + +void reset_params(struct param *params); + +#ifdef __cplusplus +}; +#endif + +#endif /* QUERY_H_ENTRY */ diff --git a/backend/src/routes.c b/backend/src/routes.c new file mode 100644 index 0000000..764b5ec --- /dev/null +++ b/backend/src/routes.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include "routes.h" +#include "server.h" +#include "template.h" +#include +#include + +int res_scrollbar(struct route *route, FCGX_Request *req, char buff[FBUFFSZ]) +{ + char fpath[ROUTESZ]; + + sprintf(fpath, "%s%s", STATIC_PATH, route->uri); + + read_params(FCGX_GetParam("QUERY_STRING", req->envp), route->params); + + if (rendertpl(fpath, buff, route->params)) { + return 1; + } + + reset_params(route->params); + + return 0; +} + +struct route *find_route(FCGX_Request *request) +{ + char buff[ROUTESZ], *uri; + int i = 0; + + uri = FCGX_GetParam("REQUEST_URI", request->envp); + + while (routes[i].uri) { + size_t routelen, urilen; + + routelen = strlen(routes[i].uri); + urilen = strlen(uri); + + if (urilen < routelen) { + continue; + } + + memcpy(buff, uri, routelen); + buff[routelen] = '\0'; + + if (!strcmp(buff, routes[i].uri)) { + return &routes[i]; + } + + i++; + } + + return NULL; +} diff --git a/backend/src/routes.h b/backend/src/routes.h new file mode 100644 index 0000000..c26690c --- /dev/null +++ b/backend/src/routes.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef ROUTES_H_ENTRY +#define ROUTES_H_ENTRY + +#include +#include +#include "server.h" +#include "query.h" + +#define ROUTESZ 255 + +#ifdef __cplusplus +extern "C" { +#endif + +struct route { + const char *uri; + int (*resh)(struct route *route, FCGX_Request *req, char dest[FBUFFSZ]); + struct param params[15]; +}; + +/* responses */ +int res_scrollbar(struct route *route, FCGX_Request *req, char dest[FBUFFSZ]); + +static struct route routes[2] = { + { + "/webapps/scrollbar.xhtml", + &res_scrollbar, + { + /* key defaultval val */ + { "sbw", "10px", "" }, + + { "thumbclr", "#9b3e46", "" }, + + { "thumbbstl", "solid", "" }, + { "thumbbrad", "8px", "" }, + { "thumbbw", "1px", "" }, + { "thumbbclr", "#ffffff", "" }, + + + { "trackclr", "#3b4252", "" }, + { "trackbrad", "8px", "" }, + { "trackmt", "0px", "" }, + { "trackmb", "0px", "" }, + NULL + } + }, + NULL +}; + +struct route *find_route(FCGX_Request *req); + +#ifdef __cplusplus +}; +#endif + +#endif /* ROUTES_H_ENTRY */ diff --git a/backend/src/server.h b/backend/src/server.h new file mode 100644 index 0000000..356bc49 --- /dev/null +++ b/backend/src/server.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef SERVER_H_ENTRY +#define SERVER_H_ENTRY + +#define SOCKET_PATH "/tmp/vilor.one.sock" +#define STATIC_PATH "/var/www/html/vilor" + +#define CRLF "\r\n" +#define XHTML_DOCTYPE "" + +#define FBUFFSZ 8192 + +#endif /* SERVER_H_ENTRY */ diff --git a/backend/src/template.c b/backend/src/template.c new file mode 100644 index 0000000..044e993 --- /dev/null +++ b/backend/src/template.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include "template.h" +#include "utils.h" +#include +#include +#include + +int rendertpl(const char *path, char dest[FBUFFSZ], struct param *params) +{ + FILE *fp = NULL; + int i = 0; + char paramtpl[100]; + + if (!(fp = fopen(path, "r"))) { + fputs("Can't open the file\n", stderr); + return 1; + } + + if (!fread(dest, sizeof(char), FBUFFSZ, fp)) { + fputs("Can't read file contents\n", stderr); + fclose(fp); + return 2; + } + fclose(fp); + +#ifdef DEBUG_MODE + puts("Interpolation"); +#endif + while (params[i].key) { + char *val = strlen(params[i].val) + ? params[i].val + : params[i].defaultval; + + sprintf(paramtpl, "{{ %s }}", params[i].key); +#ifdef DEBUG_MODE + printf("Key: %s; Val: %s; Real Val: %s\n", paramtpl, params[i].val, val); +#endif + while(strreplace(dest, paramtpl, val)) {} + i++; + } + + return 0; +} diff --git a/backend/src/template.h b/backend/src/template.h new file mode 100644 index 0000000..61595a4 --- /dev/null +++ b/backend/src/template.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef TEMPLATE_H_ENTRY +#define TEMPLATE_H_ENTRY + +#include "query.h" +#include "server.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int rendertpl(const char *path, char dest[FBUFFSZ], struct param *params); + +#ifdef __cplusplus +}; +#endif + +#endif /* TEMPLATE_H_ENTRY */ diff --git a/backend/src/utils.c b/backend/src/utils.c new file mode 100644 index 0000000..37e4675 --- /dev/null +++ b/backend/src/utils.c @@ -0,0 +1,35 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include +#include "utils.h" + +char *strreplace(char *s, const char *s1, const char *s2) { + char *p = strstr(s, s1); + + if (p) { + size_t len1 = strlen(s1); + size_t len2 = strlen(s2); + if (len1 != len2) { + memmove(p + len2, p + len1, strlen(p + len1) + 1); + } + memcpy(p, s2, len2); + } + + return p; +} diff --git a/backend/src/utils.h b/backend/src/utils.h new file mode 100644 index 0000000..1b8d5b0 --- /dev/null +++ b/backend/src/utils.h @@ -0,0 +1,24 @@ +/* + Copyright (C) 2022 Ivan Polyakov + + This file is part of vilor's website. + + Vilor's website is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Vilor's website is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef UTILS_H_ENTRY +#define UTILS_H_ENTRY + +char *strreplace(char *s, const char *s1, const char *s2); + +#endif /* UTILS_H_ENTRY */ diff --git a/src/pages/index.scm b/src/pages/index.scm index 801dfb8..50cc4b3 100644 --- a/src/pages/index.scm +++ b/src/pages/index.scm @@ -38,5 +38,6 @@ page-desc '() '() + '() '(((name "description") (content "Vilor's personal website")) ((name "keywords") (content "vilor")))))) diff --git a/src/pages/webapps/scrollbar.scm b/src/pages/webapps/scrollbar.scm index 3edad25..caab15a 100644 --- a/src/pages/webapps/scrollbar.scm +++ b/src/pages/webapps/scrollbar.scm @@ -16,6 +16,7 @@ ;; along with this program. If not, see . (import sxml-serializer) +(import scss) (load "./src/general.scm") @@ -29,10 +30,33 @@ (define page-styles '("scrollbar.css")) (define page-scripts '("scrollbar.js")) +(define page-embedded-style + '(css+ + (.scrollbar-app__demo + (scrollbar-width "{{ sbw }}") + (scrollbar-color "{{ thumbclr }} {{ trackclr }}") + + ((& ::-webkit-scrollbar) + (width "{{ sbw }}")) + + ((& ::-webkit-scrollbar-thumb) + (background-color "{{ thumbclr }}") + (border-width "{{ thumbbw }}") + (border-style "{{ thumbbstl }}") + (border-color "{{ thumbbclr }}") + (border-radius "{{ thumbbrad }}")) + + ((& ::-webkit-scrollbar-track) + (background-color "{{ trackclr }}") + (border-radius "{{ trackbrad }}") + (margin-top "{{ trackmt }}") + (margin-bottom "{{ trackmb }}"))))) + +(define example-text "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") + (define content `(div (@ (class "scrollbar-app")) - (noscript "Sorry, but this crap doesn't work without JavaScript.") - (form + (form (@ (method "GET") (action "/webapps/scrollbar.xhtml")) (fieldset (@ (class "scrollbar-app__panel")) (h3 "Bar:") (div (@ (class "scrollbar-app__input")) @@ -41,7 +65,7 @@ (type "text") (id "sbw") (name "sbw") - (value "10px") + (value "{{ sbw }}") (pattern "\\d+px") (title "Size in pixels with format: \"px\""))))) @@ -53,12 +77,12 @@ (type "color") (id "thumbclr") (name "thumbclr") - (value "#9b3e46"))) + (value "{{ thumbclr }}"))) (input (@ (type "text") (id "thumbclrtxt") (name "thumbclrtxt") - (value "#9b3e46") + (value "{{ thumbclr }}") (pattern "#[0-9A-Fa-f]{6}") (title "Hexadecimal RGB color with \"#\" at the beginning")))) @@ -84,7 +108,7 @@ (type "text") (id "thumbbrad") (name "thumbbrad") - (value 8px) + (value "{{ thumbbrad }}") (pattern "\\d+(px|%)") (title "Radius in pixels or percents with format: \"px\" or \"%\"")))) @@ -94,7 +118,7 @@ (type "text") (id "thumbbw") (name "thumbbw") - (value 1px) + (value "{{ thumbbw }}") (pattern "\\d+px") (title "Size in pixels with format: \"px\"")))) @@ -104,12 +128,12 @@ (type "color") (id "thumbbclr") (name "thumbbclr") - (value "#ffffff"))) + (value "{{ thumbbclr }}"))) (input (@ (type "text") (id "thumbbclrtxt") (name "thumbbclrtxt") - (value "#ffffff") + (value "{{ thumbbclr }}") (pattern "#[0-9A-Fa-f]{6}") (title "Hexadecimal RGB color with \"\#\" at the beginning")))))) @@ -121,12 +145,12 @@ (type "color") (id "trackclr") (name "trackclr") - (value "#3b4252"))) + (value "{{ trackclr }}"))) (input (@ (type "text") (id "trackclrtxt") (name "trackclrtxt") - (value "#3b4252") + (value "{{ trackclr }}") (pattern "#[0-9A-Fa-f]{6}") (title "Hexadecimal RGB color with \"#\" at the beginning")))) @@ -136,7 +160,7 @@ (type "text") (id "trackbrad") (name "trackbrad") - (value 8px) + (value "{{ trackbrad }}") (pattern "\\d+(px|%)") (title "Radius in pixels or percents with format: \"px\" or \"%\"")))) @@ -146,7 +170,7 @@ (type "text") (id "trackmt") (name "trackmt") - (value "0px") + (value "{{ trackmt }}") (pattern "\\d+px") (title "Size in pixels with format: \"px\"")))) @@ -156,17 +180,40 @@ (type "text") (id "trackmb") (name "trackmb") - (value "0px") + (value "{{ trackmb }}") (pattern "\\d+px") (title "Size in pixels with format: \"px\""))))) - (div (@ (class "scrollbar-app__buttons")) - (button (@ (type "button") (id "sbUpdBtn")) "update") - (button (@ (type "button") (id "sbPrintBtn")) "print scss") - (button (@ (type "button") (id "sbClearBtn")) "clear output"))) - - (pre (@ (class "scrollbar-app__panel") (style "display: none") (id "sbScssOut"))) - (textarea (@ (id "sbTextArea") (readonly "readonly")) "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."))) + (div (@ (class "scrollbar-app__buttons") (id "sbBtns")) + (button (@ (type "submit") (id "sbUpdBtn")) "update"))) + + (pre (@ (class "scrollbar-app__panel") (id "sbScssOut")) + " +.selector { + scrollbar-color: {{ thumbclr }} {{ trackclr }}; + + &::-webkit-scrollbar { + width: {{ sbw }}; + } + + &::-webkit-scrollbar-track { + background-color: {{ trackclr }}; + border-radius: {{ trackbrad }}; + margin-top: {{ trackmt }}; + margin-bottom: {{ trackmb }}; + } + + &::-webkit-scrollbar-thumb { + background-color: {{ thumbclr }}; + border: {{ thumbbw }} {{ thumbbstl }} {{ thumbbclr }}; + border-radius: {{ thumbbrad }}; + } +}") + (textarea (@ (class "scrollbar-app__demo") + (readonly "readonly") + (rows 5) + (cols 30)) + ,example-text))) (load "./src/templates/default.scm") (display xhtml-1.0-doctype) @@ -176,6 +223,7 @@ content page-name page-desc + page-embedded-style page-styles page-scripts `(((name "description") diff --git a/src/scripts/webapps/scrollbar.js b/src/scripts/webapps/scrollbar.js index 05e6c49..90c0186 100644 --- a/src/scripts/webapps/scrollbar.js +++ b/src/scripts/webapps/scrollbar.js @@ -1,203 +1,65 @@ // @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later /* Copyright (C) 2022 Ivan Polyakov - This file is part of vilor's website. - Vilor's website is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - Vilor's website is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with this program. If not, see . */ (function() { - var textArea = document.getElementById('sbTextArea'); - var updBtn = document.getElementById('sbUpdBtn'); - var printBtn = document.getElementById('sbPrintBtn'); - var clearBtn = document.getElementById('sbClearBtn'); - var msg = "Failed to get ELEMENT! Please report this bug to me." + var scssOut = document.getElementById("sbScssOut"); + scssOut.style = "display:none"; - if (!textArea) { - msg.replace("ELEMENT", "textarea"); - } else if (!updBtn) { - msg.replace("ELEMENT", "update button"); - } else { - msg = null; - } + var buttons = document.getElementById("sbBtns"); + createScssOutToggles(buttons); - if (msg) { - alert(msg); - console.error(msg); - return; - } - delete msg; + new ColorInput( + document.getElementById("thumbclr"), + document.getElementById("thumbclrtxt")); - var settingsForm = { - bar: { - inputs: { - width: document.getElementById('sbw'), - }, - getStyle() { - return "--sb-w:" + this.inputs.width.value + ";"; - }, - }, - thumb: { - inputs: { - color: document.getElementById('thumbclr'), - colortxt: document.getElementById('thumbclrtxt'), - bstl: document.getElementById('thumbbstl'), - bw: document.getElementById('thumbbw'), - bclr: document.getElementById('thumbbclr'), - bclrtxt: document.getElementById('thumbbclrtxt'), - brad: document.getElementById('thumbbrad'), - }, - init() { - this.inputs.colortxt.oninput = () => { - this.inputs.color.value = this.inputs.colortxt.value; - } - this.inputs.color.oninput = () => { - this.inputs.colortxt.value = this.inputs.color.value; - } + new ColorInput( + document.getElementById("thumbbclr"), + document.getElementById("thumbbclrtxt")); - this.inputs.bclr.oninput = () => { - this.inputs.bclrtxt.value = this.inputs.bclr.value; - } - this.inputs.bclrtxt.oninput = () => { - this.inputs.bclr.value = this.inputs.bclrtxt.value; - } - }, - getStyle() { - return "--thumb-clr:" + this.inputs.color.value + ";" - + "--thumb-bstl:" + this.inputs.bstl.value + ";" - + "--thumb-bw:" + this.inputs.bw.value + ";" - + "--thumb-bclr:" + this.inputs.bclr.value + ";" - + "--thumb-brad:" + this.inputs.brad.value + ";"; - }, - }, - track: { - inputs: { - color: document.getElementById('trackclr'), - colortxt: document.getElementById('trackclrtxt'), - brad: document.getElementById('trackbrad'), - mt: document.getElementById('trackmt'), - mb: document.getElementById('trackmb'), - }, - init() { - this.inputs.colortxt.oninput = () => { - this.inputs.color.value = this.inputs.colortxt.value; - } - this.inputs.color.oninput = () => { - this.inputs.colortxt.value = this.inputs.color.value; - } - }, - getStyle() { - return "--track-clr: " + this.inputs.color.value + ";" - + "--track-brad:" + this.inputs.brad.value + ";" - + "--track-mt:" + this.inputs.mt.value + ";" - + "--track-mb:" + this.inputs.mb.value + ";"; - }, - }, - output: document.getElementById('sbScssOut'), - init() { - this.thumb.init(); - this.track.init(); - }, - updStyle(el) { - el.style = this.bar.getStyle() + this.thumb.getStyle() - + this.track.getStyle(); - }, - updData() { - this.print(); - this.updateUrl(); - }, - print() { - this.output.textContent = ".selector {\n" + - " scrollbar-color: " + this.thumb.inputs.color.value + - " " + this.track.inputs.color.value + ";\n" + - "\n &::-webkit-scrollbar {\n" + - " width: " + this.bar.inputs.width.value + ";" + - "\n }\n" + - "\n &::-webkit-scrollbar-track {\n" + - " background-color: " + this.track.inputs.color.value + ";\n" + - " border-radius: " + this.track.inputs.brad.value + ";\n" + - " margin-top: " + this.track.inputs.mt.value + ";\n" + - " margin-bottom: " + this.track.inputs.mb.value + ";" + - "\n }\n" + - "\n &::-webkit-scrollbar-thumb {\n" + - " background-color: " + this.thumb.inputs.color.value + ";\n" + - " border: " + this.thumb.inputs.bw.value + " " + this.thumb.inputs.bstl.value + " " + this.thumb.inputs.bclr.value + ";\n" + - " border-radius: " + this.thumb.inputs.brad.value + ";" + - "\n }" + - "\n}"; - }, - updateUrl() { - var _this = this; - var url = window.location.origin + window.location.pathname; - var isFirst = true; - this.iterInputs(function(obj, input) { - var ch = isFirst ? "?" : "&"; - url += ch + obj + input + "=" + _this[obj].inputs[input].value; - isFirst = false; - }); - url = url.replace(/\#/g, "%23"); + new ColorInput( + document.getElementById("trackclr"), + document.getElementById("trackclrtxt")); - window.location.href = url; - }, - showScss() { - this.output.style = "display:block;" - }, - hideScss() { - this.output.style = "display:none;" - }, - iterInputs(cb) { - var objs = ['bar', 'thumb', 'track']; - for (var i = 0; i < objs.length; i++) { - var entries = Object.keys(settingsForm[objs[i]].inputs); - for (var j = 0; j < entries.length; j++) { - cb(objs[i], entries[j]); - } - } - delete objs; + function ColorInput(tcolor, ttext) { + tcolor.onchange = function() { + ttext.value = tcolor.value; } - }; - settingsForm.init(); - - updBtn.onclick = settingsForm.updData.bind(settingsForm); - printBtn.onclick = settingsForm.showScss.bind(settingsForm); - clearBtn.onclick = settingsForm.hideScss.bind(settingsForm); - - function getParameterByName(name, url = window.location.href) { - name = name.replace(/[\[\]]/g, '\\$&'); - var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, ' ')); + ttext.onchange = function() { + tcolor.value = ttext.value; + } } - var updNeeded = false; - settingsForm.iterInputs(function(obj, input) { - var val = getParameterByName(obj + input); - if (val) { - settingsForm[obj].inputs[input].value = val; + function createScssOutToggles(root) { + var printBtn = document.createElement("button"); + printBtn.type = "button"; + printBtn.textContent = "show scss"; + printBtn.onclick = function() { + scssOut.style = ""; + }; + + var clearBtn = document.createElement("button"); + clearBtn.type = "button"; + clearBtn.textContent = "hide scss"; + clearBtn.onclick = function() { + scssOut.style = "display:none"; + }; - if (settingsForm[obj].inputs[input].value !== val) { - updNeeded = true; - } - } - }); - settingsForm.updStyle(textArea); - settingsForm.print(); - if (updNeeded) { - settingsForm.updData(); + buttons.appendChild(printBtn); + buttons.appendChild(clearBtn); + + return [printBtn, clearBtn]; } })(); -// @license-end diff --git a/src/styles/webapps/scrollbar.scm b/src/styles/webapps/scrollbar.scm index 37482a7..6ec394d 100644 --- a/src/styles/webapps/scrollbar.scm +++ b/src/styles/webapps/scrollbar.scm @@ -49,40 +49,15 @@ (background-color "#585f70") (padding 12px)) - ((// textarea) - ("--sb-w" 10px) - ("--thumb-clr" "#9b3e46") - ("--thumb-bstl" "solid") - ("--thumb-bw" 1px) - ("--thumb-bclr" white) - ("--thumb-brad" 8px) - ("--track-clr" "#3b4252") - ("--track-brad" 8px) - ("--track-mt" 0px) - ("--track-mb" 0px) + ((// .scrollbar-app__demo) (height 300px) + (width 100%) (font-size 32px) (overflow-y scroll) - (scrollbar-width "var(--sb-w)") - (scrollbar-color "var(--thumb-clr) var(--track-clr)") (margin-top 60px) ((& ::-webkit-scrollbar) - (width "var(--sb-w)") - (margin-bottom 5px)) - - ((& ::-webkit-scrollbar-thumb) - (background-color "var(--thumb-clr)") - (border-style "var(--thumb-bstl)") - (border-width "var(--thumb-bw)") - (border-color "var(--thumb-bclr)") - (border-radius "var(--thumb-brad)")) - - ((& ::-webkit-scrollbar-track) - (background-color "var(--track-clr)") - (border-radius "var(--track-brad)") - (margin-top "var(--track-mt)") - (margin-bottom "var(--track-mb)"))) + (margin-bottom 5px))) ((// .scrollbar-app__buttons) (margin-top 24px) diff --git a/src/templates/clean.scm b/src/templates/clean.scm index 530ec33..2590363 100644 --- a/src/templates/clean.scm +++ b/src/templates/clean.scm @@ -15,10 +15,17 @@ ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . +(import scss) + (define (clean-tpl page-title page-content - #!optional (page-styles '()) (page-scripts '()) (page-meta '())) + + #!optional + (page-embedded-style '()) + (page-styles '()) + (page-scripts '()) + (page-meta '())) `(html (@ (xmlns "http://www.w3.org/1999/xhtml") (xml:lang "en") (lang "en")) @@ -36,8 +43,12 @@ `(link (@ (rel "stylesheet") (href ,l)))) page-styles) - (title ,page-title)) + (title ,page-title) + + ,(if (not (null? page-embedded-style)) + `(style ,(scss->css page-embedded-style)) + '())) (body ,page-content - ,(map (lambda (l) `(script (@ (src ,l)))) page-scripts)))) + ,(map (lambda (l) `(script (@ (src ,l) (type "text/javascript")) " ")) page-scripts)))) diff --git a/src/templates/default.scm b/src/templates/default.scm index 4f51a01..a819366 100644 --- a/src/templates/default.scm +++ b/src/templates/default.scm @@ -24,7 +24,12 @@ page-content page-name page-desc - #!optional (page-styles '()) (page-scripts '()) (page-meta '())) + + #!optional + (page-embedded-style '()) + (page-styles '()) + (page-scripts '()) + (page-meta '())) (clean-tpl page-title `(div (@ (class "wrapper")) @@ -38,8 +43,7 @@ (hr) ,footer) - (append - '("/style.css") - page-styles) + page-embedded-style + (append '("/style.css") page-styles) page-scripts page-meta))