1
0
mirror of https://codeberg.org/nobody/LocalCDN.git synced 2025-06-05 21:49:31 +02:00

Added: Statistics icon in popup (#74)

This commit is contained in:
nobody
2020-08-11 07:09:07 +02:00
parent b94c815f32
commit 83af2e06e9
4 changed files with 115 additions and 111 deletions

View File

@@ -1,7 +1,6 @@
/** /**
* Sections * Sections
*/ */
body { body {
background-color: #f0f0f0; background-color: #f0f0f0;
color: #555; color: #555;
@@ -63,7 +62,6 @@ footer {
/** /**
* Fonts * Fonts
*/ */
@font-face { @font-face {
font-family: 'Noto Sans'; font-family: 'Noto Sans';
font-style: normal; font-style: normal;
@@ -91,7 +89,6 @@ footer {
/** /**
* Headings * Headings
*/ */
.heading { .heading {
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
@@ -109,7 +106,6 @@ footer {
/** /**
* Lists * Lists
*/ */
.list { .list {
margin: 0; margin: 0;
padding: 8px 0 0; padding: 8px 0 0;
@@ -171,7 +167,6 @@ footer {
/** /**
* Icons * Icons
*/ */
.icon { .icon {
margin-right: 6px; margin-right: 6px;
} }
@@ -185,7 +180,6 @@ footer {
/** /**
* Buttons * Buttons
*/ */
.button { .button {
-moz-user-select: none; -moz-user-select: none;
user-select: none; user-select: none;
@@ -197,6 +191,7 @@ footer {
float: right; float: right;
font-size: 12px; font-size: 12px;
padding: 5px 22px; padding: 5px 22px;
margin-left: 10px;
} }
.button:hover { .button:hover {
@@ -217,6 +212,15 @@ footer {
color: #339a6f; color: #339a6f;
} }
.button-svg {
background-size: cover;
width: 15px;
height: 15px;
}
/**
* Donate
*/
#donate-button { #donate-button {
-moz-user-select: none; -moz-user-select: none;
user-select: none; user-select: none;
@@ -235,12 +239,13 @@ footer {
text-decoration: underline; text-decoration: underline;
} }
#options-button-svg, #donate-button-svg { #donate-button-svg {
background-size: cover; background-image: url("../../icons/donate.svg");
width: 15px;
height: 15px;
} }
/**
* Options
*/
#options-button-svg { #options-button-svg {
background-image: url("../../icons/settings-dark.svg"); background-image: url("../../icons/settings-dark.svg");
} }
@@ -249,10 +254,25 @@ footer {
filter: contrast(.5); filter: contrast(.5);
} }
#donate-button-svg { /**
background-image: url("../../icons/donate.svg"); * Statistics
*/
#statistics-button-svg {
/* https://www.svgrepo.com/svg/67340/statistics */
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgNDUyLjU5NCA0NTIuNTk0IgogICBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA0NTIuNTk0IDQ1Mi41OTQiCiAgIGlkPSJzdmcxNCIKICAgc29kaXBvZGk6ZG9jbmFtZT0ic3RhdGlzdGljcy1kYXJrLnN2ZyIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC45Mi4zICgyNDA1NTQ2LCAyMDE4LTAzLTExKSI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhMjAiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMxOCIgLz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IgogICAgIGJvcmRlcm9wYWNpdHk9IjEiCiAgICAgb2JqZWN0dG9sZXJhbmNlPSIxMCIKICAgICBncmlkdG9sZXJhbmNlPSIxMCIKICAgICBndWlkZXRvbGVyYW5jZT0iMTAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjE2ODAiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iOTk3IgogICAgIGlkPSJuYW1lZHZpZXcxNiIKICAgICBzaG93Z3JpZD0iZmFsc2UiCiAgICAgaW5rc2NhcGU6em9vbT0iMC4zNjg3MTI4IgogICAgIGlua3NjYXBlOmN4PSItMzc2LjgxNDY4IgogICAgIGlua3NjYXBlOmN5PSI2MjMuNDcxNTgiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiCiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjI1IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iZzEyIiAvPgogIDxnCiAgICAgaWQ9ImcxMiIKICAgICBzdHlsZT0iZmlsbDojNzc3Nzc3O2ZpbGwtb3BhY2l0eToxIj4KICAgIDxwYXRoCiAgICAgICBkPSJtNDMwLjUxMSw0NC42NTRoLTQwOC40MjljLTEyLjE3NiwwLTIyLjA4Miw5LjkwNi0yMi4wODIsMjIuMDgydjI1MC4yMjRjMCwxMi4xNzYgOS45MDYsMjIuMDgyIDIyLjA4MiwyMi4wODJoMTU0LjMyM2wtNi40MjgsNDguODk4aC0yNy41MDVjLTUuNTIyLDAtMTAsNC40NzctMTAsMTBzNC40NzgsMTAgMTAsMTBoMTY3LjY1YzUuNTIyLDAgMTAtNC40NzcgMTAtMTBzLTQuNDc4LTEwLTEwLTEwaC0yNy41MDZsLTYuNDI4LTQ4Ljg5OGgxNTQuMzIyYzEyLjE3NywwIDIyLjA4My05LjkwNiAyMi4wODMtMjIuMDgydi0yNTAuMjI0YzAuMDAxLTEyLjE3Ni05LjkwNS0yMi4wODItMjIuMDgyLTIyLjA4MnptLTQwOC40MjksMjBoNDA4LjQyOWMxLjE0OCwwIDIuMDgzLDAuOTM0IDIuMDgzLDIuMDgydjIxMS4zNTloLTQxMi41OTR2LTIxMS4zNTljMC0xLjE0OCAwLjkzNC0yLjA4MiAyLjA4Mi0yLjA4MnptMjQwLjM2MiwzMjMuMjg2aC03Mi4yOTZsNi40MjktNDguODk4aDU5LjQzOWw2LjQyOCw0OC44OTh6bTE2OC4wNjctNjguODk4aC00MDguNDI5Yy0xLjE0OCwwLTIuMDgyLTAuOTM0LTIuMDgyLTIuMDgydi0xOC44NjVoNDEyLjU5NHYxOC44NjVjMCwxLjE0OC0wLjkzNSwyLjA4Mi0yLjA4MywyLjA4MnoiCiAgICAgICBpZD0icGF0aDIiCiAgICAgICBzdHlsZT0iZmlsbDojNzc3Nzc3O2ZpbGwtb3BhY2l0eToxIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gODYuMjk3LDI1OS4wNDIgaCA0MCBjIDUuNTIyLDAgMTAsLTQuNDc3IDEwLC0xMCB2IC02MiBjIDAsLTUuNTIzIC00LjQ3OCwtMTAgLTEwLC0xMCBoIC00MCBjIC01LjUyMiwwIC0xMCw0LjQ3NyAtMTAsMTAgdiA2MiBjIDAsNS41MjMgNC40NzcsMTAgMTAsMTAgeiIKICAgICAgIGlkPSJwYXRoNCIKICAgICAgIHN0eWxlPSJmaWxsOiM3Nzc3Nzc7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJzc3Nzc3Nzc3MiIC8+CiAgICA8cGF0aAogICAgICAgZD0ibSAzMjYuMjk3LDI1OC41NTUgaCA0MCBjIDUuNTIyLDAgMTAsLTQuNDc3IDEwLC0xMCB2IC0yOS41NSBjIDAsLTUuNTIzIC00LjQ3OCwtMTAgLTEwLC0xMCBoIC00MCBjIC01LjUyMiwwIC0xMCw0LjQ3NyAtMTAsMTAgdiAyOS41NSBjIDAsNS41MjMgNC40NzcsMTAgMTAsMTAgeiIKICAgICAgIGlkPSJwYXRoNiIKICAgICAgIHN0eWxlPSJmaWxsOiM3Nzc3Nzc7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJzc3Nzc3Nzc3MiIC8+CiAgICA8cGF0aAogICAgICAgZD0ibSAyNDYuMjk3LDI1OS4wNDIgaCA0MCBjIDUuNTIyLDAgMTAsLTQuNDc3IDEwLC0xMCBWIDE2MC42MiBjIDAsLTUuNTIzIC00LjQ3OCwtMTAgLTEwLC0xMCBoIC00MCBjIC01LjUyMiwwIC0xMCw0LjQ3NyAtMTAsMTAgdiA4OC40MjIgYyAwLDUuNTIzIDQuNDc3LDEwIDEwLDEwIHoiCiAgICAgICBpZD0icGF0aDgiCiAgICAgICBzdHlsZT0iZmlsbDojNzc3Nzc3O2ZpbGwtb3BhY2l0eToxIgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0ic3Nzc3Nzc3NzIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMTY2LjI5NywyNTkuMDQyIGggNDAgYyA1LjUyMiwwIDEwLC00LjQ3NyAxMCwtMTAgViAxMzAuMjQ1IGMgMCwtNS41MjMgLTQuNDc4LC0xMCAtMTAsLTEwIGggLTQwIGMgLTUuNTIyLDAgLTEwLDQuNDc3IC0xMCwxMCB2IDExOC43OTcgYyAwLDUuNTIzIDQuNDc3LDEwIDEwLDEwIHoiCiAgICAgICBpZD0icGF0aDEwIgogICAgICAgc3R5bGU9ImZpbGw6Izc3Nzc3NztmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9InNzc3Nzc3NzcyIgLz4KICA8L2c+Cjwvc3ZnPgo=");
} }
#statistics-button:hover {
filter: contrast(.5);
}
#statistics-button {
display: none;
}
/**
* Toggles
*/
#protection-toggle, #manipulateDOM-toggle { #protection-toggle, #manipulateDOM-toggle {
-moz-user-select: none; -moz-user-select: none;
cursor: pointer; cursor: pointer;
@@ -322,6 +342,9 @@ input:checked + .slider:hover {
background-color: #4b806a; background-color: #4b806a;
} }
/**
* Info
*/
#info-button-svg { #info-button-svg {
background-image: url("../../icons/info-dark.svg"); background-image: url("../../icons/info-dark.svg");
background-repeat: no-repeat; background-repeat: no-repeat;
@@ -480,6 +503,11 @@ input:checked + .slider:hover {
background-image: url("../../icons/settings-light.svg"); background-image: url("../../icons/settings-light.svg");
} }
#statistics-button-svg {
/* https://www.svgrepo.com/svg/67340/statistics */
background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgNDUyLjU5NCA0NTIuNTk0IgogICBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA0NTIuNTk0IDQ1Mi41OTQiCiAgIGlkPSJzdmcxNCIKICAgc29kaXBvZGk6ZG9jbmFtZT0ic3RhdGlzdGljcy1saWdodC5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTIuMyAoMjQwNTU0NiwgMjAxOC0wMy0xMSkiPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTIwIj4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT48L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTgiIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxNjgwIgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijk5NyIKICAgICBpZD0ibmFtZWR2aWV3MTYiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjAuMzY4NzEyOCIKICAgICBpbmtzY2FwZTpjeD0iLTM3Ni44MTQ2OCIKICAgICBpbmtzY2FwZTpjeT0iNjIzLjQ3MTU4IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIwIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIyNSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9ImcxMiIgLz4KICA8ZwogICAgIGlkPSJnMTIiCiAgICAgc3R5bGU9ImZpbGw6Izc3Nzc3NztmaWxsLW9wYWNpdHk6MSI+CiAgICA8cGF0aAogICAgICAgZD0ibTQzMC41MTEsNDQuNjU0aC00MDguNDI5Yy0xMi4xNzYsMC0yMi4wODIsOS45MDYtMjIuMDgyLDIyLjA4MnYyNTAuMjI0YzAsMTIuMTc2IDkuOTA2LDIyLjA4MiAyMi4wODIsMjIuMDgyaDE1NC4zMjNsLTYuNDI4LDQ4Ljg5OGgtMjcuNTA1Yy01LjUyMiwwLTEwLDQuNDc3LTEwLDEwczQuNDc4LDEwIDEwLDEwaDE2Ny42NWM1LjUyMiwwIDEwLTQuNDc3IDEwLTEwcy00LjQ3OC0xMC0xMC0xMGgtMjcuNTA2bC02LjQyOC00OC44OThoMTU0LjMyMmMxMi4xNzcsMCAyMi4wODMtOS45MDYgMjIuMDgzLTIyLjA4MnYtMjUwLjIyNGMwLjAwMS0xMi4xNzYtOS45MDUtMjIuMDgyLTIyLjA4Mi0yMi4wODJ6bS00MDguNDI5LDIwaDQwOC40MjljMS4xNDgsMCAyLjA4MywwLjkzNCAyLjA4MywyLjA4MnYyMTEuMzU5aC00MTIuNTk0di0yMTEuMzU5YzAtMS4xNDggMC45MzQtMi4wODIgMi4wODItMi4wODJ6bTI0MC4zNjIsMzIzLjI4NmgtNzIuMjk2bDYuNDI5LTQ4Ljg5OGg1OS40MzlsNi40MjgsNDguODk4em0xNjguMDY3LTY4Ljg5OGgtNDA4LjQyOWMtMS4xNDgsMC0yLjA4Mi0wLjkzNC0yLjA4Mi0yLjA4MnYtMTguODY1aDQxMi41OTR2MTguODY1YzAsMS4xNDgtMC45MzUsMi4wODItMi4wODMsMi4wODJ6IgogICAgICAgaWQ9InBhdGgyIgogICAgICAgc3R5bGU9ImZpbGw6I2YyZjJmMjtmaWxsLW9wYWNpdHk6MSIgLz4KICAgIDxwYXRoCiAgICAgICBkPSJtIDg2LjI5NywyNTkuMDQyIGggNDAgYyA1LjUyMiwwIDEwLC00LjQ3NyAxMCwtMTAgdiAtNjIgYyAwLC01LjUyMyAtNC40NzgsLTEwIC0xMCwtMTAgaCAtNDAgYyAtNS41MjIsMCAtMTAsNC40NzcgLTEwLDEwIHYgNjIgYyAwLDUuNTIzIDQuNDc3LDEwIDEwLDEwIHoiCiAgICAgICBpZD0icGF0aDQiCiAgICAgICBzdHlsZT0iZmlsbDojZjJmMmYyO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0ic3Nzc3Nzc3NzIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMzI2LjI5NywyNTguNTU1IGggNDAgYyA1LjUyMiwwIDEwLC00LjQ3NyAxMCwtMTAgdiAtMjkuNTUgYyAwLC01LjUyMyAtNC40NzgsLTEwIC0xMCwtMTAgaCAtNDAgYyAtNS41MjIsMCAtMTAsNC40NzcgLTEwLDEwIHYgMjkuNTUgYyAwLDUuNTIzIDQuNDc3LDEwIDEwLDEwIHoiCiAgICAgICBpZD0icGF0aDYiCiAgICAgICBzdHlsZT0iZmlsbDojZjJmMmYyO2ZpbGwtb3BhY2l0eToxIgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0ic3Nzc3Nzc3NzIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMjQ2LjI5NywyNTkuMDQyIGggNDAgYyA1LjUyMiwwIDEwLC00LjQ3NyAxMCwtMTAgViAxNjAuNjIgYyAwLC01LjUyMyAtNC40NzgsLTEwIC0xMCwtMTAgaCAtNDAgYyAtNS41MjIsMCAtMTAsNC40NzcgLTEwLDEwIHYgODguNDIyIGMgMCw1LjUyMyA0LjQ3NywxMCAxMCwxMCB6IgogICAgICAgaWQ9InBhdGg4IgogICAgICAgc3R5bGU9ImZpbGw6I2YyZjJmMjtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9InNzc3Nzc3NzcyIgLz4KICAgIDxwYXRoCiAgICAgICBkPSJtIDE2Ni4yOTcsMjU5LjA0MiBoIDQwIGMgNS41MjIsMCAxMCwtNC40NzcgMTAsLTEwIFYgMTMwLjI0NSBjIDAsLTUuNTIzIC00LjQ3OCwtMTAgLTEwLC0xMCBoIC00MCBjIC01LjUyMiwwIC0xMCw0LjQ3NyAtMTAsMTAgdiAxMTguNzk3IGMgMCw1LjUyMyA0LjQ3NywxMCAxMCwxMCB6IgogICAgICAgaWQ9InBhdGgxMCIKICAgICAgIHN0eWxlPSJmaWxsOiNmMmYyZjI7ZmlsbC1vcGFjaXR5OjEiCiAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJzc3Nzc3Nzc3MiIC8+CiAgPC9nPgo8L3N2Zz4K");
}
input:checked + .slider { input:checked + .slider {
background-color: #6bb798; background-color: #6bb798;
} }

View File

@@ -18,7 +18,7 @@
</div> </div>
<div id="donate-button"> <div id="donate-button">
<p id="label-donate" data-i18n-content="labelDonate">Donate</p> <p id="label-donate" data-i18n-content="labelDonate">Donate</p>
<div id="donate-button-svg"></div> <div id="donate-button-svg" class="button-svg"></div>
</div> </div>
</header> </header>
<section class="content"> <section class="content">
@@ -55,7 +55,10 @@
<footer> <footer>
<a id="testing-utility-link" class="link-text">localcdn.org/test</a> <a id="testing-utility-link" class="link-text">localcdn.org/test</a>
<div id="options-button" class="button" data-i18n-title="optionsTitle"> <div id="options-button" class="button" data-i18n-title="optionsTitle">
<div id="options-button-svg"></div> <div id="options-button-svg" class="button-svg"></div>
</div>
<div id="statistics-button" class="button" data-i18n-title="optionsTitle">
<div id="statistics-button-svg" class="button-svg"></div>
</div> </div>
</footer> </footer>
<div id="popup-incomplete-translation"></div> <div id="popup-incomplete-translation"></div>

View File

@@ -26,9 +26,7 @@ var popup = {};
/** /**
* Private Methods * Private Methods
*/ */
popup._renderContents = function () { popup._renderContents = function () {
helpers.insertI18nContentIntoDocument(document); helpers.insertI18nContentIntoDocument(document);
helpers.insertI18nTitlesIntoDocument(document); helpers.insertI18nTitlesIntoDocument(document);
@@ -45,14 +43,12 @@ popup._renderContents = function () {
.then(popup._determineNegateHtmlFilterOption) .then(popup._determineNegateHtmlFilterOption)
.then(popup._renderContextualContents); .then(popup._renderContextualContents);
if(BrowserType.CHROMIUM) { if (BrowserType.CHROMIUM) {
document.getElementById('div-manipulateDOM').hidden = true; document.getElementById('div-manipulateDOM').hidden = true;
} }
}; };
popup._renderNonContextualContents = function () { popup._renderNonContextualContents = function () {
let versionLabelElement, nameLabelElement, counterElement, testingUtilityLinkElement, optionsButtonElement, donationButtonElement, infoButtonLabel; let versionLabelElement, nameLabelElement, counterElement, testingUtilityLinkElement, optionsButtonElement, donationButtonElement, infoButtonLabel;
versionLabelElement = document.getElementById('version-label'); versionLabelElement = document.getElementById('version-label');
@@ -71,10 +67,14 @@ popup._renderNonContextualContents = function () {
optionsButtonElement.addEventListener('mouseup', popup._onOptionsButtonClicked); optionsButtonElement.addEventListener('mouseup', popup._onOptionsButtonClicked);
donationButtonElement.addEventListener('mouseup', popup._onDonationButtonClicked); donationButtonElement.addEventListener('mouseup', popup._onDonationButtonClicked);
infoButtonLabel.addEventListener('mouseup', popup._onInfoButtonClicked); infoButtonLabel.addEventListener('mouseup', popup._onInfoButtonClicked);
if (popup._statisticsStatus) {
document.getElementById('statistics-button').style.display = 'block';
document.getElementById('statistics-button').addEventListener('mouseup', popup._onStatisticsButtonClicked);
}
}; };
popup._renderContextualContents = function () { popup._renderContextualContents = function () {
if (popup._domain !== null) { if (popup._domain !== null) {
popup._renderDomainWhitelistPanel(); popup._renderDomainWhitelistPanel();
} }
@@ -85,7 +85,6 @@ popup._renderContextualContents = function () {
}; };
popup._renderDomainWhitelistPanel = function () { popup._renderDomainWhitelistPanel = function () {
let websiteContextElement, protectionToggleElement, domainIndicatorElement, manipulateDOMToggleElement, manipulateDOMToggleStyle; let websiteContextElement, protectionToggleElement, domainIndicatorElement, manipulateDOMToggleElement, manipulateDOMToggleStyle;
websiteContextElement = document.getElementById('website-context'); websiteContextElement = document.getElementById('website-context');
@@ -97,33 +96,29 @@ popup._renderDomainWhitelistPanel = function () {
manipulateDOMToggleElement = document.getElementById('manipulateDOM-toggle-switch'); manipulateDOMToggleElement = document.getElementById('manipulateDOM-toggle-switch');
manipulateDOMToggleStyle = document.getElementById('toggle-switch-manipulateDOM'); manipulateDOMToggleStyle = document.getElementById('toggle-switch-manipulateDOM');
if (popup._domainIsWhitelisted === true) { if (popup._domainIsWhitelisted === true) {
manipulateDOMToggleElement.disabled = true; manipulateDOMToggleElement.disabled = true;
protectionToggleElement.checked = false; protectionToggleElement.checked = false;
manipulateDOMToggleStyle.setAttribute('class', 'slider-disabled'); manipulateDOMToggleStyle.setAttribute('class', 'slider-disabled');
protectionToggleElement.addEventListener('click', popup._enableProtection); protectionToggleElement.addEventListener('click', popup._enableProtection);
} else { } else {
manipulateDOMToggleElement.disabled = false; manipulateDOMToggleElement.disabled = false;
manipulateDOMToggleStyle.setAttribute('class', 'slider'); manipulateDOMToggleStyle.setAttribute('class', 'slider');
protectionToggleElement.checked = true; protectionToggleElement.checked = true;
protectionToggleElement.addEventListener('click', popup._disableProtection); protectionToggleElement.addEventListener('click', popup._disableProtection);
if ( popup.negateHtmlFilterList && !popup._domainManipulateDOM) { if (popup.negateHtmlFilterList && !popup._domainManipulateDOM) {
manipulateDOMToggleElement.checked = true; manipulateDOMToggleElement.checked = true;
manipulateDOMToggleElement.addEventListener('click', popup._enableManipulateDOM); manipulateDOMToggleElement.addEventListener('click', popup._enableManipulateDOM);
} else if (!popup.negateHtmlFilterList && !popup._domainManipulateDOM) { } else if (!popup.negateHtmlFilterList && !popup._domainManipulateDOM) {
manipulateDOMToggleElement.checked = false; manipulateDOMToggleElement.checked = false;
manipulateDOMToggleElement.addEventListener('click', popup._enableManipulateDOM); manipulateDOMToggleElement.addEventListener('click', popup._enableManipulateDOM);
} else if ( popup.negateHtmlFilterList && popup._domainManipulateDOM) { } else if (popup.negateHtmlFilterList && popup._domainManipulateDOM) {
manipulateDOMToggleElement.checked = false; manipulateDOMToggleElement.checked = false;
manipulateDOMToggleElement.addEventListener('click', popup._disableManipulateDOM); manipulateDOMToggleElement.addEventListener('click', popup._disableManipulateDOM);
} else if (!popup.negateHtmlFilterList && popup._domainManipulateDOM) { } else if (!popup.negateHtmlFilterList && popup._domainManipulateDOM) {
manipulateDOMToggleElement.checked = true; manipulateDOMToggleElement.checked = true;
manipulateDOMToggleElement.addEventListener('click', popup._disableManipulateDOM); manipulateDOMToggleElement.addEventListener('click', popup._disableManipulateDOM);
} }
@@ -133,7 +128,6 @@ popup._renderDomainWhitelistPanel = function () {
}; };
popup._renderInjectionPanel = function (groupedInjections) { popup._renderInjectionPanel = function (groupedInjections) {
let websiteContextElement, injectionOverviewElement; let websiteContextElement, injectionOverviewElement;
websiteContextElement = document.getElementById('website-context'); websiteContextElement = document.getElementById('website-context');
@@ -143,10 +137,9 @@ popup._renderInjectionPanel = function (groupedInjections) {
}; };
popup._enableProtection = function () { popup._enableProtection = function () {
let message = { let message = {
'topic': 'whitelist:remove-domain', topic: 'whitelist:remove-domain',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function () { chrome.runtime.sendMessage(message, function () {
@@ -155,10 +148,9 @@ popup._enableProtection = function () {
}; };
popup._disableProtection = function () { popup._disableProtection = function () {
let message = { let message = {
'topic': 'whitelist:add-domain', topic: 'whitelist:add-domain',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function () { chrome.runtime.sendMessage(message, function () {
@@ -167,10 +159,9 @@ popup._disableProtection = function () {
}; };
popup._enableManipulateDOM = function () { popup._enableManipulateDOM = function () {
let message = { let message = {
'topic': 'manipulateDOM:add-domain', topic: 'manipulateDOM:add-domain',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function () { chrome.runtime.sendMessage(message, function () {
@@ -179,10 +170,9 @@ popup._enableManipulateDOM = function () {
}; };
popup._disableManipulateDOM = function () { popup._disableManipulateDOM = function () {
let message = { let message = {
'topic': 'manipulateDOM:remove-domain', topic: 'manipulateDOM:remove-domain',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function () { chrome.runtime.sendMessage(message, function () {
@@ -191,16 +181,13 @@ popup._disableManipulateDOM = function () {
}; };
popup._determineDomainWhitelistStatus = function () { popup._determineDomainWhitelistStatus = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
let message = { let message = {
'topic': 'domain:fetch-is-whitelisted', topic: 'domain:fetch-is-whitelisted',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function (response) { chrome.runtime.sendMessage(message, function (response) {
popup._domainIsWhitelisted = response.value; popup._domainIsWhitelisted = response.value;
resolve(); resolve();
}); });
@@ -208,16 +195,13 @@ popup._determineDomainWhitelistStatus = function () {
}; };
popup._determineStatusManipulateDOM = function () { popup._determineStatusManipulateDOM = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
let message = { let message = {
'topic': 'domain:fetch-is-manipulateDOM', topic: 'domain:fetch-is-manipulateDOM',
'value': popup._domain value: popup._domain,
}; };
chrome.runtime.sendMessage(message, function (response) { chrome.runtime.sendMessage(message, function (response) {
popup._domainManipulateDOM = response.value; popup._domainManipulateDOM = response.value;
resolve(); resolve();
}); });
@@ -225,16 +209,13 @@ popup._determineStatusManipulateDOM = function () {
}; };
popup._determineResourceInjections = function () { popup._determineResourceInjections = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
let message = { let message = {
'topic': 'tab:fetch-injections', topic: 'tab:fetch-injections',
'value': popup._targetTab.id value: popup._targetTab.id,
}; };
chrome.runtime.sendMessage(message, function (response) { chrome.runtime.sendMessage(message, function (response) {
let groupedInjections = popup._groupResourceInjections(response.value); let groupedInjections = popup._groupResourceInjections(response.value);
popup._resourceInjections = groupedInjections; popup._resourceInjections = groupedInjections;
@@ -244,11 +225,8 @@ popup._determineResourceInjections = function () {
}; };
popup._determineTargetTab = function () { popup._determineTargetTab = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.query({'active': true, 'currentWindow': true}, function (tabs) {
popup._targetTab = tabs[0]; popup._targetTab = tabs[0];
popup._domain = helpers.extractDomainFromUrl(tabs[0].url, true); popup._domain = helpers.extractDomainFromUrl(tabs[0].url, true);
@@ -258,11 +236,8 @@ popup._determineTargetTab = function () {
}; };
popup._determineAmountInjected = function () { popup._determineAmountInjected = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.storage.sync.get(Setting.AMOUNT_INJECTED, function (items) { chrome.storage.sync.get(Setting.AMOUNT_INJECTED, function (items) {
popup._amountInjected = items.amountInjected || 0; popup._amountInjected = items.amountInjected || 0;
resolve(); resolve();
}); });
@@ -270,24 +245,28 @@ popup._determineAmountInjected = function () {
}; };
popup._determineNegateHtmlFilterOption = function () { popup._determineNegateHtmlFilterOption = function () {
return new Promise((resolve) => { return new Promise((resolve) => {
chrome.storage.sync.get(Setting.NEGATE_HTML_FILTER_LIST, function (items) { chrome.storage.sync.get(Setting.NEGATE_HTML_FILTER_LIST, function (items) {
popup.negateHtmlFilterList = items.negateHtmlFilterList; popup.negateHtmlFilterList = items.negateHtmlFilterList;
resolve(); resolve();
}); });
}); });
}; };
popup._groupResourceInjections = function (injections) { popup._getStatisticsStatus = function () {
return new Promise((resolve) => {
chrome.storage.local.get(Setting.INTERNAL_STATISTICS, function (items) {
popup._statisticsStatus = items.internalStatistics || false;
resolve();
});
});
};
popup._groupResourceInjections = function (injections) {
let groupedInjections = {}; let groupedInjections = {};
for (let index in injections) { for (let index in injections) {
let { source } = injections[index];
let {source} = injections[index];
groupedInjections[source] = groupedInjections[source] || []; groupedInjections[source] = groupedInjections[source] || [];
groupedInjections[source].push(injections[index]); groupedInjections[source].push(injections[index]);
@@ -297,12 +276,10 @@ popup._groupResourceInjections = function (injections) {
}; };
popup._createInjectionOverviewElement = function (groupedInjections) { popup._createInjectionOverviewElement = function (groupedInjections) {
let injectionOverviewElement = document.createElement('ul'); let injectionOverviewElement = document.createElement('ul');
injectionOverviewElement.setAttribute('class', 'list'); injectionOverviewElement.setAttribute('class', 'list');
for (let source in groupedInjections) { for (let source in groupedInjections) {
let injectionGroupHeaderElement, injectionGroupElement, cdn; let injectionGroupHeaderElement, injectionGroupElement, cdn;
cdn = groupedInjections[source]; cdn = groupedInjections[source];
@@ -318,7 +295,6 @@ popup._createInjectionOverviewElement = function (groupedInjections) {
}; };
popup._createInjectionGroupHeaderElement = function (source, cdn) { popup._createInjectionGroupHeaderElement = function (source, cdn) {
let injectionGroupHeaderElement, badgeElement, badgeTextNode, cdnNameTextNode; let injectionGroupHeaderElement, badgeElement, badgeTextNode, cdnNameTextNode;
injectionGroupHeaderElement = document.createElement('li'); injectionGroupHeaderElement = document.createElement('li');
@@ -339,7 +315,6 @@ popup._createInjectionGroupHeaderElement = function (source, cdn) {
}; };
popup._createInjectionGroupElement = function (source, cdn) { popup._createInjectionGroupElement = function (source, cdn) {
let injectionGroupElement; let injectionGroupElement;
// Filter duplicates // Filter duplicates
@@ -353,17 +328,14 @@ popup._createInjectionGroupElement = function (source, cdn) {
injectionGroupElement.setAttribute('class', 'sublist'); injectionGroupElement.setAttribute('class', 'sublist');
for (let injection of filtered) { for (let injection of filtered) {
let injectionElement = popup._createInjectionElement(injection); let injectionElement = popup._createInjectionElement(injection);
injectionGroupElement.appendChild(injectionElement); injectionGroupElement.appendChild(injectionElement);
} }
return injectionGroupElement; return injectionGroupElement;
}; };
popup._createInjectionElement = function (injection) { popup._createInjectionElement = function (injection) {
let injectionElement, filename, name, nameTextNode, noteElement, noteTextNode; let injectionElement, filename, name, nameTextNode, noteElement, noteTextNode;
injectionElement = document.createElement('li'); injectionElement = document.createElement('li');
@@ -372,10 +344,10 @@ popup._createInjectionElement = function (injection) {
filename = helpers.extractFilenameFromPath(injection.path); filename = helpers.extractFilenameFromPath(injection.path);
// If bundle empty, use filename // If bundle empty, use filename
if (injection.bundle === ''){ if (injection.bundle === '') {
name = helpers.determineResourceName(filename); name = helpers.determineResourceName(filename);
} else { } else {
name = injection.bundle + ' (Bundle)' name = injection.bundle + ' (Bundle)';
} }
nameTextNode = document.createTextNode(`- ${name}`); nameTextNode = document.createTextNode(`- ${name}`);
@@ -393,12 +365,12 @@ popup._createInjectionElement = function (injection) {
versionNode = ` v${injection.versionRequested}`; versionNode = ` v${injection.versionRequested}`;
} else if (injection.versionRequested === 'beta') { } else if (injection.versionRequested === 'beta') {
versionNode = ` ${injection.versionRequested}`; versionNode = ` ${injection.versionRequested}`;
} else if (injection.versionRequested !== 'latest'){ } else if (injection.versionRequested !== 'latest') {
versionNode = ` (v${injection.versionRequested} » v${injection.versionDelivered})`; versionNode = ` (v${injection.versionRequested} » v${injection.versionDelivered})`;
} else if (injection.versionRequested === 'latest') { } else if (injection.versionRequested === 'latest') {
versionNode = ` v${injection.versionDelivered}`; versionNode = ` v${injection.versionDelivered}`;
} else { } else {
versionNode = '' versionNode = '';
} }
noteTextNode = document.createTextNode(versionNode); noteTextNode = document.createTextNode(versionNode);
noteElement.appendChild(noteTextNode); noteElement.appendChild(noteTextNode);
@@ -408,24 +380,22 @@ popup._createInjectionElement = function (injection) {
return injectionElement; return injectionElement;
}; };
popup._filterDuplicates = function(array, key) { popup._filterDuplicates = function (array, key) {
/** /**
* Function to remove duplicates from an array, depending on 'key'. * Function to remove duplicates from an array, depending on 'key'.
* Ignore empty values of the 'key' * Ignore empty values of the 'key'
* *
*/ */
let filtered = array let filtered = array
.map(e => e[key]) .map((e) => e[key])
.map((value, index, newArray) => (value != '') ? (newArray.indexOf(value) === index && index) : index ) .map((value, index, newArray) => (value != '' ? newArray.indexOf(value) === index && index : index))
.filter(e => array[e]) .filter((e) => array[e])
.map(e => array[e]); .map((e) => array[e]);
return filtered; return filtered;
}; };
popup._renderLocaleNotice = function () { popup._renderLocaleNotice = function () {
let localeNoticeElement, nameTextNode; let localeNoticeElement, nameTextNode;
localeNoticeElement = document.getElementById('popup-incomplete-translation'); localeNoticeElement = document.getElementById('popup-incomplete-translation');
@@ -438,12 +408,12 @@ popup._renderLocaleNotice = function () {
localeNoticeElement.addEventListener('mouseup', popup._onIncompleteTranslation); localeNoticeElement.addEventListener('mouseup', popup._onIncompleteTranslation);
}; };
/** /**
* Event Handlers * Event Handlers
*/ */
popup._onDocumentLoaded = function () { popup._onDocumentLoaded = function () {
let manifest, language; let manifest, language;
manifest = chrome.runtime.getManifest(); manifest = chrome.runtime.getManifest();
@@ -454,16 +424,15 @@ popup._onDocumentLoaded = function () {
popup._scriptDirection = helpers.determineScriptDirection(language); popup._scriptDirection = helpers.determineScriptDirection(language);
popup._determineAmountInjected() popup._determineAmountInjected()
.then(popup._getStatisticsStatus)
.then(popup._renderContents); .then(popup._renderContents);
}; };
popup._onTestingUtilityLinkClicked = function (event) { popup._onTestingUtilityLinkClicked = function (event) {
if (event.button === 0 || event.button === 1) { if (event.button === 0 || event.button === 1) {
chrome.tabs.create({ chrome.tabs.create({
'url': 'https://www.localcdn.org/test', url: 'https://www.localcdn.org/test',
'active': (event.button === 0) active: event.button === 0,
}); });
} }
@@ -473,18 +442,15 @@ popup._onTestingUtilityLinkClicked = function (event) {
}; };
popup._onOptionsButtonClicked = function () { popup._onOptionsButtonClicked = function () {
chrome.runtime.openOptionsPage(); chrome.runtime.openOptionsPage();
return window.close(); return window.close();
}; };
popup._onDonationButtonClicked = function () { popup._onDonationButtonClicked = function () {
if (event.button === 0 || event.button === 1) { if (event.button === 0 || event.button === 1) {
chrome.tabs.create({ chrome.tabs.create({
'url': chrome.extension.getURL('pages/donate/donate.html'), url: chrome.extension.getURL('pages/donate/donate.html'),
'active': (event.button === 0) active: event.button === 0,
}); });
} }
@@ -494,25 +460,20 @@ popup._onDonationButtonClicked = function () {
}; };
popup._onToggled = function () { popup._onToggled = function () {
let bypassCache = typeof browser === 'undefined';
let bypassCache = (typeof browser === 'undefined'); chrome.tabs.reload(popup._targetTab.id, { bypassCache });
chrome.tabs.reload(popup._targetTab.id, {bypassCache});
setTimeout(function () { setTimeout(function () {
popup._close(); popup._close();
}, 200); }, 200);
}; };
popup._close = function () { popup._close = function () {
chrome.runtime.getPlatformInfo(function (information) { chrome.runtime.getPlatformInfo(function (information) {
if (information.os === chrome.runtime.PlatformOs.ANDROID) { if (information.os === chrome.runtime.PlatformOs.ANDROID) {
chrome.tabs.getCurrent(function (tab) { chrome.tabs.getCurrent(function (tab) {
chrome.tabs.remove(tab.id); chrome.tabs.remove(tab.id);
}); });
} else { } else {
window.close(); window.close();
} }
@@ -521,10 +482,9 @@ popup._close = function () {
popup._onInfoButtonClicked = function () { popup._onInfoButtonClicked = function () {
if (event.button === 0 || event.button === 1) { if (event.button === 0 || event.button === 1) {
chrome.tabs.create({ chrome.tabs.create({
'url': chrome.extension.getURL('pages/help/help.html'), url: chrome.extension.getURL('pages/help/help.html'),
'active': (event.button === 0) active: event.button === 0,
}); });
} }
@@ -535,10 +495,9 @@ popup._onInfoButtonClicked = function () {
popup._onIncompleteTranslation = function () { popup._onIncompleteTranslation = function () {
if (event.button === 0 || event.button === 1) { if (event.button === 0 || event.button === 1) {
chrome.tabs.create({ chrome.tabs.create({
'url': 'https://hosted.weblate.org/projects/localcdn/', url: 'https://hosted.weblate.org/projects/localcdn/',
'active': (event.button === 0) active: event.button === 0,
}); });
} }
@@ -547,9 +506,22 @@ popup._onIncompleteTranslation = function () {
} }
}; };
popup._onStatisticsButtonClicked = function () {
if (event.button === 0 || event.button === 1) {
chrome.tabs.create({
url: chrome.extension.getURL('pages/statistics/statistics.html'),
active: event.button === 0,
});
}
if (event.button === 0) {
window.close();
}
};
/** /**
* Initializations * Initializations
*/ */
popup.negateHtmlFilterList = false; popup.negateHtmlFilterList = false;
popup._statisticsStatus = false;
document.addEventListener('DOMContentLoaded', popup._onDocumentLoaded); document.addEventListener('DOMContentLoaded', popup._onDocumentLoaded);

View File

@@ -38,6 +38,7 @@
<li>Added CDN: loli.net (cdnjs.loli.net, fonts.loli.net, cdn.css.net, ajax.loli.net) (<a href="https://codeberg.org/nobody/LocalCDN/issues/77">#77</a>)</li> <li>Added CDN: loli.net (cdnjs.loli.net, fonts.loli.net, cdn.css.net, ajax.loli.net) (<a href="https://codeberg.org/nobody/LocalCDN/issues/77">#77</a>)</li>
<li>Added CDN: cdn.bootcss.net (<a href="https://codeberg.org/nobody/LocalCDN/issues/77">#77</a>)</li> <li>Added CDN: cdn.bootcss.net (<a href="https://codeberg.org/nobody/LocalCDN/issues/77">#77</a>)</li>
<li>Added: 'Monero' (Donations page)</li> <li>Added: 'Monero' (Donations page)</li>
<li>Added: Statistics icon in popup</li>
</ul> </ul>
<div id="generator-section"> <div id="generator-section">
<div class="topic-label"> <div class="topic-label">