├── .github └── workflows │ └── test.yml ├── .gitignore ├── .gitmodules ├── Dockerfile ├── LICENSE ├── README.md ├── dev ├── resources │ └── config.edn └── user.clj ├── doc ├── commentator.service └── commentator_schema.jpg ├── integration └── mcorbin │ └── page.html ├── project.clj ├── release.sh ├── site └── commentator │ ├── .hugo_build.lock │ ├── archetypes │ └── default.md │ ├── config.toml │ ├── content │ ├── _index.md │ ├── api │ │ ├── _index.md │ │ ├── comments │ │ │ └── _index.md │ │ ├── events │ │ │ └── _index.md │ │ └── monitoring │ │ │ └── _index.md │ ├── howto │ │ ├── _index.md │ │ ├── configuration │ │ │ └── _index.md │ │ ├── get-build │ │ │ └── _index.md │ │ └── use-it │ │ │ └── _index.md │ └── support │ │ └── _index.md │ ├── layouts │ └── partials │ │ ├── logo.html │ │ └── menu-footer.html │ ├── public │ ├── 404.html │ ├── _redirects │ ├── api │ │ ├── comments │ │ │ ├── index.html │ │ │ └── index.xml │ │ ├── events │ │ │ ├── index.html │ │ │ └── index.xml │ │ ├── index.html │ │ ├── index.xml │ │ └── monitoring │ │ │ ├── index.html │ │ │ └── index.xml │ ├── categories │ │ ├── index.html │ │ └── index.xml │ ├── css │ │ ├── atom-one-dark-reasonable.css │ │ ├── auto-complete.css │ │ ├── featherlight.min.css │ │ ├── fontawesome-all.min.css │ │ ├── hugo-theme.css │ │ ├── hybrid.css │ │ ├── nucleus.css │ │ ├── perfect-scrollbar.min.css │ │ ├── tabs.css │ │ ├── tags.css │ │ ├── theme-blue.css │ │ ├── theme-commentator.css │ │ ├── theme-green.css │ │ ├── theme-red.css │ │ └── theme.css │ ├── fonts │ │ ├── Inconsolata.eot │ │ ├── Inconsolata.svg │ │ ├── Inconsolata.ttf │ │ ├── Inconsolata.woff │ │ ├── Novecentosanswide-Normal-webfont.eot │ │ ├── Novecentosanswide-Normal-webfont.svg │ │ ├── Novecentosanswide-Normal-webfont.ttf │ │ ├── Novecentosanswide-Normal-webfont.woff │ │ ├── Novecentosanswide-Normal-webfont.woff2 │ │ ├── Novecentosanswide-UltraLight-webfont.eot │ │ ├── Novecentosanswide-UltraLight-webfont.svg │ │ ├── Novecentosanswide-UltraLight-webfont.ttf │ │ ├── Novecentosanswide-UltraLight-webfont.woff │ │ ├── Novecentosanswide-UltraLight-webfont.woff2 │ │ ├── Work_Sans_200.eot │ │ ├── Work_Sans_200.svg │ │ ├── Work_Sans_200.ttf │ │ ├── Work_Sans_200.woff │ │ ├── Work_Sans_200.woff2 │ │ ├── Work_Sans_300.eot │ │ ├── Work_Sans_300.svg │ │ ├── Work_Sans_300.ttf │ │ ├── Work_Sans_300.woff │ │ ├── Work_Sans_300.woff2 │ │ ├── Work_Sans_500.eot │ │ ├── Work_Sans_500.svg │ │ ├── Work_Sans_500.ttf │ │ ├── Work_Sans_500.woff │ │ └── Work_Sans_500.woff2 │ ├── health.html │ ├── howto │ │ ├── configuration │ │ │ ├── index.html │ │ │ └── index.xml │ │ ├── get-build │ │ │ ├── index.html │ │ │ └── index.xml │ │ ├── index.html │ │ ├── index.xml │ │ └── use-it │ │ │ ├── index.html │ │ │ └── index.xml │ ├── images │ │ ├── clippy.svg │ │ ├── favicon.png │ │ └── gopher-404.jpg │ ├── img │ │ ├── commentator_presentation.jpg │ │ ├── mirabelle_presentation.png │ │ └── mirabelle_streams.png │ ├── index.html │ ├── index.xml │ ├── js │ │ ├── auto-complete.js │ │ ├── clipboard.min.js │ │ ├── featherlight.min.js │ │ ├── highlight.pack.js │ │ ├── hugo-learn.js │ │ ├── jquery-3.3.1.min.js │ │ ├── jquery.sticky.js │ │ ├── learn.js │ │ ├── lunr.min.js │ │ ├── modernizr.custom-3.6.0.js │ │ ├── perfect-scrollbar.jquery.min.js │ │ ├── perfect-scrollbar.min.js │ │ └── search.js │ ├── mermaid │ │ └── mermaid.js │ ├── sitemap.xml │ ├── support │ │ ├── index.html │ │ └── index.xml │ ├── tags │ │ ├── index.html │ │ └── index.xml │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 │ └── static │ ├── health.html │ └── img │ └── commentator_presentation.jpg ├── src └── commentator │ ├── api.clj │ ├── cache.clj │ ├── chain.clj │ ├── challenge.clj │ ├── comment.clj │ ├── config.clj │ ├── core.clj │ ├── event.clj │ ├── handler.clj │ ├── interceptor │ ├── auth.clj │ └── cors.clj │ ├── lock.clj │ ├── rate_limit.clj │ ├── spec.clj │ ├── store.clj │ └── usage.clj └── test └── commentator ├── chain_test.clj ├── challenge_test.clj ├── comment_test.clj ├── event_test.clj ├── handler_test.clj ├── interceptor └── cors_test.clj ├── mock └── s3.clj ├── rate_limit_test.clj └── usage_test.clj /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches : [master] 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-20.04 10 | steps: 11 | - name: checkout 12 | uses: actions/checkout@v2 13 | - name: install java 14 | uses: actions/setup-java@v1 15 | with: 16 | java-version: 1.17 17 | - name: Install leiningen 18 | uses: DeLaGuardo/setup-clojure@3.4 19 | with: 20 | lein: latest 21 | - name: Run lein tests 22 | run: lein test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | profiles.clj 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | /.lein-* 10 | /.nrepl-port 11 | .hgignore 12 | .hg/ 13 | .clj-kondo/ 14 | .lsp/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "site/commentator/themes/hugo-theme-learn"] 2 | path = site/commentator/themes/hugo-theme-learn 3 | url = https://github.com/matcornic/hugo-theme-learn.git 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM clojure:openjdk-17-lein as build-env 2 | 3 | ADD . /app 4 | WORKDIR /app 5 | 6 | RUN lein uberjar 7 | 8 | # ----------------------------------------------------------------------------- 9 | 10 | FROM eclipse-temurin:17 11 | 12 | RUN groupadd -r commentator && useradd -r -s /bin/false -g commentator commentator 13 | 14 | RUN mkdir /app 15 | COPY --from=build-env --chown=commentator:commentator /app/target/uberjar/commentator-*-standalone.jar /app/commentator.jar 16 | ENV COMMENTATOR_CONFIGURATION=/app/config.edn 17 | USER commentator 18 | 19 | ENTRYPOINT ["java", "-ea", "-XX:+AlwaysPreTouch", "-XX:MaxRAMPercentage=90", "-cp", "/app/commentator.jar"] 20 | 21 | CMD ["commentator.core"] 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Commentator 2 | 3 | A commenting system for your blog or website. Comments are stored on any S3-compatible store. 4 | 5 | I built commentator to provide an easy to use (and easy to host) free commenting system with advanced functionalities. 6 | 7 | ## Features 8 | 9 | Commentator provides: 10 | 11 | - [x] Multi website support: one instance of Commentator can manage comments for multiple websites. 12 | - [x] An easy-to-use API to manage comments and events. A public API allows users to create or retrieve approved comments, and a admin API allows you to administrate comments (approve them or delete them for example). 13 | Everytime a comment is added an event is generated into a dedicated file on S3. The API allows you to read and delete the events. You can use this file to be notified when a new comment is added. 14 | - [x] Rate limiting, either by IP or using the requests `x-forwarded-for` header. 15 | - [x] A "challenge" system to avoid spammers. 16 | - [x] An in-memory cache for comments, for performances and to avoid hitting S3 too much. 17 | - [x] Metrics about the applications exposed using the Prometheus format. 18 | 19 | ## Documentation 20 | 21 | The documentation is available at https://www.commentator.mcorbin.fr/ 22 | 23 | -------------------------------------------------------------------------------- /dev/resources/config.edn: -------------------------------------------------------------------------------- 1 | {:http {:host "127.0.0.1" 2 | :port 8787} 3 | :allow-origin ["https://www.mcorbin.fr"] 4 | :rate-limit-minutes 5 5 | :admin {:token #secret "my-super-token"} 6 | :store {:access-key #secret #env ACCESS_KEY 7 | :secret-key #secret #env SECRET_KEY 8 | :bucket-prefix "commentator-dev-" 9 | :endpoint "https://sos-ch-gva-2.exo.io"} 10 | :comment {:auto-approve false 11 | :allowed-articles {"mcorbin-fr" ["foo" 12 | "bar"]}} 13 | :logging {:level "info" 14 | :console {:encoder "json"} 15 | :overrides {:org.eclipse.jetty "info" 16 | :org.apache.http "error"}} 17 | :prometheus {:host "127.0.0.1" 18 | :port 8788} 19 | :challenges {:type :questions 20 | :ttl 120 21 | :questions [{:question "1 + 4 = ?" 22 | :answer "5"} 23 | {:question "1 + 9 = ?" 24 | :answer "10"}] 25 | :secret #secret "aezaz"}} 26 | -------------------------------------------------------------------------------- /dev/user.clj: -------------------------------------------------------------------------------- 1 | (ns user 2 | (:require [clojure.tools.namespace.repl :refer [refresh]] 3 | [commentator.core :as core])) 4 | 5 | (defn start! 6 | [] 7 | (core/start!) 8 | "started") 9 | 10 | (defn stop! 11 | [] 12 | (core/stop!) 13 | "stopped") 14 | 15 | (defn restart! 16 | [] 17 | (stop!) 18 | (refresh) 19 | (start!)) 20 | 21 | (defn challenge 22 | [] 23 | (let [operations [* + -] 24 | mapping {* " * " + " + " - " - "} 25 | n1 (rand-int 12) 26 | n2 (rand-int 12) 27 | op (rand-nth operations) 28 | result (op n1 n2) 29 | ] 30 | () 31 | {:question (format "what is the result of: %d %s %d" 32 | n1 33 | (get mapping op) 34 | n2) 35 | :answer (str result)})) 36 | 37 | (defn challenges 38 | [n] 39 | (->> {:challenges (reduce (fn [state _] (assoc state 40 | (keyword (str (java.util.UUID/randomUUID))) 41 | (challenge))) 42 | {} 43 | (range n))} 44 | pr-str 45 | (spit "/tmp/challenges.edn")) 46 | 47 | ) 48 | -------------------------------------------------------------------------------- /doc/commentator.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Your favorite commenting system 3 | After=network.target 4 | ConditionPathExists=/etc/commentator/commentator.edn 5 | 6 | [Service] 7 | User=commentator 8 | Environment=COMMENTATOR_CONFIGURATION=/etc/commentator/commentator.edn 9 | Environment=ACCESS_KEY=value 10 | Environment=SECRET_KEY=value 11 | Group=commentator 12 | ExecStart=/usr/bin/java -Xms300m -Xmx300m -XX:+ExitOnOutOfMemoryError -jar /opt/commentator.jar 13 | Restart=on-failure 14 | 15 | [Install] 16 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /doc/commentator_schema.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/doc/commentator_schema.jpg -------------------------------------------------------------------------------- /integration/mcorbin/page.html: -------------------------------------------------------------------------------- 1 | - 2 | 62 | 63 |
64 |
65 |
66 | 67 |
68 | 69 | 72 |

