Browse Source

scrollbar app remaked with cgi backend

pull/2/head
Ivan Polyakov 2 years ago
parent
commit
64237712f9
  1. 2
      backend/.gitignore
  2. 30
      backend/Makefile
  3. 26
      backend/config.mk
  4. 86
      backend/src/main.c
  5. 70
      backend/src/query.c
  6. 46
      backend/src/query.h
  7. 70
      backend/src/routes.c
  8. 74
      backend/src/routes.h
  9. 30
      backend/src/server.h
  10. 60
      backend/src/template.c
  11. 35
      backend/src/template.h
  12. 35
      backend/src/utils.c
  13. 24
      backend/src/utils.h
  14. 1
      src/pages/index.scm
  15. 90
      src/pages/webapps/scrollbar.scm
  16. 210
      src/scripts/webapps/scrollbar.js
  17. 31
      src/styles/webapps/scrollbar.scm
  18. 17
      src/templates/clean.scm
  19. 12
      src/templates/default.scm

2
backend/.gitignore vendored

@ -0,0 +1,2 @@
*.o
*cgi

30
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 <https://www.gnu.org/licenses/>.
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

26
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 <https://www.gnu.org/licenses/>.
CC=cc
CFLAGS=-ansi -pedantic
LDFLAGS=-lfcgi
DEBUG=
ifdef DEBUG
CFLAGS+=-Wall -g -DDEBUG_MODE
else
CFLAGS+=-O3
endif

86
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 <https://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <stdio.h>
#include <fcgi_config.h>
#include <fcgiapp.h>
#include <string.h>
#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;
}

70
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 <https://www.gnu.org/licenses/>.
*/
#include "query.h"
#include "utils.h"
#include <string.h>
#include <stdio.h>
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 &params[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++;
}
}

46
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 <https://www.gnu.org/licenses/>.
*/
#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 */

70
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 <https://www.gnu.org/licenses/>.
*/
#include "routes.h"
#include "server.h"
#include "template.h"
#include <string.h>
#include <stdio.h>
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;
}

74
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 <https://www.gnu.org/licenses/>.
*/
#ifndef ROUTES_H_ENTRY
#define ROUTES_H_ENTRY
#include <stddef.h>
#include <fcgiapp.h>
#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 */

30
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 <https://www.gnu.org/licenses/>.
*/
#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 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
#define FBUFFSZ 8192
#endif /* SERVER_H_ENTRY */

60
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 <https://www.gnu.org/licenses/>.
*/
#include "template.h"
#include "utils.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
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;
}

35
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 <https://www.gnu.org/licenses/>.
*/
#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 */

35
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 <https://www.gnu.org/licenses/>.
*/
#include <string.h>
#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;
}

24
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 <https://www.gnu.org/licenses/>.
*/
#ifndef UTILS_H_ENTRY
#define UTILS_H_ENTRY
char *strreplace(char *s, const char *s1, const char *s2);
#endif /* UTILS_H_ENTRY */

1
src/pages/index.scm

@ -38,5 +38,6 @@
page-desc page-desc
'() '()
'() '()
'()
'(((name "description") (content "Vilor's personal website")) '(((name "description") (content "Vilor's personal website"))
((name "keywords") (content "vilor")))))) ((name "keywords") (content "vilor"))))))

90
src/pages/webapps/scrollbar.scm