Add a comment

73 |

74 | 75 | 76 |

77 | 78 |
79 |

80 |

If you have a bug/issue with the commenting system, please send me an email (my email is in the "About" section).

81 | 82 |
83 | 84 |
85 |
86 | 87 |
88 | {% else %} 89 |
90 |

Comments are disabled for this article

91 |
92 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject commentator "0.18.0" 2 | :description "A Free commenting system" 3 | :url "https://github.com/mcorbin/commentator" 4 | :license {:name "EPL-2.0" 5 | :url "https://www.eclipse.org/legal/epl-2.0/"} 6 | :dependencies [[amazonica "0.3.156" 7 | :exclusions 8 | [com.amazonaws/aws-java-sdk 9 | com.amazonaws/amazon-kinesis-client]] 10 | [com.amazonaws/aws-java-sdk-core "1.12.128"] 11 | [com.amazonaws/aws-java-sdk-s3 "1.12.128"] 12 | [fr.mcorbin/corbihttp "0.30.0"] 13 | [org.clojure/clojure "1.10.3"] 14 | [org.clojure/core.cache "1.0.225"]] 15 | :main ^:skip-aot commentator.core 16 | :target-path "target/%s" 17 | :source-paths ["src"] 18 | :profiles {:dev {:dependencies [[org.clojure/tools.namespace "1.2.0"] 19 | [pjstadig/humane-test-output "0.11.0"] 20 | [tortue/spy "2.9.0"] 21 | [ring/ring-mock "0.4.0"]] 22 | :global-vars {*assert* true} 23 | :env {:commentator-configuration "dev/resources/config.edn"} 24 | :plugins [[lein-environ "1.1.0"] 25 | [lein-cloverage "1.1.1"] 26 | [lein-ancient "0.6.15"] 27 | [lein-cljfmt "0.6.6"]] 28 | :injections [(require 'pjstadig.humane-test-output) 29 | (pjstadig.humane-test-output/activate!)] 30 | :repl-options {:init-ns user} 31 | :source-paths ["dev"]} 32 | :uberjar {:aot :all}} 33 | :test-selectors {:default (fn [x] (not (:integration x))) 34 | :integration :integration}) 35 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | tag=$1 3 | lein test 4 | 5 | git add . 6 | git commit -m "release ${tag}" 7 | git tag -a "${tag}" -m "release ${tag}" 8 | docker build -t mcorbin/commentator:${tag} . 9 | docker push mcorbin/commentator:${tag} 10 | git push --tags 11 | git push 12 | -------------------------------------------------------------------------------- /site/commentator/.hugo_build.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/.hugo_build.lock -------------------------------------------------------------------------------- /site/commentator/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /site/commentator/config.toml: -------------------------------------------------------------------------------- 1 | baseURL = "https://www.commentator.mcorbin.fr" 2 | languageCode = "en-us" 3 | title = "Commentator" 4 | theme = "hugo-theme-learn" 5 | 6 | [params] 7 | themeVariant = "commentator" 8 | disableInlineCopyToClipBoard = true 9 | 10 | 11 | [[menu.shortcuts]] 12 | name = " Github repo" 13 | identifier = "ds" 14 | url = "https://github.com/mcorbin/commentator" 15 | weight = 10 16 | 17 | [[menu.shortcuts]] 18 | name = " Site theme" 19 | identifier = "learntheme" 20 | url = "https://github.com/matcornic/hugo-theme-learn/" 21 | weight = 20 -------------------------------------------------------------------------------- /site/commentator/content/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Commentator 3 | weight: 30 4 | chapter: false 5 | --- 6 | 7 | # Commentator, a free commenting system for your blog 8 | 9 | Commentator is a simple application which provide all you need to have a powerful commenting system on your blogs or websites. 10 | 11 | Commentator uses json files (one per article) stored on any S3-compatible storage to store your comment. The rest of the application is completely stateless. 12 | 13 | Using a S3 compatible store as a database provide several advantages: 14 | 15 | - Easy to use: you don't have to setup a SQL database for example. 16 | - Highly available storage. 17 | - You can use any S3 tools (s3cmd for example) to interact directly with your comments if you want to. 18 | 19 | Commentator also provides: 20 | 21 | - Multi site support: one instance of Commentator can manage comments for multiple websites. 22 | - An easy-to-use API to manage comments and events. A public API allows users to create or retrieve approved comments, and a admin API allows you to administrate comments (approve them or delete them for example). 23 | Everytime a comment is added an event is generated into a dedicated file on S3. The API allows you to read and delete the events. You can use this file to be notified when a new comment is added. 24 | - Rate limiting, either by IP or using the requests `x-forwarded-for` header. 25 | - A "challenge" system to avoid spammers. 26 | - An in-memory cache for comments, for performances and to avoid hitting S3 too much. 27 | - Metrics about the applications exposed using the Prometheus format. 28 | 29 | ![Mirabelle](img/commentator_presentation.jpg) 30 | -------------------------------------------------------------------------------- /site/commentator/content/api/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API 3 | weight: 20 4 | chapter: false 5 | --- 6 | 7 | The Commentator API is used to manage comments and events. 8 | 9 | Some API calls (to approve or delete comments for exemple) are only availables for admin users. 10 | 11 | Admin users should provide the token (defined in the [configuration](/howto/configuration/) in the `Authorization` header. 12 | 13 | New ways of authenticating admin users may be added in the future. 14 | -------------------------------------------------------------------------------- /site/commentator/content/api/comments/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Comments 3 | weight: 1 4 | disableToc: false 5 | --- 6 | 7 | # Public API 8 | 9 | ## Add a comment 10 | 11 | - **POST** `/api/v1/comment//
` 12 | 13 | 14 | | Field | Type | Description | 15 | | ------ | ----------- | ----------- | 16 | | author | string | The author's name | 17 | | author-website | string | The author's website (optional) | 18 | | content | string | The comment content | 19 | | signature | string | The challenge signature | 20 | | timestamp | string | The challenge timestamp | 21 | | answer | string | The challenge answer | 22 | 23 | --- 24 | 25 | ``` 26 | curl -X POST --header "Content-Type: application/json" --data \ '{"author":"mcorbin", "author-website": "mcorbin.fr", "content":"My comment","challenge":"c1","answer":"5", "signature": "", "timestamp": 1639688441946}' http://localhost:8787/api/v1/comment/mcorbin-fr/foo 27 | 28 | {"message":"Comment added"} 29 | ``` 30 | 31 | ## List comments for an article 32 | 33 | - **GET** `/api/v1/comment//
` 34 | 35 | --- 36 | 37 | ``` 38 | curl http://localhost:8787/api/v1/comment/mcorbin-fr/foo 39 | 40 | [ 41 | { 42 | "content": "My comment", 43 | "author": "mcorbin", 44 | "author-website": "mcorbin.fr", 45 | "id": "0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9", 46 | "approved": true, 47 | "timestamp": 1629101319712 48 | } 49 | ] 50 | 51 | ``` 52 | 53 | ## Get a random challenge 54 | 55 | - **GET** `/api/v1/challenge/` 56 | 57 | --- 58 | 59 | ``` 60 | curl http://localhost:8787/api/v1/challenge/mcorbin-fr/foo 61 | {"timestamp": 1629101319712,"question":"1 + 9 = ?", "signature": ""} 62 | ``` 63 | 64 | # Admin API 65 | 66 | ## Get a comment 67 | 68 | - **GET** `/api/admin/comment//
/` 69 | 70 | --- 71 | 72 | ``` 73 | curl -H "Authorization: my-super-token" http://localhost:8787/api/admin/comment/mcorbin-fr/foo/0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9 74 | 75 | { 76 | "content": "My comment", 77 | "author": "mcorbin", 78 | "author-website": "mcorbin.fr", 79 | "id": "0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9", 80 | "approved": false, 81 | "timestamp": 1629101319712 82 | } 83 | ``` 84 | 85 | ## List comments for an article 86 | 87 | - **GET** `/api/admin/comment//
` 88 | 89 | --- 90 | 91 | ``` 92 | curl -H "Authorization: my-super-token" http://localhost:8787/api/admin/comment/mcorbin-fr/foo 93 | [ 94 | { 95 | "content": "My comment", 96 | "author": "mcorbin", 97 | "author-website": "mcorbin.fr", 98 | "id": "0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9", 99 | "approved": false, 100 | "timestamp": 1629101319712 101 | } 102 | ] 103 | ``` 104 | 105 | ## Approve a comment 106 | 107 | - **POST** `/api/admin/comment//
/` 108 | 109 | --- 110 | 111 | ``` 112 | curl -X POST -H "Authorization: my-super-token" http://localhost:8787/api/admin/comment/mcorbin-fr/foo/0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9 113 | 114 | { 115 | "message": "Comment approved" 116 | } 117 | ``` 118 | 119 | ## Delete a comment 120 | 121 | - **DELETE** `/api/admin/comment//
/` 122 | 123 | --- 124 | 125 | ``` 126 | curl -X DELETE -H "Authorization: my-super-token" http://localhost:8787/api/admin/comment/mcorbin-fr/foo/0bfe788b-3a06-47fe-8a75-4a3ec6a3b8d9 127 | 128 | { 129 | "message":"Comment deleted" 130 | } 131 | ``` 132 | 133 | ## Delete all comments for an article 134 | 135 | - **DELETE** `/api/admin/comment//
` 136 | 137 | --- 138 | 139 | ``` 140 | curl -X DELETE -H "Authorization: my-super-token" http://localhost:8787/api/admin/comment/mcorbin-fr/foo 141 | 142 | { 143 | "message":"Comments deleted" 144 | } 145 | ``` 146 | -------------------------------------------------------------------------------- /site/commentator/content/api/events/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Events 3 | weight: 1 4 | disableToc: false 5 | --- 6 | 7 | **Admin API** 8 | 9 | ## List events 10 | 11 | - **GET** `/api/admin/event/` 12 | 13 | --- 14 | 15 | ``` 16 | curl -H "Authorization: my-super-token" http://localhost:8787/api/admin/event/mcorbin-fr 17 | 18 | [ 19 | { 20 | "timestamp": 1628364816474, 21 | "id": "01970a27-eb5f-4ee5-97af-a5a11a427824", 22 | "article": "foo", 23 | "message": "New comment 67f99f31-9724-4288-94d7-4fc860dab744 on article foo", 24 | "comment-id": "67f99f31-9724-4288-94d7-4fc860dab744", 25 | "type": "new-comment" 26 | } 27 | ] 28 | ``` 29 | 30 | ## Delete an event 31 | 32 | - **DELETE** `/api/admin/event/` 33 | 34 | --- 35 | 36 | ``` 37 | curl -H "Authorization: my-super-token" http://localhost:8787/api/admin/event/mcorbin-fr 38 | 39 | [ 40 | { 41 | "timestamp": 1628364816474, 42 | "id": "01970a27-eb5f-4ee5-97af-a5a11a427824", 43 | "article": "foo", 44 | "message": "New comment 67f99f31-9724-4288-94d7-4fc860dab744 on article foo", 45 | "comment-id": "67f99f31-9724-4288-94d7-4fc860dab744", 46 | "type": "new-comment" 47 | } 48 | ] 49 | ``` 50 | -------------------------------------------------------------------------------- /site/commentator/content/api/monitoring/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Monitoring 3 | weight: 30 4 | disableToc: false 5 | --- 6 | 7 | ## Healthz 8 | 9 | - **GET** `/healthz` 10 | 11 | --- 12 | 13 | ``` 14 | curl localhost:8787/healthz 15 | 16 | {"message":"ok"} 17 | ``` 18 | 19 | ## Metrics 20 | 21 | You can [configure](howto/configuration/) Commentator to expose metrics using the Prometheus format on a dedicated port. 22 | -------------------------------------------------------------------------------- /site/commentator/content/howto/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How to 3 | weight: 1 4 | chapter: true 5 | --- 6 | 7 | # How to use Commentator 8 | -------------------------------------------------------------------------------- /site/commentator/content/howto/configuration/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration 3 | weight: 10 4 | disableToc: false 5 | --- 6 | 7 | The Commentator configuration is defined in [EDN](https://github.com/edn-format/edn). 8 | Here is a commented example configuration file: 9 | 10 | ```clojure 11 | {;; The Mirabelle HTTP Server. 12 | ;; The key, cert, and cacert optional parameters can be set to enable TLS (the 13 | ;; parameters are path to the cert files) 14 | :http {:host "127.0.0.1" 15 | :port 8787} 16 | ;; The list of allowed origins for the public API. 17 | :allow-origin ["https://www.mcorbin.fr"] 18 | ;; The admin token for the admin API calls 19 | :admin {:token #secret "my-super-token"} 20 | ;; The number of minutes for an user before being able to publish another comment 21 | ;; on Commentator. 22 | ;; The `x-forwarded-for` header is first used to get the user IP 23 | ;; If the header is not set it fallbacks to the request source IP. 24 | :rate-limit-minutes 5 25 | :store {;; Your s3 access/secret keys 26 | ;; In this example the #env reader is used but you can also 27 | ;; specify the values without using environment variables if you 28 | ;; want to 29 | :access-key #secret #env ACCESS_KEY 30 | :secret-key #secret #env SECRET_KEY 31 | ;; the prefix for the buckets used by Commentator to store comments 32 | ;; and events 33 | :bucket-prefix "commentator-dev-" 34 | ;; The S3 endpoint 35 | :endpoint "https://sos-ch-gva-2.exo.io"} 36 | :comment {;; Set to true if you want to have comments automatically approved once 37 | ;; created 38 | :auto-approve false 39 | ;; A map containing for each website a list of articles which can receive 40 | ;; comments. You can use this map to disable comments for an article 41 | ;; for example. 42 | :allowed-articles {"mcorbin-fr" ["foo" 43 | "bar"]}} 44 | ;; Logging configuration (https://github.com/pyr/unilog) 45 | :logging {:level "info" 46 | :console {:encoder "json"} 47 | :overrides {:org.eclipse.jetty "info" 48 | :org.apache.http "error"}} 49 | ;; The prometheus configuration to expose the metrics. 50 | ;; The key, cert, and cacert optional parameters can be set to enable TLS (the 51 | ;; parameters are path to the cert files) 52 | :prometheus {:host "127.0.0.1" 53 | :port 8788} 54 | ;; Challenges configurations to avoid spammers 55 | ;; See the different modes to configure challenges on https://www.commentator.mcorbin.fr/howto/use-it/ 56 | :challenges {:type :math 57 | :ttl 120 58 | :secret #secret "azizjiuzarhuaizhaiuzr"}} 59 | ``` 60 | 61 | Commentator can be used to store comments for multiple websites. 62 | 63 | The `:allowed-articles` key should contain the list of articles open for comments for each website. The website names and articles should match the ones used in the [API](/api/comments/). You can also check the [use it](/howto/use-it/) section of the documentation for more information about this. 64 | 65 | Each website will have a dedicated bucket to store its comments and events. 66 | 67 | The bucket name will be ``. The bucket prefix should be a string between 1 and 19 characters, and the website a string between 1 and 39 characters. Allowed characters are letters (both uppercase and lowercase), number, `_` and `-`. 68 | -------------------------------------------------------------------------------- /site/commentator/content/howto/get-build/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Get and launch Commentator 3 | weight: 1 4 | disableToc: false 5 | --- 6 | 7 | ## Get Commentator jar file 8 | 9 | You can download the Commentator jar from [Github](https://github.com/mcorbin/commentator/releases). Commentator is tested under Java 17 (LTS). 10 | 11 | You can also build Commentator yourself. You will need to do that: 12 | 13 | - [Leiningen](https://leiningen.org/), the Clojure build tool. 14 | - Java 11. 15 | 16 | Then, clone the [Git repository](https://github.com/mcorbin/commentator). You can now build the project with `lein uberjar`. 17 | 18 | The resulting jar will be in `target/uberjar/commentator--standalone.jar` 19 | 20 | ## Launch Commentator 21 | 22 | Commentator needs a [configuration file](/howto/configuration/). You need to set the environment variable `COMMENTATOR_CONFIGURATION` to the path of this file. 23 | 24 | ### Using Docker 25 | 26 | The Docker image is available on the [Docker Hub](https://hub.docker.com/r/mcorbin/commentator). 27 | You will need to mount the configuration file as a volume (or inject it into the running container somehow) in order to make it work. 28 | -------------------------------------------------------------------------------- /site/commentator/content/howto/use-it/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Use it 3 | weight: 50 4 | disableToc: false 5 | --- 6 | 7 | Commentator stores the articles comments on a S3 compatible store. + 8 | Let's say we want to store comments for the blog `mcorbin.fr` for example. 9 | 10 | The first thing to do is to write the Commentator [configuration file](/howto/configuration/). 11 | 12 | As explained in the linked section of the documentation, several things are important. 13 | 14 | **Allow origin** 15 | 16 | The same Commentator instance can serve comments for several websites. You need to configure the list of websites in the `:allow-origin` section. 17 | 18 | **Rate limit** 19 | 20 | The `:rate-limit-minutes` option prevents users to create more than one comment every N minutes. 21 | 22 | The `x-forwarded-for` header is first used to get the user IP. If the header is not set it fallbacks to the request source IP. 23 | 24 | **Comment** 25 | 26 | Comments can be automatically approved by setting the `:auto-approve` value to `true`. By default, comments not approved by an administrator are not displayed. 27 | 28 | You also need to configure the `allowed-articles` key. It contains a map containing for each website the list of articles allowed to receive comments. For example: 29 | 30 | ```clojure 31 | {"mcorbin-fr" ["my-first-article" 32 | "my-second-article"]} 33 | ``` 34 | 35 | With this setup, only requests to create comments on the `/api/v1/comment//
` path will be allowed, where the possible value for `` is "mcorbin-fr" and the possible values for `
` are "my-first-article" and "my-second-article". 36 | 37 | You can read the [API documentation](/api/comments/) to understand how it works. It's important to keep in mind that the `allowed-articles` key should match how the API is used later to store and retrieve comments for articles. 38 | 39 | **Challenges** 40 | 41 | Commentator supports a basic challenge system to avoid spammers. 42 | 43 | Commentator provides an [API endpoint](/api/comments/) to return a random challenge. This API endpoint can be used to integrate Commentator on your website. What is returned by the endpoint is a json payload containing: 44 | 45 | - A `question`, a text containing a question 46 | - A `timestamp` 47 | - A `signature` 48 | 49 | When users want to create a comment, they should provide: 50 | 51 | - The `timestamp` and the `signature` provided by the previous endpoint. 52 | - An `answer` field containing the expected answer (case insensitive). 53 | 54 | The `:challenges` key in the configuration can be used to configure challenges. It currently supports two modes. 55 | 56 | ### questions 57 | 58 | ```clojure 59 | {:type :questions 60 | :ttl 120 61 | :secret #secret "azizjiuzarhuaizhaiuzr" 62 | :questions [{:question "1 + 4 = ?" 63 | :answer "5"} 64 | {:question "1 + 9 = ?" 65 | :answer "10"}]} 66 | ``` 67 | 68 | We have here two challenges with simple questions about mathematical operations. The questions and answers are totally free, it's up to you to choose what you want to ask. 69 | 70 | You can also easily generate a lot of challenges programmatically if you want to. 71 | 72 | When users want to create a comment, they should provide: 73 | 74 | challenge name and the correct answer. The case of the letters in the answer is not important, everything is compared after being converted to lower case. 75 | 76 | The TTL is the validity duration of the challenge. 77 | 78 | ### math 79 | 80 | ```clojure 81 | {:type :math 82 | :ttl 120 83 | :secret #secret "azizjiuzarhuaizhaiuzr"} 84 | ``` 85 | 86 | This challenge will automatically generate simple mathematical challenges. It could for example return a `:question` containing `"what is the result of: 10 + 6"` 87 | 88 | The user should, like in the `questions` challenge, provide the answer, timestamp and signature when creating a comment. 89 | 90 | **Store** 91 | 92 | You should put the store configuration (to access the S3 storage) in the `:store` key. 93 | 94 | The `:bucket-prefix` value will be used as prefix for the buckets storing the comments. For example, if `:bucket-prefix` is set to "commentator-", the bucket will be "commentator-mcorbin-fr" for the `mcorbin-fr` website. 95 | 96 | The buckets should already exist, Commentator will not create them automatically. 97 | 98 | ## Events 99 | 100 | Every time a comment is published, an event is pushed in the website bucket in a file named `events.json`. 101 | 102 | The [API](/api/events/) let you retrieve and delete these events. You can use this file or these endpoints to be notified when a new comment is created. 103 | 104 | ## Integration 105 | 106 | The code I use to integrate Commentator on my personal blog is available on [Github](https://github.com/mcorbin/commentator/blob/master/integration/mcorbin/page.html). 107 | 108 | I'm not a frontend developer. If you have frontend skills and want to write a nice integration, please reach to me on Github. 109 | -------------------------------------------------------------------------------- /site/commentator/content/support/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Support and contributions 3 | weight: 30 4 | chapter: false 5 | --- 6 | 7 | 8 | ## Need help ? 9 | 10 | If you need help, please open issues on [Github](https://github.com/mcorbin/commentator). 11 | -------------------------------------------------------------------------------- /site/commentator/layouts/partials/logo.html: -------------------------------------------------------------------------------- 1 |

4 | -------------------------------------------------------------------------------- /site/commentator/layouts/partials/menu-footer.html: -------------------------------------------------------------------------------- 1 |

Powered by mcorbin

2 | -------------------------------------------------------------------------------- /site/commentator/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 404 Page not found 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 37 | 38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 |
46 |

Error

47 |

48 |

49 |

Woops. Looks like this page doesn't exist ¯\_(ツ)_/¯.

50 |

51 |

Go to homepage

52 |

Page not found!

53 |
54 |
55 | 56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /site/commentator/public/_redirects: -------------------------------------------------------------------------------- 1 | https://commentator.mcorbin.fr/* https://www.commentator.mcorbin.fr/:splat 301! -------------------------------------------------------------------------------- /site/commentator/public/api/comments/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Comments on Commentator 5 | https://www.commentator.mcorbin.fr/api/comments/ 6 | Recent content in Comments on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/api/events/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Events on Commentator 5 | https://www.commentator.mcorbin.fr/api/events/ 6 | Recent content in Events on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/api/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API on Commentator 5 | https://www.commentator.mcorbin.fr/api/ 6 | Recent content in API on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/api/monitoring/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Monitoring on Commentator 5 | https://www.commentator.mcorbin.fr/api/monitoring/ 6 | Recent content in Monitoring on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/categories/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Categories on Commentator 5 | https://www.commentator.mcorbin.fr/categories/ 6 | Recent content in Categories on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/css/atom-one-dark-reasonable.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Atom One Dark With support for ReasonML by Gidi Morris, based off work by Daniel Gamage 4 | 5 | Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax 6 | 7 | */ 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | line-height: 1.3em; 13 | color: #abb2bf; 14 | background: #282c34; 15 | border-radius: 5px; 16 | } 17 | .hljs-keyword, .hljs-operator { 18 | color: #F92672; 19 | } 20 | .hljs-pattern-match { 21 | color: #F92672; 22 | } 23 | .hljs-pattern-match .hljs-constructor { 24 | color: #61aeee; 25 | } 26 | .hljs-function { 27 | color: #61aeee; 28 | } 29 | .hljs-function .hljs-params { 30 | color: #A6E22E; 31 | } 32 | .hljs-function .hljs-params .hljs-typing { 33 | color: #FD971F; 34 | } 35 | .hljs-module-access .hljs-module { 36 | color: #7e57c2; 37 | } 38 | .hljs-constructor { 39 | color: #e2b93d; 40 | } 41 | .hljs-constructor .hljs-string { 42 | color: #9CCC65; 43 | } 44 | .hljs-comment, .hljs-quote { 45 | color: #b18eb1; 46 | font-style: italic; 47 | } 48 | .hljs-doctag, .hljs-formula { 49 | color: #c678dd; 50 | } 51 | .hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst { 52 | color: #e06c75; 53 | } 54 | .hljs-literal { 55 | color: #56b6c2; 56 | } 57 | .hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string { 58 | color: #98c379; 59 | } 60 | .hljs-built_in, .hljs-class .hljs-title { 61 | color: #e6c07b; 62 | } 63 | .hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number { 64 | color: #d19a66; 65 | } 66 | .hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title { 67 | color: #61aeee; 68 | } 69 | .hljs-emphasis { 70 | font-style: italic; 71 | } 72 | .hljs-strong { 73 | font-weight: bold; 74 | } 75 | .hljs-link { 76 | text-decoration: underline; 77 | } 78 | -------------------------------------------------------------------------------- /site/commentator/public/css/auto-complete.css: -------------------------------------------------------------------------------- 1 | .autocomplete-suggestions { 2 | text-align: left; 3 | cursor: default; 4 | border: 1px solid #ccc; 5 | border-top: 0; 6 | background: #fff; 7 | box-shadow: -1px 1px 3px rgba(0,0,0,.1); 8 | 9 | /* core styles should not be changed */ 10 | position: absolute; 11 | display: none; 12 | z-index: 9999; 13 | max-height: 254px; 14 | overflow: hidden; 15 | overflow-y: auto; 16 | box-sizing: border-box; 17 | 18 | } 19 | .autocomplete-suggestion { 20 | position: relative; 21 | cursor: pointer; 22 | padding: 7px; 23 | line-height: 23px; 24 | white-space: nowrap; 25 | overflow: hidden; 26 | text-overflow: ellipsis; 27 | color: #333; 28 | } 29 | 30 | .autocomplete-suggestion b { 31 | font-weight: normal; 32 | color: #1f8dd6; 33 | } 34 | 35 | .autocomplete-suggestion.selected { 36 | background: #333; 37 | color: #fff; 38 | } 39 | 40 | .autocomplete-suggestion:hover { 41 | background: #444; 42 | color: #fff; 43 | } 44 | 45 | .autocomplete-suggestion > .context { 46 | font-size: 12px; 47 | } 48 | -------------------------------------------------------------------------------- /site/commentator/public/css/featherlight.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Featherlight - ultra slim jQuery lightbox 3 | * Version 1.7.13 - http://noelboss.github.io/featherlight/ 4 | * 5 | * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com) 6 | * MIT Licensed. 7 | **/ 8 | html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}} -------------------------------------------------------------------------------- /site/commentator/public/css/hugo-theme.css: -------------------------------------------------------------------------------- 1 | /* Insert here special css for hugo theme, on top of any other imported css */ 2 | 3 | 4 | /* Table of contents */ 5 | 6 | .progress ul { 7 | list-style: none; 8 | margin: 0; 9 | padding: 0 15px; 10 | } 11 | 12 | #TableOfContents { 13 | font-size: 13px !important; 14 | max-height: 85vh; 15 | overflow: auto; 16 | padding: 15px 5px !important; 17 | } 18 | 19 | #TableOfContents > ul > li > a { 20 | font-weight: bold; 21 | } 22 | 23 | body { 24 | font-size: 16px !important; 25 | color: #323232 !important; 26 | } 27 | 28 | #body a.highlight, #body a.highlight:hover, #body a.highlight:focus { 29 | text-decoration: none; 30 | outline: none; 31 | outline: 0; 32 | } 33 | #body a.highlight { 34 | line-height: 1.1; 35 | display: inline-block; 36 | } 37 | #body a.highlight:after { 38 | display: block; 39 | content: ""; 40 | height: 1px; 41 | width: 0%; 42 | background-color: #0082a7; /*#CE3B2F*/ 43 | -webkit-transition: width 0.5s ease; 44 | -moz-transition: width 0.5s ease; 45 | -ms-transition: width 0.5s ease; 46 | transition: width 0.5s ease; 47 | } 48 | #body a.highlight:hover:after, #body a.highlight:focus:after { 49 | width: 100%; 50 | } 51 | .progress { 52 | position:absolute; 53 | background-color: rgba(246, 246, 246, 0.97); 54 | width: auto; 55 | border: thin solid #ECECEC; 56 | display:none; 57 | z-index:200; 58 | } 59 | 60 | #toc-menu { 61 | border-right: thin solid #DAD8D8 !important; 62 | padding-right: 1rem !important; 63 | margin-right: 0.5rem !important; 64 | } 65 | 66 | #sidebar-toggle-span { 67 | border-right: thin solid #DAD8D8 !important; 68 | padding-right: 0.5rem !important; 69 | margin-right: 1rem !important; 70 | } 71 | 72 | .btn { 73 | display: inline-block !important; 74 | padding: 6px 12px !important; 75 | margin-bottom: 0 !important; 76 | font-size: 14px !important; 77 | font-weight: normal !important; 78 | line-height: 1.42857143 !important; 79 | text-align: center !important; 80 | white-space: nowrap !important; 81 | vertical-align: middle !important; 82 | -ms-touch-action: manipulation !important; 83 | touch-action: manipulation !important; 84 | cursor: pointer !important; 85 | -webkit-user-select: none !important; 86 | -moz-user-select: none !important; 87 | -ms-user-select: none !important; 88 | user-select: none !important; 89 | background-image: none !important; 90 | border: 1px solid transparent !important; 91 | border-radius: 4px !important; 92 | -webkit-transition: all 0.15s !important; 93 | -moz-transition: all 0.15s !important; 94 | transition: all 0.15s !important; 95 | } 96 | .btn:focus { 97 | /*outline: thin dotted; 98 | outline: 5px auto -webkit-focus-ring-color; 99 | outline-offset: -2px;*/ 100 | outline: none !important; 101 | } 102 | .btn:hover, 103 | .btn:focus { 104 | color: #2b2b2b !important; 105 | text-decoration: none !important; 106 | } 107 | 108 | .btn-default { 109 | color: #333 !important; 110 | background-color: #fff !important; 111 | border-color: #ccc !important; 112 | } 113 | .btn-default:hover, 114 | .btn-default:focus, 115 | .btn-default:active { 116 | color: #fff !important; 117 | background-color: #9e9e9e !important; 118 | border-color: #9e9e9e !important; 119 | } 120 | .btn-default:active { 121 | background-image: none !important; 122 | } 123 | 124 | /* anchors */ 125 | .anchor { 126 | color: #00bdf3; 127 | font-size: 0.5em; 128 | cursor:pointer; 129 | visibility:hidden; 130 | margin-left: 0.5em; 131 | position: absolute; 132 | margin-top:0.1em; 133 | } 134 | 135 | h2:hover .anchor, h3:hover .anchor, h4:hover .anchor, h5:hover .anchor, h6:hover .anchor { 136 | visibility:visible; 137 | } 138 | 139 | /* Redfines headers style */ 140 | 141 | h2, h3, h4, h5, h6 { 142 | font-weight: 400; 143 | line-height: 1.1; 144 | } 145 | 146 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { 147 | font-weight: inherit; 148 | } 149 | 150 | h2 { 151 | font-size: 2.5rem; 152 | line-height: 110% !important; 153 | margin: 2.5rem 0 1.5rem 0; 154 | } 155 | 156 | h3 { 157 | font-size: 2rem; 158 | line-height: 110% !important; 159 | margin: 2rem 0 1rem 0; 160 | } 161 | 162 | h4 { 163 | font-size: 1.5rem; 164 | line-height: 110% !important; 165 | margin: 1.5rem 0 0.75rem 0; 166 | } 167 | 168 | h5 { 169 | font-size: 1rem; 170 | line-height: 110% !important; 171 | margin: 1rem 0 0.2rem 0; 172 | } 173 | 174 | h6 { 175 | font-size: 0.5rem; 176 | line-height: 110% !important; 177 | margin: 0.5rem 0 0.2rem 0; 178 | } 179 | 180 | p { 181 | margin: 1rem 0; 182 | } 183 | 184 | figcaption h4 { 185 | font-weight: 300 !important; 186 | opacity: .85; 187 | font-size: 1em; 188 | text-align: center; 189 | margin-top: -1.5em; 190 | } 191 | 192 | .select-style { 193 | border: 0; 194 | width: 150px; 195 | border-radius: 0px; 196 | overflow: hidden; 197 | display: inline-flex; 198 | } 199 | 200 | .select-style svg { 201 | fill: #ccc; 202 | width: 14px; 203 | height: 14px; 204 | pointer-events: none; 205 | margin: auto; 206 | } 207 | 208 | .select-style svg:hover { 209 | fill: #e6e6e6; 210 | } 211 | 212 | .select-style select { 213 | padding: 0; 214 | width: 130%; 215 | border: none; 216 | box-shadow: none; 217 | background: transparent; 218 | background-image: none; 219 | -webkit-appearance: none; 220 | margin: auto; 221 | margin-left: 0px; 222 | margin-right: -20px; 223 | } 224 | 225 | .select-style select:focus { 226 | outline: none; 227 | } 228 | 229 | .select-style :hover { 230 | cursor: pointer; 231 | } 232 | 233 | @media only all and (max-width: 47.938em) { 234 | #breadcrumbs .links, #top-github-link-text { 235 | display: none; 236 | } 237 | } 238 | 239 | .is-sticky #top-bar { 240 | box-shadow: -1px 2px 5px 1px rgba(0, 0, 0, 0.1); 241 | } -------------------------------------------------------------------------------- /site/commentator/public/css/hybrid.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid) 4 | 5 | */ 6 | 7 | /*background color*/ 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #1d1f21; 13 | } 14 | 15 | /*selection color*/ 16 | .hljs::selection, 17 | .hljs span::selection { 18 | background: #373b41; 19 | } 20 | 21 | .hljs::-moz-selection, 22 | .hljs span::-moz-selection { 23 | background: #373b41; 24 | } 25 | 26 | /*foreground color*/ 27 | .hljs { 28 | color: #c5c8c6; 29 | } 30 | 31 | /*color: fg_yellow*/ 32 | .hljs-title, 33 | .hljs-name { 34 | color: #f0c674; 35 | } 36 | 37 | /*color: fg_comment*/ 38 | .hljs-comment, 39 | .hljs-meta, 40 | .hljs-meta .hljs-keyword { 41 | color: #707880; 42 | } 43 | 44 | /*color: fg_red*/ 45 | .hljs-number, 46 | .hljs-symbol, 47 | .hljs-literal, 48 | .hljs-deletion, 49 | .hljs-link { 50 | color: #cc6666 51 | } 52 | 53 | /*color: fg_green*/ 54 | .hljs-string, 55 | .hljs-doctag, 56 | .hljs-addition, 57 | .hljs-regexp, 58 | .hljs-selector-attr, 59 | .hljs-selector-pseudo { 60 | color: #b5bd68; 61 | } 62 | 63 | /*color: fg_purple*/ 64 | .hljs-attribute, 65 | .hljs-code, 66 | .hljs-selector-id { 67 | color: #b294bb; 68 | } 69 | 70 | /*color: fg_blue*/ 71 | .hljs-keyword, 72 | .hljs-selector-tag, 73 | .hljs-bullet, 74 | .hljs-tag { 75 | color: #81a2be; 76 | } 77 | 78 | /*color: fg_aqua*/ 79 | .hljs-subst, 80 | .hljs-variable, 81 | .hljs-template-tag, 82 | .hljs-template-variable { 83 | color: #8abeb7; 84 | } 85 | 86 | /*color: fg_orange*/ 87 | .hljs-type, 88 | .hljs-built_in, 89 | .hljs-builtin-name, 90 | .hljs-quote, 91 | .hljs-section, 92 | .hljs-selector-class { 93 | color: #de935f; 94 | } 95 | 96 | .hljs-emphasis { 97 | font-style: italic; 98 | } 99 | 100 | .hljs-strong { 101 | font-weight: bold; 102 | } 103 | -------------------------------------------------------------------------------- /site/commentator/public/css/perfect-scrollbar.min.css: -------------------------------------------------------------------------------- 1 | /* perfect-scrollbar v0.6.13 */ 2 | .ps-container{-ms-touch-action:auto;touch-action:auto;overflow:hidden !important;-ms-overflow-style:none}@supports (-ms-overflow-style: none){.ps-container{overflow:auto !important}}@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none){.ps-container{overflow:auto !important}}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block;background-color:transparent}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;bottom:0px;height:15px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;-o-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;-moz-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;bottom:2px;height:6px}.ps-container>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x,.ps-container>.ps-scrollbar-x-rail:active>.ps-scrollbar-x{height:11px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;right:0;width:15px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out;-o-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;-moz-transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out;transition:background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out;right:2px;width:6px}.ps-container>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y,.ps-container>.ps-scrollbar-y-rail:active>.ps-scrollbar-y{width:11px}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999;height:11px}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999;width:11px}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999} 3 | -------------------------------------------------------------------------------- /site/commentator/public/css/tabs.css: -------------------------------------------------------------------------------- 1 | #body .tab-nav-button { 2 | border-width: 1px 1px 1px 1px !important; 3 | border-color: #ccc !important; 4 | border-radius: 4px 4px 0 0 !important; 5 | background-color: #ddd !important; 6 | float: left; 7 | display: block; 8 | position: relative; 9 | margin-left: 4px; 10 | bottom: -1px; 11 | } 12 | #body .tab-nav-button:first-child { 13 | margin-left: 0px; 14 | } 15 | #body .tab-nav-button.active { 16 | background-color: #fff !important; 17 | border-bottom-color: #fff !important; 18 | } 19 | 20 | #body .tab-panel { 21 | margin-top: 32px; 22 | margin-bottom: 32px; 23 | } 24 | #body .tab-content { 25 | display: block; 26 | clear: both; 27 | padding: 8px; 28 | border-width: 1px; 29 | border-style: solid; 30 | border-color: #ccc; 31 | } 32 | #body .tab-content .tab-item{ 33 | display: none; 34 | } 35 | 36 | #body .tab-content .tab-item.active{ 37 | display: block; 38 | } 39 | 40 | #body .tab-item pre{ 41 | margin-bottom: 0; 42 | margin-top: 0; 43 | } 44 | -------------------------------------------------------------------------------- /site/commentator/public/css/tags.css: -------------------------------------------------------------------------------- 1 | /* Tags */ 2 | 3 | #head-tags{ 4 | margin-left:1em; 5 | margin-top:1em; 6 | } 7 | 8 | #body .tags a.tag-link { 9 | display: inline-block; 10 | line-height: 2em; 11 | font-size: 0.8em; 12 | position: relative; 13 | margin: 0 16px 8px 0; 14 | padding: 0 10px 0 12px; 15 | background: #8451a1; 16 | 17 | -webkit-border-bottom-right-radius: 3px; 18 | border-bottom-right-radius: 3px; 19 | -webkit-border-top-right-radius: 3px; 20 | border-top-right-radius: 3px; 21 | 22 | -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2); 23 | box-shadow: 0 1px 2px rgba(0,0,0,0.2); 24 | color: #fff; 25 | } 26 | 27 | #body .tags a.tag-link:before { 28 | content: ""; 29 | position: absolute; 30 | top:0; 31 | left: -1em; 32 | width: 0; 33 | height: 0; 34 | border-color: transparent #8451a1 transparent transparent; 35 | border-style: solid; 36 | border-width: 1em 1em 1em 0; 37 | } 38 | 39 | #body .tags a.tag-link:after { 40 | content: ""; 41 | position: absolute; 42 | top: 10px; 43 | left: 1px; 44 | width: 5px; 45 | height: 5px; 46 | -webkit-border-radius: 50%; 47 | border-radius: 100%; 48 | background: #fff; 49 | } 50 | -------------------------------------------------------------------------------- /site/commentator/public/css/theme-blue.css: -------------------------------------------------------------------------------- 1 | 2 | :root{ 3 | 4 | --MAIN-TEXT-color:#323232; /* Color of text by default */ 5 | --MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */ 6 | --MAIN-LINK-color:#1C90F3; /* Color of links */ 7 | --MAIN-LINK-HOVER-color:#167ad0; /* Color of hovered links */ 8 | --MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */ 9 | 10 | --MENU-HOME-LINK-color: #323232; /* Color of the home button text */ 11 | --MENU-HOME-LINK-HOVER-color: #5e5e5e; /* Color of the hovered home button text */ 12 | 13 | --MENU-HEADER-BG-color:#1C90F3; /* Background color of menu header */ 14 | --MENU-HEADER-BORDER-color:#33a1ff; /*Color of menu header border */ 15 | 16 | --MENU-SEARCH-BG-color:#167ad0; /* Search field background color (by default borders + icons) */ 17 | --MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */ 18 | --MENU-SEARCH-BOX-ICONS-color: #a1d2fd; /* Override search field icons color */ 19 | 20 | --MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */ 21 | --MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */ 22 | --MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */ 23 | --MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */ 24 | --MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */ 25 | --MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */ 26 | 27 | --MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */ 28 | --MENU-SECTION-HR-color: #20272b; /* Color of
separator in menu */ 29 | 30 | } 31 | 32 | body { 33 | color: var(--MAIN-TEXT-color) !important; 34 | } 35 | 36 | textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus { 37 | border-color: none; 38 | box-shadow: none; 39 | } 40 | 41 | h2, h3, h4, h5 { 42 | color: var(--MAIN-TITLES-TEXT-color) !important; 43 | } 44 | 45 | a { 46 | color: var(--MAIN-LINK-color); 47 | } 48 | 49 | .anchor { 50 | color: var(--MAIN-ANCHOR-color); 51 | } 52 | 53 | a:hover { 54 | color: var(--MAIN-LINK-HOVER-color); 55 | } 56 | 57 | #sidebar ul li.visited > a .read-icon { 58 | color: var(--MENU-VISITED-color); 59 | } 60 | 61 | #body a.highlight:after { 62 | display: block; 63 | content: ""; 64 | height: 1px; 65 | width: 0%; 66 | -webkit-transition: width 0.5s ease; 67 | -moz-transition: width 0.5s ease; 68 | -ms-transition: width 0.5s ease; 69 | transition: width 0.5s ease; 70 | background-color: var(--MAIN-LINK-HOVER-color); 71 | } 72 | #sidebar { 73 | background-color: var(--MENU-SECTIONS-BG-color); 74 | } 75 | #sidebar #header-wrapper { 76 | background: var(--MENU-HEADER-BG-color); 77 | color: var(--MENU-SEARCH-BOX-color); 78 | border-color: var(--MENU-HEADER-BORDER-color); 79 | } 80 | #sidebar .searchbox { 81 | border-color: var(--MENU-SEARCH-BOX-color); 82 | background: var(--MENU-SEARCH-BG-color); 83 | } 84 | #sidebar ul.topics > li.parent, #sidebar ul.topics > li.active { 85 | background: var(--MENU-SECTIONS-ACTIVE-BG-color); 86 | } 87 | #sidebar .searchbox * { 88 | color: var(--MENU-SEARCH-BOX-ICONS-color); 89 | } 90 | 91 | #sidebar a { 92 | color: var(--MENU-SECTIONS-LINK-color); 93 | } 94 | 95 | #sidebar a:hover { 96 | color: var(--MENU-SECTIONS-LINK-HOVER-color); 97 | } 98 | 99 | #sidebar ul li.active > a { 100 | background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color); 101 | color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important; 102 | } 103 | 104 | #sidebar hr { 105 | border-color: var(--MENU-SECTION-HR-color); 106 | } 107 | 108 | #body .tags a.tag-link { 109 | background-color: var(--MENU-HEADER-BG-color); 110 | } 111 | 112 | #body .tags a.tag-link:before { 113 | border-right-color: var(--MENU-HEADER-BG-color); 114 | } 115 | 116 | #homelinks { 117 | background: var(--MENU-HEADER-BG-color); 118 | background-color: var(--MENU-HEADER-BORDER-color); 119 | border-bottom-color: var(--MENU-HEADER-BORDER-color); 120 | } 121 | 122 | #homelinks a { 123 | color: var(--MENU-HOME-LINK-color); 124 | } 125 | 126 | #homelinks a:hover { 127 | color: var(--MENU-HOME-LINK-HOVERED-color); 128 | } -------------------------------------------------------------------------------- /site/commentator/public/css/theme-commentator.css: -------------------------------------------------------------------------------- 1 | 2 | :root{ 3 | 4 | --MAIN-TEXT-color:#323232; /* Color of text by default */ 5 | --MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */ 6 | --MAIN-LINK-color: #0007c9; /* Color of links */ 7 | --MAIN-LINK-HOVER-color:#0007c9; /* Color of hovered links */ 8 | --MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */ 9 | 10 | --MENU-HOME-LINK-color: #323232; /* Color of the home button text */ 11 | --MENU-HOME-LINK-HOVER-color: #5e5e5e; /* Color of the hovered home button text */ 12 | 13 | --MENU-HEADER-BG-color: #0199b1 ; /* Background color of menu header */ 14 | --MENU-HEADER-BORDER-color :#fff; /*Color of menu header border */ 15 | 16 | --MENU-SEARCH-BG-color: #e6e6e6; /* Search field background color (by default borders + icons) */ 17 | --MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */ 18 | --MENU-SEARCH-BOX-ICONS-color: #33a1ff; /* Override search field icons color */ 19 | 20 | --MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */ 21 | --MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */ 22 | --MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */ 23 | --MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */ 24 | --MENU-SECTION-ACTIVE-CATEGORY-color: black; /* Color of active category text */ 25 | --MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */ 26 | 27 | --MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */ 28 | --MENU-SECTION-HR-color: #20272b; /* Color of
separator in menu */ 29 | 30 | } 31 | 32 | body { 33 | color: var(--MAIN-TEXT-color) !important; 34 | } 35 | 36 | textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus { 37 | border-color: none; 38 | box-shadow: none; 39 | } 40 | 41 | h2, h3, h4, h5 { 42 | color: var(--MAIN-TITLES-TEXT-color) !important; 43 | } 44 | 45 | a { 46 | color: var(--MAIN-LINK-color); 47 | } 48 | 49 | .anchor { 50 | color: var(--MAIN-ANCHOR-color); 51 | } 52 | 53 | a:hover { 54 | color: var(--MAIN-LINK-HOVER-color); 55 | } 56 | 57 | #sidebar ul li.visited > a .read-icon { 58 | color: var(--MENU-VISITED-color); 59 | } 60 | 61 | #body a.highlight:after { 62 | display: block; 63 | content: ""; 64 | height: 1px; 65 | width: 0%; 66 | -webkit-transition: width 0.5s ease; 67 | -moz-transition: width 0.5s ease; 68 | -ms-transition: width 0.5s ease; 69 | transition: width 0.5s ease; 70 | background-color: var(--MAIN-LINK-HOVER-color); 71 | } 72 | #sidebar { 73 | background-color: var(--MENU-SECTIONS-BG-color); 74 | } 75 | #sidebar #header-wrapper { 76 | background: var(--MENU-HEADER-BG-color); 77 | color: var(--MENU-SEARCH-BOX-color); 78 | border-color: var(--MENU-HEADER-BORDER-color); 79 | } 80 | #sidebar .searchbox { 81 | border-color: var(--MENU-SEARCH-BOX-color); 82 | background: var(--MENU-SEARCH-BG-color); 83 | } 84 | #sidebar ul.topics > li.parent, #sidebar ul.topics > li.active { 85 | background: var(--MENU-SECTIONS-ACTIVE-BG-color); 86 | } 87 | #sidebar .searchbox * { 88 | color: var(--MENU-SEARCH-BOX-ICONS-color); 89 | } 90 | 91 | #sidebar a { 92 | color: var(--MENU-SECTIONS-LINK-color); 93 | } 94 | 95 | #sidebar a:hover { 96 | color: var(--MENU-SECTIONS-LINK-HOVER-color); 97 | } 98 | 99 | #sidebar ul li.active > a { 100 | background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color); 101 | color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important; 102 | } 103 | 104 | #sidebar hr { 105 | border-color: var(--MENU-SECTION-HR-color); 106 | } 107 | 108 | #body .tags a.tag-link { 109 | background-color: var(--MENU-HEADER-BG-color); 110 | } 111 | 112 | #body .tags a.tag-link:before { 113 | border-right-color: var(--MENU-HEADER-BG-color); 114 | } 115 | 116 | #homelinks { 117 | background: var(--MENU-HEADER-BG-color); 118 | background-color: var(--MENU-HEADER-BORDER-color); 119 | border-bottom-color: var(--MENU-HEADER-BORDER-color); 120 | } 121 | 122 | #homelinks a { 123 | color: var(--MENU-HOME-LINK-color); 124 | } 125 | 126 | #homelinks a:hover { 127 | color: var(--MENU-HOME-LINK-HOVERED-color); 128 | } 129 | -------------------------------------------------------------------------------- /site/commentator/public/css/theme-green.css: -------------------------------------------------------------------------------- 1 | 2 | :root{ 3 | 4 | --MAIN-TEXT-color:#323232; /* Color of text by default */ 5 | --MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */ 6 | --MAIN-LINK-color:#599a3e; /* Color of links */ 7 | --MAIN-LINK-HOVER-color:#3f6d2c; /* Color of hovered links */ 8 | --MAIN-ANCHOR-color: #599a3e; /* color of anchors on titles */ 9 | 10 | --MENU-HOME-LINK-color: #323232; /* Color of the home button text */ 11 | --MENU-HOME-LINK-HOVER-color: #5e5e5e; /* Color of the hovered home button text */ 12 | 13 | --MENU-HEADER-BG-color:#74b559; /* Background color of menu header */ 14 | --MENU-HEADER-BORDER-color:#9cd484; /*Color of menu header border */ 15 | 16 | --MENU-SEARCH-BG-color:#599a3e; /* Search field background color (by default borders + icons) */ 17 | --MENU-SEARCH-BOX-color: #84c767; /* Override search field border color */ 18 | --MENU-SEARCH-BOX-ICONS-color: #c7f7c4; /* Override search field icons color */ 19 | 20 | --MENU-SECTIONS-ACTIVE-BG-color:#1b211c; /* Background color of the active section and its childs */ 21 | --MENU-SECTIONS-BG-color:#222723; /* Background color of other sections */ 22 | --MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */ 23 | --MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */ 24 | --MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */ 25 | --MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */ 26 | 27 | --MENU-VISITED-color: #599a3e; /* Color of 'page visited' icons in menu */ 28 | --MENU-SECTION-HR-color: #18211c; /* Color of
separator in menu */ 29 | 30 | } 31 | 32 | body { 33 | color: var(--MAIN-TEXT-color) !important; 34 | } 35 | 36 | textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus { 37 | border-color: none; 38 | box-shadow: none; 39 | } 40 | 41 | h2, h3, h4, h5 { 42 | color: var(--MAIN-TITLES-TEXT-color) !important; 43 | } 44 | 45 | a { 46 | color: var(--MAIN-LINK-color); 47 | } 48 | 49 | .anchor { 50 | color: var(--MAIN-ANCHOR-color); 51 | } 52 | 53 | a:hover { 54 | color: var(--MAIN-LINK-HOVER-color); 55 | } 56 | 57 | #sidebar ul li.visited > a .read-icon { 58 | color: var(--MENU-VISITED-color); 59 | } 60 | 61 | #body a.highlight:after { 62 | display: block; 63 | content: ""; 64 | height: 1px; 65 | width: 0%; 66 | -webkit-transition: width 0.5s ease; 67 | -moz-transition: width 0.5s ease; 68 | -ms-transition: width 0.5s ease; 69 | transition: width 0.5s ease; 70 | background-color: var(--MAIN-LINK-HOVER-color); 71 | } 72 | #sidebar { 73 | background-color: var(--MENU-SECTIONS-BG-color); 74 | } 75 | #sidebar #header-wrapper { 76 | background: var(--MENU-HEADER-BG-color); 77 | color: var(--MENU-SEARCH-BOX-color); 78 | border-color: var(--MENU-HEADER-BORDER-color); 79 | } 80 | #sidebar .searchbox { 81 | border-color: var(--MENU-SEARCH-BOX-color); 82 | background: var(--MENU-SEARCH-BG-color); 83 | } 84 | #sidebar ul.topics > li.parent, #sidebar ul.topics > li.active { 85 | background: var(--MENU-SECTIONS-ACTIVE-BG-color); 86 | } 87 | #sidebar .searchbox * { 88 | color: var(--MENU-SEARCH-BOX-ICONS-color); 89 | } 90 | 91 | #sidebar a { 92 | color: var(--MENU-SECTIONS-LINK-color); 93 | } 94 | 95 | #sidebar a:hover { 96 | color: var(--MENU-SECTIONS-LINK-HOVER-color); 97 | } 98 | 99 | #sidebar ul li.active > a { 100 | background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color); 101 | color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important; 102 | } 103 | 104 | #sidebar hr { 105 | border-color: var(--MENU-SECTION-HR-color); 106 | } 107 | 108 | #body .tags a.tag-link { 109 | background-color: var(--MENU-HEADER-BG-color); 110 | } 111 | 112 | #body .tags a.tag-link:before { 113 | border-right-color: var(--MENU-HEADER-BG-color); 114 | } 115 | 116 | #homelinks { 117 | background: var(--MENU-HEADER-BG-color); 118 | background-color: var(--MENU-HEADER-BORDER-color); 119 | border-bottom-color: var(--MENU-HEADER-BORDER-color); 120 | } 121 | 122 | #homelinks a { 123 | color: var(--MENU-HOME-LINK-color); 124 | } 125 | 126 | #homelinks a:hover { 127 | color: var(--MENU-HOME-LINK-HOVERED-color); 128 | } -------------------------------------------------------------------------------- /site/commentator/public/css/theme-red.css: -------------------------------------------------------------------------------- 1 | 2 | :root{ 3 | 4 | --MAIN-TEXT-color:#323232; /* Color of text by default */ 5 | --MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */ 6 | --MAIN-LINK-color:#f31c1c; /* Color of links */ 7 | --MAIN-LINK-HOVER-color:#d01616; /* Color of hovered links */ 8 | --MAIN-ANCHOR-color: #f31c1c; /* color of anchors on titles */ 9 | 10 | --MENU-HOME-LINK-color: #ccc; /* Color of the home button text */ 11 | --MENU-HOME-LINK-HOVER-color: #e6e6e6; /* Color of the hovered home button text */ 12 | 13 | --MENU-HEADER-BG-color:#dc1010; /* Background color of menu header */ 14 | --MENU-HEADER-BORDER-color:#e23131; /*Color of menu header border */ 15 | 16 | --MENU-SEARCH-BG-color:#b90000; /* Search field background color (by default borders + icons) */ 17 | --MENU-SEARCH-BOX-color: #ef2020; /* Override search field border color */ 18 | --MENU-SEARCH-BOX-ICONS-color: #fda1a1; /* Override search field icons color */ 19 | 20 | --MENU-SECTIONS-ACTIVE-BG-color:#2b2020; /* Background color of the active section and its childs */ 21 | --MENU-SECTIONS-BG-color:#312525; /* Background color of other sections */ 22 | --MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */ 23 | --MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */ 24 | --MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */ 25 | --MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */ 26 | 27 | --MENU-VISITED-color: #ff3333; /* Color of 'page visited' icons in menu */ 28 | --MENU-SECTION-HR-color: #2b2020; /* Color of
separator in menu */ 29 | 30 | } 31 | 32 | body { 33 | color: var(--MAIN-TEXT-color) !important; 34 | } 35 | 36 | textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus { 37 | border-color: none; 38 | box-shadow: none; 39 | } 40 | 41 | h2, h3, h4, h5 { 42 | color: var(--MAIN-TITLES-TEXT-color) !important; 43 | } 44 | 45 | a { 46 | color: var(--MAIN-LINK-color); 47 | } 48 | 49 | .anchor { 50 | color: var(--MAIN-ANCHOR-color); 51 | } 52 | 53 | a:hover { 54 | color: var(--MAIN-LINK-HOVER-color); 55 | } 56 | 57 | #sidebar ul li.visited > a .read-icon { 58 | color: var(--MENU-VISITED-color); 59 | } 60 | 61 | #body a.highlight:after { 62 | display: block; 63 | content: ""; 64 | height: 1px; 65 | width: 0%; 66 | -webkit-transition: width 0.5s ease; 67 | -moz-transition: width 0.5s ease; 68 | -ms-transition: width 0.5s ease; 69 | transition: width 0.5s ease; 70 | background-color: var(--MAIN-LINK-HOVER-color); 71 | } 72 | #sidebar { 73 | background-color: var(--MENU-SECTIONS-BG-color); 74 | } 75 | #sidebar #header-wrapper { 76 | background: var(--MENU-HEADER-BG-color); 77 | color: var(--MENU-SEARCH-BOX-color); 78 | border-color: var(--MENU-HEADER-BORDER-color); 79 | } 80 | #sidebar .searchbox { 81 | border-color: var(--MENU-SEARCH-BOX-color); 82 | background: var(--MENU-SEARCH-BG-color); 83 | } 84 | #sidebar ul.topics > li.parent, #sidebar ul.topics > li.active { 85 | background: var(--MENU-SECTIONS-ACTIVE-BG-color); 86 | } 87 | #sidebar .searchbox * { 88 | color: var(--MENU-SEARCH-BOX-ICONS-color); 89 | } 90 | 91 | #sidebar a { 92 | color: var(--MENU-SECTIONS-LINK-color); 93 | } 94 | 95 | #sidebar a:hover { 96 | color: var(--MENU-SECTIONS-LINK-HOVER-color); 97 | } 98 | 99 | #sidebar ul li.active > a { 100 | background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color); 101 | color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important; 102 | } 103 | 104 | #sidebar hr { 105 | border-color: var(--MENU-SECTION-HR-color); 106 | } 107 | 108 | #body .tags a.tag-link { 109 | background-color: var(--MENU-HEADER-BG-color); 110 | } 111 | 112 | #body .tags a.tag-link:before { 113 | border-right-color: var(--MENU-HEADER-BG-color); 114 | } 115 | 116 | #homelinks { 117 | background: var(--MENU-HEADER-BG-color); 118 | background-color: var(--MENU-HEADER-BORDER-color); 119 | border-bottom-color: var(--MENU-HEADER-BORDER-color); 120 | } 121 | 122 | #homelinks a { 123 | color: var(--MENU-HOME-LINK-color); 124 | } 125 | 126 | #homelinks a:hover { 127 | color: var(--MENU-HOME-LINK-HOVERED-color); 128 | } -------------------------------------------------------------------------------- /site/commentator/public/fonts/Inconsolata.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Inconsolata.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Inconsolata.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Inconsolata.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Inconsolata.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-Normal-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-Normal-webfont.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-Normal-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-Normal-webfont.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-Normal-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-Normal-webfont.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-Normal-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-Normal-webfont.woff2 -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Novecentosanswide-UltraLight-webfont.woff2 -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_200.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_200.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_200.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_200.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_200.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_200.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_200.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_200.woff2 -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_300.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_300.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_300.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_300.woff2 -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_500.eot -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_500.ttf -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_500.woff -------------------------------------------------------------------------------- /site/commentator/public/fonts/Work_Sans_500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/fonts/Work_Sans_500.woff2 -------------------------------------------------------------------------------- /site/commentator/public/health.html: -------------------------------------------------------------------------------- 1 | It works! 2 | -------------------------------------------------------------------------------- /site/commentator/public/howto/configuration/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Configuration on Commentator 5 | https://www.commentator.mcorbin.fr/howto/configuration/ 6 | Recent content in Configuration on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/howto/get-build/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Get and launch Commentator on Commentator 5 | https://www.commentator.mcorbin.fr/howto/get-build/ 6 | Recent content in Get and launch Commentator on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/howto/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | How to on Commentator 5 | https://www.commentator.mcorbin.fr/howto/ 6 | Recent content in How to on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/howto/use-it/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Use it on Commentator 5 | https://www.commentator.mcorbin.fr/howto/use-it/ 6 | Recent content in Use it on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/images/clippy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/commentator/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/images/favicon.png -------------------------------------------------------------------------------- /site/commentator/public/images/gopher-404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/images/gopher-404.jpg -------------------------------------------------------------------------------- /site/commentator/public/img/commentator_presentation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/img/commentator_presentation.jpg -------------------------------------------------------------------------------- /site/commentator/public/img/mirabelle_presentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/img/mirabelle_presentation.png -------------------------------------------------------------------------------- /site/commentator/public/img/mirabelle_streams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcorbin/commentator/25093372506d2f0e598f689e3f9e393e49f16732/site/commentator/public/img/mirabelle_streams.png -------------------------------------------------------------------------------- /site/commentator/public/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Commentator 5 | https://www.commentator.mcorbin.fr/ 6 | Recent content on Commentator 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | -------------------------------------------------------------------------------- /site/commentator/public/js/auto-complete.js: -------------------------------------------------------------------------------- 1 | // JavaScript autoComplete v1.0.4 2 | // https://github.com/Pixabay/JavaScript-autoComplete 3 | var autoComplete=function(){function e(e){function t(e,t){return e.classList?e.classList.contains(t):new RegExp("\\b"+t+"\\b").test(e.className)}function o(e,t,o){e.attachEvent?e.attachEvent("on"+t,o):e.addEventListener(t,o)}function s(e,t,o){e.detachEvent?e.detachEvent("on"+t,o):e.removeEventListener(t,o)}function n(e,s,n,l){o(l||document,s,function(o){for(var s,l=o.target||o.srcElement;l&&!(s=t(l,e));)l=l.parentElement;s&&n.call(l,o)})}if(document.querySelector){var l={selector:0,source:0,minChars:3,delay:150,offsetLeft:0,offsetTop:1,cache:1,menuClass:"",renderItem:function(e,t){t=t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&");var o=new RegExp("("+t.split(" ").join("|")+")","gi");return'
'+e.replace(o,"$1")+"
"},onSelect:function(){}};for(var c in e)e.hasOwnProperty(c)&&(l[c]=e[c]);for(var a="object"==typeof l.selector?[l.selector]:document.querySelectorAll(l.selector),u=0;u0?i.sc.scrollTop=n+i.sc.suggestionHeight+s-i.sc.maxHeight:0>n&&(i.sc.scrollTop=n+s)}else i.sc.scrollTop=0},o(window,"resize",i.updateSC),document.body.appendChild(i.sc),n("autocomplete-suggestion","mouseleave",function(){var e=i.sc.querySelector(".autocomplete-suggestion.selected");e&&setTimeout(function(){e.className=e.className.replace("selected","")},20)},i.sc),n("autocomplete-suggestion","mouseover",function(){var e=i.sc.querySelector(".autocomplete-suggestion.selected");e&&(e.className=e.className.replace("selected","")),this.className+=" selected"},i.sc),n("autocomplete-suggestion","mousedown",function(e){if(t(this,"autocomplete-suggestion")){var o=this.getAttribute("data-val");i.value=o,l.onSelect(e,o,this),i.sc.style.display="none"}},i.sc),i.blurHandler=function(){try{var e=document.querySelector(".autocomplete-suggestions:hover")}catch(t){var e=0}e?i!==document.activeElement&&setTimeout(function(){i.focus()},20):(i.last_val=i.value,i.sc.style.display="none",setTimeout(function(){i.sc.style.display="none"},350))},o(i,"blur",i.blurHandler);var r=function(e){var t=i.value;if(i.cache[t]=e,e.length&&t.length>=l.minChars){for(var o="",s=0;st||t>40)&&13!=t&&27!=t){var o=i.value;if(o.length>=l.minChars){if(o!=i.last_val){if(i.last_val=o,clearTimeout(i.timer),l.cache){if(o in i.cache)return void r(i.cache[o]);for(var s=1;s https://github.com/noelboss/featherlight/issues/317 9 | !function(u){"use strict";if(void 0!==u)if(u.fn.jquery.match(/-ajax/))"console"in window&&window.console.info("Featherlight needs regular jQuery, not the slim version.");else{var r=[],i=function(t){return r=u.grep(r,function(e){return e!==t&&0','
','",'
'+n.loading+"
","
",""].join("")),o="."+n.namespace+"-close"+(n.otherClose?","+n.otherClose:"");return n.$instance=i.clone().addClass(n.variant),n.$instance.on(n.closeTrigger+"."+n.namespace,function(e){if(!e.isDefaultPrevented()){var t=u(e.target);("background"===n.closeOnClick&&t.is("."+n.namespace)||"anywhere"===n.closeOnClick||t.closest(o).length)&&(n.close(e),e.preventDefault())}}),this},getContent:function(){if(!1!==this.persist&&this.$content)return this.$content;var t=this,e=this.constructor.contentFilters,n=function(e){return t.$currentTarget&&t.$currentTarget.attr(e)},r=n(t.targetAttr),i=t.target||r||"",o=e[t.type];if(!o&&i in e&&(o=e[i],i=t.target&&r),i=i||n("href")||"",!o)for(var a in e)t[a]&&(o=e[a],i=t[a]);if(!o){var s=i;if(i=null,u.each(t.contentFilters,function(){return(o=e[this]).test&&(i=o.test(s)),!i&&o.regex&&s.match&&s.match(o.regex)&&(i=s),!i}),!i)return"console"in window&&window.console.error("Featherlight: no content filter found "+(s?' for "'+s+'"':" (no target specified)")),!1}return o.process.call(t,i)},setContent:function(e){return this.$instance.removeClass(this.namespace+"-loading"),this.$instance.toggleClass(this.namespace+"-iframe",e.is("iframe")),this.$instance.find("."+this.namespace+"-inner").not(e).slice(1).remove().end().replaceWith(u.contains(this.$instance[0],e[0])?"":e),this.$content=e.addClass(this.namespace+"-inner"),this},open:function(t){var n=this;if(n.$instance.hide().appendTo(n.root),!(t&&t.isDefaultPrevented()||!1===n.beforeOpen(t))){t&&t.preventDefault();var e=n.getContent();if(e)return r.push(n),s(!0),n.$instance.fadeIn(n.openSpeed),n.beforeContent(t),u.when(e).always(function(e){n.setContent(e),n.afterContent(t)}).then(n.$instance.promise()).done(function(){n.afterOpen(t)})}return n.$instance.detach(),u.Deferred().reject().promise()},close:function(e){var t=this,n=u.Deferred();return!1===t.beforeClose(e)?n.reject():(0===i(t).length&&s(!1),t.$instance.fadeOut(t.closeSpeed,function(){t.$instance.detach(),t.afterClose(e),n.resolve()})),n.promise()},resize:function(e,t){if(e&&t&&(this.$content.css("width","").css("height",""),this.$content.parent().width()');return n.onload=function(){r.naturalWidth=n.width,r.naturalHeight=n.height,t.resolve(r)},n.onerror=function(){t.reject(r)},n.src=e,t.promise()}},html:{regex:/^\s*<[\w!][^<]*>/,process:function(e){return u(e)}},ajax:{regex:/./,process:function(e){var n=u.Deferred(),r=u("
").load(e,function(e,t){"error"!==t&&n.resolve(r.contents()),n.fail()});return n.promise()}},iframe:{process:function(e){var t=new u.Deferred,n=u("