@ -16,6 +16,7 @@
;; along with this program. If not, see <https://www.gnu.org/licenses/>. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
(import sxml-serializer) (import sxml-serializer)
(import scss)
(load "./src/general.scm") (load "./src/general.scm")
@ -29,10 +30,33 @@
(define page-styles '("scrollbar.css")) (define page-styles '("scrollbar.css"))
(define page-scripts '("scrollbar.js")) (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 (define content
`(div (@ (class "scrollbar-app")) `(div (@ (class "scrollbar-app"))
(noscript "Sorry, but this crap doesn't work without JavaScript.") (form (@ (method "GET") (action "/webapps/scrollbar.xhtml"))
(form
(fieldset (@ (class "scrollbar-app__panel")) (fieldset (@ (class "scrollbar-app__panel"))
(h3 "Bar:") (h3 "Bar:")
(div (@ (class "scrollbar-app__input")) (div (@ (class "scrollbar-app__input"))
@ -41,7 +65,7 @@
(type "text") (type "text")
(id "sbw") (id "sbw")
(name "sbw") (name "sbw")
(value "10px") (value "{{ sbw }}")
(pattern "\\d+px") (pattern "\\d+px")
(title "Size in pixels with format: \"<NUMBER>px\""))))) (title "Size in pixels with format: \"<NUMBER>px\"")))))
@ -53,12 +77,12 @@
(type "color") (type "color")
(id "thumbclr") (id "thumbclr")
(name "thumbclr") (name "thumbclr")
(value "#9b3e46"))) (value "{{ thumbclr }}")))
(input (@ (input (@
(type "text") (type "text")
(id "thumbclrtxt") (id "thumbclrtxt")
(name "thumbclrtxt") (name "thumbclrtxt")
(value "#9b3e46") (value "{{ thumbclr }}")
(pattern "#[0-9A-Fa-f]{6}") (pattern "#[0-9A-Fa-f]{6}")
(title "Hexadecimal RGB color with \"#\" at the beginning")))) (title "Hexadecimal RGB color with \"#\" at the beginning"))))
@ -84,7 +108,7 @@
(type "text") (type "text")
(id "thumbbrad") (id "thumbbrad")
(name "thumbbrad") (name "thumbbrad")
(value 8px) (value "{{ thumbbrad }}")
(pattern "\\d+(px|%)") (pattern "\\d+(px|%)")
(title "Radius in pixels or percents with format: \"<NUMBER>px\" or \"<NUMBER>%\"")))) (title "Radius in pixels or percents with format: \"<NUMBER>px\" or \"<NUMBER>%\""))))
@ -94,7 +118,7 @@
(type "text") (type "text")
(id "thumbbw") (id "thumbbw")
(name "thumbbw") (name "thumbbw")
(value 1px) (value "{{ thumbbw }}")
(pattern "\\d+px") (pattern "\\d+px")
(title "Size in pixels with format: \"<NUMBER>px\"")))) (title "Size in pixels with format: \"<NUMBER>px\""))))
@ -104,12 +128,12 @@
(type "color") (type "color")
(id "thumbbclr") (id "thumbbclr")
(name "thumbbclr") (name "thumbbclr")
(value "#ffffff"))) (value "{{ thumbbclr }}")))
(input (@ (input (@
(type "text") (type "text")
(id "thumbbclrtxt") (id "thumbbclrtxt")
(name "thumbbclrtxt") (name "thumbbclrtxt")
(value "#ffffff") (value "{{ thumbbclr }}")
(pattern "#[0-9A-Fa-f]{6}") (pattern "#[0-9A-Fa-f]{6}")
(title "Hexadecimal RGB color with \"\#\" at the beginning")))))) (title "Hexadecimal RGB color with \"\#\" at the beginning"))))))
@ -121,12 +145,12 @@
(type "color") (type "color")
(id "trackclr") (id "trackclr")
(name "trackclr") (name "trackclr")
(value "#3b4252"))) (value "{{ trackclr }}")))
(input (@ (input (@
(type "text") (type "text")
(id "trackclrtxt") (id "trackclrtxt")
(name "trackclrtxt") (name "trackclrtxt")
(value "#3b4252") (value "{{ trackclr }}")
(pattern "#[0-9A-Fa-f]{6}") (pattern "#[0-9A-Fa-f]{6}")
(title "Hexadecimal RGB color with \"#\" at the beginning")))) (title "Hexadecimal RGB color with \"#\" at the beginning"))))
@ -136,7 +160,7 @@
(type "text") (type "text")
(id "trackbrad") (id "trackbrad")
(name "trackbrad") (name "trackbrad")
(value 8px) (value "{{ trackbrad }}")
(pattern "\\d+(px|%)") (pattern "\\d+(px|%)")
(title "Radius in pixels or percents with format: \"<NUMBER>px\" or \"<NUMBER>%\"")))) (title "Radius in pixels or percents with format: \"<NUMBER>px\" or \"<NUMBER>%\""))))
@ -146,7 +170,7 @@
(type "text") (type "text")
(id "trackmt") (id "trackmt")
(name "trackmt") (name "trackmt")
(value "0px") (value "{{ trackmt }}")
(pattern "\\d+px") (pattern "\\d+px")
(title "Size in pixels with format: \"<NUMBER>px\"")))) (title "Size in pixels with format: \"<NUMBER>px\""))))
@ -156,17 +180,40 @@
(type "text") (type "text")
(id "trackmb") (id "trackmb")
(name "trackmb") (name "trackmb")
(value "0px") (value "{{ trackmb }}")
(pattern "\\d+px") (pattern "\\d+px")
(title "Size in pixels with format: \"<NUMBER>px\""))))) (title "Size in pixels with format: \"<NUMBER>px\"")))))
(div (@ (class "scrollbar-app__buttons")) (div (@ (class "scrollbar-app__buttons") (id "sbBtns"))
(button (@ (type "button") (id "sbUpdBtn")) "update") (button (@ (type "submit") (id "sbUpdBtn")) "update")))
(button (@ (type "button") (id "sbPrintBtn")) "print scss")
(button (@ (type "button") (id "sbClearBtn")) "clear output"))) (pre (@ (class "scrollbar-app__panel") (id "sbScssOut"))
"
(pre (@ (class "scrollbar-app__panel") (style "display: none") (id "sbScssOut"))) .selector {
(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."))) 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") (load "./src/templates/default.scm")
(display xhtml-1.0-doctype) (display xhtml-1.0-doctype)
@ -176,6 +223,7 @@
content content
page-name page-name
page-desc page-desc
page-embedded-style
page-styles page-styles
page-scripts page-scripts
`(((name "description") `(((name "description")

210
src/scripts/webapps/scrollbar.js

@ -1,203 +1,65 @@
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later // @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
/* /*
Copyright (C) 2022 Ivan Polyakov Copyright (C) 2022 Ivan Polyakov
This file is part of vilor's website. This file is part of vilor's website.
Vilor's website is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Vilor's website is distributed in the hope that it will be useful, Vilor's website is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
(function() { (function() {
var textArea = document.getElementById('sbTextArea'); var scssOut = document.getElementById("sbScssOut");
var updBtn = document.getElementById('sbUpdBtn'); scssOut.style = "display:none";
var printBtn = document.getElementById('sbPrintBtn');
var clearBtn = document.getElementById('sbClearBtn');
var msg = "Failed to get ELEMENT! Please report this bug to me."
if (!textArea) { var buttons = document.getElementById("sbBtns");
msg.replace("ELEMENT", "textarea"); createScssOutToggles(buttons);
} else if (!updBtn) {
msg.replace("ELEMENT", "update button");
} else {
msg = null;
}
if (msg) { new ColorInput(
alert(msg); document.getElementById("thumbclr"),
console.error(msg); document.getElementById("thumbclrtxt"));
return;
}
delete msg;
var settingsForm = { new ColorInput(
bar: { document.getElementById("thumbbclr"),
inputs: { document.getElementById("thumbbclrtxt"));
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;
}
this.inputs.bclr.oninput = () => { new ColorInput(
this.inputs.bclrtxt.value = this.inputs.bclr.value; document.getElementById("trackclr"),
} document.getElementById("trackclrtxt"));
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");
window.location.href = url; function ColorInput(tcolor, ttext) {
}, tcolor.onchange = function() {
showScss() { ttext.value = tcolor.value;
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;
} }
};
settingsForm.init(); ttext.onchange = function() {
tcolor.value = ttext.value;
}
}
updBtn.onclick = settingsForm.updData.bind(settingsForm); function createScssOutToggles(root) {
printBtn.onclick = settingsForm.showScss.bind(settingsForm); var printBtn = document.createElement("button");
clearBtn.onclick = settingsForm.hideScss.bind(settingsForm); printBtn.type = "button";
printBtn.textContent = "show scss";
printBtn.onclick = function() {
scssOut.style = "";
};
function getParameterByName(name, url = window.location.href) { var clearBtn = document.createElement("button");
name = name.replace(/[\[\]]/g, '\\$&'); clearBtn.type = "button";
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), clearBtn.textContent = "hide scss";
results = regex.exec(url); clearBtn.onclick = function() {
if (!results) return null; scssOut.style = "display:none";
if (!results[2]) return ''; };
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
var updNeeded = false; buttons.appendChild(printBtn);
settingsForm.iterInputs(function(obj, input) { buttons.appendChild(clearBtn);
var val = getParameterByName(obj + input);
if (val) {
settingsForm[obj].inputs[input].value = val;
if (settingsForm[obj].inputs[input].value !== val) { return [printBtn, clearBtn];
updNeeded = true;
}
}
});
settingsForm.updStyle(textArea);
settingsForm.print();
if (updNeeded) {
settingsForm.updData();
} }
})(); })();
// @license-end

31
src/styles/webapps/scrollbar.scm

@ -49,40 +49,15 @@
(background-color "#585f70") (background-color "#585f70")
(padding 12px)) (padding 12px))
((// textarea) ((// .scrollbar-app__demo)
("--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)
(height 300px) (height 300px)
(width 100%)
(font-size 32px) (font-size 32px)
(overflow-y scroll) (overflow-y scroll)
(scrollbar-width "var(--sb-w)")
(scrollbar-color "var(--thumb-clr) var(--track-clr)")
(margin-top 60px) (margin-top 60px)
((& ::-webkit-scrollbar) ((& ::-webkit-scrollbar)
(width "var(--sb-w)") (margin-bottom 5px)))
(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)")))
((// .scrollbar-app__buttons) ((// .scrollbar-app__buttons)
(margin-top 24px) (margin-top 24px)

17
src/templates/clean.scm

@ -15,10 +15,17 @@
;; You should have received a copy of the GNU General Public License ;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
(import scss)
(define (clean-tpl (define (clean-tpl
page-title page-title
page-content 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") `(html (@ (xmlns "http://www.w3.org/1999/xhtml")
(xml:lang "en") (xml:lang "en")
(lang "en")) (lang "en"))
@ -36,8 +43,12 @@
`(link (@ (rel "stylesheet") (href ,l)))) `(link (@ (rel "stylesheet") (href ,l))))
page-styles) page-styles)
(title ,page-title)) (title ,page-title)
,(if (not (null? page-embedded-style))
`(style ,(scss->css page-embedded-style))
'()))
(body (body
,page-content ,page-content
,(map (lambda (l) `(script (@ (src ,l)))) page-scripts)))) ,(map (lambda (l) `(script (@ (src ,l) (type "text/javascript")) " ")) page-scripts))))

12
src/templates/default.scm

@ -24,7 +24,12 @@
page-content page-content
page-name page-name
page-desc page-desc
#!optional (page-styles '()) (page-scripts '()) (page-meta '()))
#!optional
(page-embedded-style '())
(page-styles '())
(page-scripts '())
(page-meta '()))
(clean-tpl (clean-tpl
page-title page-title
`(div (@ (class "wrapper")) `(div (@ (class "wrapper"))
@ -38,8 +43,7 @@
(hr) (hr)
,footer) ,footer)
(append page-embedded-style
'("/style.css") (append '("/style.css") page-styles)
page-styles)
page-scripts page-scripts
page-meta)) page-meta))

Loading…
Cancel
Save