├── Procfile ├── .gitignore ├── .github ├── CONTRIBUTING.md ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE │ ├── new-pronouns.md │ ├── feature_request.md │ └── bug_report.md ├── resources ├── pronouns.css ├── 500.html ├── log4j.xml ├── 404.html └── pronouns.tab ├── test └── pronouns │ ├── resource_test.clj │ ├── pages_test.clj │ └── util_test.clj ├── project.clj ├── src └── pronouns │ ├── config.clj │ ├── web.clj │ ├── util.clj │ └── pages.clj ├── .circleci └── config.yml ├── CODE_OF_CONDUCT.md ├── README.md └── COPYING /Procfile: -------------------------------------------------------------------------------- 1 | web: java $JVM_OPTS -cp target/pronouns-standalone.jar clojure.main -m pronouns.web 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | *jar 3 | /classes/ 4 | /.lein-deps-sum 5 | /.lein-failures 6 | /.lein-env 7 | /checkouts 8 | /.env 9 | /target 10 | .nrepl-port 11 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please check out the following resources: 2 | 3 | * [Info For Developers](../README.md#for-developers) 4 | * [FAQ](../README.md#FAQ) 5 | * [Code of Conduct](../CODE_OF_CONDUCT.md) 6 | -------------------------------------------------------------------------------- /resources/pronouns.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Futura, sans-serif; 3 | background-color: #F6CEFC; 4 | } 5 | 6 | footer { 7 | font-size: 0.8em; 8 | } 9 | 10 | .section { 11 | margin: 8px; 12 | padding: 4px 6px 4px 6px; 13 | border: 4px solid #EEEEEE; 14 | border-radius: 7px; 15 | } 16 | 17 | .examples { 18 | } 19 | 20 | .title { 21 | } 22 | 23 | .usage { 24 | } 25 | 26 | .contact { 27 | } 28 | 29 | .table { 30 | } 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Thanks for contributing! Please check the following things before submitting your PR :)* 2 | 3 | - [ ] PR message includes a link to the relevant issue(s) 💁‍♀️🖇️🧾 4 | - [ ] Commit messages are well-formatted 5 | (please follow [this guide](https://chris.beams.io/posts/git-commit/)) 📝📐 6 | - [ ] New features have test coverage 📋☑️☑️☑️ 7 | - [ ] The app boots and pronoun pages are served correctly 8 | (try `lein ring server`) 👩‍💻🚀 9 | -------------------------------------------------------------------------------- /test/pronouns/resource_test.clj: -------------------------------------------------------------------------------- 1 | (ns pronouns.resource-test 2 | (:require [pronouns.util :as util] 3 | [clojure.test :refer [deftest testing is]])) 4 | 5 | (deftest valid-pronouns-table 6 | (let [table (util/slurp-tabfile "resources/pronouns.tab")] 7 | (is table "pronouns.tab exists and is non-empty") 8 | (doseq [row table] 9 | (is (= (count row) 5) 10 | "row has five elements") 11 | (is (re-matches #".*sel(f|ves)$" (last row)) 12 | "final element is reflexive")))) 13 | -------------------------------------------------------------------------------- /resources/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 13 | 14 | 15 | 16 |

Error

17 |

Something went wrong. Try again, and if the problem persists 18 | please contact support.

19 | 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new-pronouns.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: New pronouns 3 | about: For requesting a new set of pronouns to pronoun.is 4 | labels: 5 | 6 | --- 7 | 8 | ### Link to fully filled-out pronoun.is link of your pronouns 9 | 10 | https://pronoun.is/a/b/c/d/e 11 | 12 | ### External link showing real-world usage of these pronouns 13 | 14 | https://example.com/whatever 15 | 16 | ### Should this pronoun set be included according to the [Philosophy on pronoun inclusion](/witch-house/pronoun.is/blob/master/README.md#philosophy-on-pronoun-inclusion)? 17 | 18 | yes/no 19 | -------------------------------------------------------------------------------- /resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /resources/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found 6 | 13 | 14 | 15 | 16 |

Page Not Found

17 |

There's no page at the address you requested. If you entered it 18 | by hand, check for typos. If you followed a link or a bookmark, 19 | it may need to be updated.

20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | labels: 5 | 6 | --- 7 | *please search the issues for duplicates and read the [FAQ](/witch-house/pronoun.is/blob/master/README.md#FAQ) 8 | before submitting a new issue :)* 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject witch-house/pronouns "1.12.0-SNAPSHOT" 2 | :description "Pronoun.is is a website for personal pronoun usage examples" 3 | :url "https://pronoun.is" 4 | :license "GNU Affero General Public License 3.0" 5 | :dependencies [[compojure "1.6.1"] 6 | [environ "1.1.0"] 7 | [hiccup "1.0.5"] 8 | [lambdaisland/ring.middleware.logger "0.5.1"] 9 | [org.clojure/clojure "1.9.0"] 10 | [ring/ring-devel "1.7.1"] 11 | [ring/ring-jetty-adapter "1.7.1"]] 12 | :min-lein-version "2.0.0" 13 | :plugins [[environ/environ.lein "0.2.1"] 14 | [lein-ring "0.9.7"]] 15 | :hooks [environ.leiningen.hooks] 16 | :uberjar-name "pronouns-standalone.jar" 17 | ;; FIXME morgan.astra <2018-11-14 Wed> 18 | ;; Is this production profile used for anything? 19 | :profiles {:production {:env {:production true}}} 20 | :ring {:handler pronouns.web/app}) 21 | -------------------------------------------------------------------------------- /test/pronouns/pages_test.clj: -------------------------------------------------------------------------------- 1 | (ns pronouns.pages-test 2 | (:require [pronouns.pages :as pages] 3 | [clojure.test :refer [deftest testing is are]])) 4 | 5 | (deftest prose-comma-list 6 | (testing "`prose-comma-list` turns a list of strings into a prose list" 7 | (are [v s] (= (pages/prose-comma-list v) s) 8 | ["foo" "bar" "baz" "bobble"] "foo, bar, baz, and bobble" 9 | ["foo" "bar" "baz"] "foo, bar, and baz" 10 | ["foo" "bar"] "foo and bar" 11 | ["foo"] "foo" 12 | [] ""))) 13 | 14 | (deftest lookup-pronouns 15 | (are [pronoun-strs pronouns] 16 | (= (pages/lookup-pronouns pronoun-strs) 17 | pronouns) 18 | ["she/her"] '(["she" "her" "her" "hers" "herself"]) 19 | ["she" "they"] '(["she" "her" "her" "hers" "herself"] 20 | ["they" "them" "their" "theirs" "themselves"]) 21 | ["she/her" "foo/bar"] '(["she" "her" "her" "hers" "herself"]) 22 | ["foo/bar"] '() 23 | ["a/b/c/d/e"] '(("a" "b" "c" "d" "e")))) 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | labels: 5 | 6 | --- 7 | *please search the issues for duplicates and read the [FAQ](/witch-house/pronoun.is/blob/master/README.md#FAQ) 8 | before submitting a new issue :)* 9 | 10 | 11 | **Describe the bug** 12 | A clear and concise description of what the bug is. 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behavior: 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Desktop (please complete the following information):** 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | - Device: [e.g. iPhone6] 34 | - OS: [e.g. iOS8.1] 35 | - Browser [e.g. stock browser, safari] 36 | - Version [e.g. 22] 37 | 38 | **Additional context** 39 | Add any other context about the problem here. 40 | -------------------------------------------------------------------------------- /src/pronouns/config.clj: -------------------------------------------------------------------------------- 1 | ;; pronoun.is - a website for pronoun usage examples 2 | ;; Copyright (C) 2014 - 2018 Morgan Astra 3 | 4 | ;; This program is free software: you can redistribute it and/or modify 5 | ;; it under the terms of the GNU Affero General Public License as 6 | ;; published by the Free Software Foundation, either version 3 of the 7 | ;; License, or (at your option) any later version. 8 | 9 | ;; This program is distributed in the hope that it will be useful, 10 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ;; GNU Affero General Public License for more details. 13 | 14 | ;; You should have received a copy of the GNU Affero General Public License 15 | ;; along with this program. If not, see 16 | 17 | (ns pronouns.config 18 | (:require [pronouns.util :as u])) 19 | 20 | (def pronouns-table 21 | (atom (u/slurp-tabfile "resources/pronouns.tab"))) 22 | 23 | (defn replace-value [old new] new) 24 | 25 | (defn reload-table! [] 26 | (swap! pronouns-table 27 | replace-value 28 | (u/slurp-tabfile "resources/pronouns.tab"))) 29 | 30 | -------------------------------------------------------------------------------- /resources/pronouns.tab: -------------------------------------------------------------------------------- 1 | she her her hers herself 2 | he him his his himself 3 | they them their theirs themselves 4 | ze hir hir hirs hirself 5 | ze zir zir zirs zirself 6 | xey xem xyr xyrs xemself 7 | ae aer aer aers aerself 8 | e em eir eirs emself 9 | ey em eir eirs eirself 10 | fae faer faer faers faerself 11 | fey fem feir feirs feirself 12 | hu hum hus hus humself 13 | it it its its itself 14 | jee jem jeir jeirs jemself 15 | kit kit kits kits kitself 16 | ne nem nir nirs nemself 17 | peh pehm peh's peh's pehself 18 | per per per pers perself 19 | sie hir hir hirs hirself 20 | se sim ser sers serself 21 | shi hir hir hirs hirself 22 | si hyr hyr hyrs hyrself 23 | they them their theirs themself 24 | thon thon thons thons thonself 25 | ve ver vis vis verself 26 | ve vem vir virs vemself 27 | vi ver ver vers verself 28 | vi vim vir virs vimself 29 | vi vim vim vims vimself 30 | xie xer xer xers xerself 31 | xe xem xyr xyrs xemself 32 | xey xem xeir xeirs xemself 33 | yo yo yos yos yosself 34 | ze zem zes zes zirself 35 | ze mer zer zers zemself 36 | zee zed zeta zetas zedself 37 | zie zir zir zirs zirself 38 | zie zem zes zes zirself 39 | zie hir hir hirs hirself 40 | zme zmyr zmyr zmyrs zmyrself 41 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Clojure CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-clojure/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: circleci/clojure:lein-2.7.1 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/postgres:9.4 16 | 17 | working_directory: ~/repo 18 | 19 | environment: 20 | LEIN_ROOT: "true" 21 | # Customize the JVM maximum heap limit 22 | JVM_OPTS: -Xmx3200m 23 | 24 | steps: 25 | - checkout 26 | 27 | # Download and cache dependencies 28 | - restore_cache: 29 | keys: 30 | - v1-dependencies-{{ checksum "project.clj" }} 31 | # fallback to using the latest cache if no exact match is found 32 | - v1-dependencies- 33 | 34 | - run: lein deps 35 | 36 | - save_cache: 37 | paths: 38 | - ~/.m2 39 | key: v1-dependencies-{{ checksum "project.clj" }} 40 | 41 | # run tests! 42 | - run: lein test 43 | -------------------------------------------------------------------------------- /test/pronouns/util_test.clj: -------------------------------------------------------------------------------- 1 | (ns pronouns.util-test 2 | (:require [pronouns.util :as util] 3 | [clojure.test :refer [deftest testing is are]])) 4 | 5 | (def test-table [["ze" "hir" "hir" "hirs" "hirself"] 6 | ["ze" "zir" "zir" "zirs" "zirself"] 7 | ["she" "her" "her" "hers" "herself"] 8 | ["he" "him" "his" "his" "himself"] 9 | ["they" "them" "their" "theirs" "themselves"] 10 | ["they" "them" "their" "theirs" "themself"]]) 11 | 12 | (deftest table-filters 13 | (testing "table-front-filter" 14 | (are [arg return] (= (util/table-front-filter arg test-table) return) 15 | ["she"] [["she" "her" "her" "hers" "herself"]] 16 | ["ze"] [["ze" "hir" "hir" "hirs" "hirself"] 17 | ["ze" "zir" "zir" "zirs" "zirself"]] 18 | ["ze" "zir"] [["ze" "zir" "zir" "zirs" "zirself"]])) 19 | 20 | (testing "table-end-filter" 21 | (are [arg return] (= (util/table-end-filter arg test-table) return) 22 | ["themself"] [["they" "them" "their" "theirs" "themself"]] 23 | ["themselves"] [["they" "them" "their" "theirs" "themselves"]]))) 24 | 25 | (deftest table-lookup 26 | (are [arg return] (= (util/table-lookup arg test-table) return) 27 | ["she"] ["she" "her" "her" "hers" "herself"] 28 | ["ze"] ["ze" "hir" "hir" "hirs" "hirself"] 29 | ["ze" "zir"] ["ze" "zir" "zir" "zirs" "zirself"] 30 | ["they"] ["they" "them" "their" "theirs" "themselves"] 31 | ["they" "..." "themself"] ["they" "them" "their" "theirs" "themself"])) 32 | 33 | -------------------------------------------------------------------------------- /src/pronouns/web.clj: -------------------------------------------------------------------------------- 1 | ;; pronoun.is - a website for pronoun usage examples 2 | ;; Copyright (C) 2014 - 2018 Morgan Astra 3 | 4 | ;; This program is free software: you can redistribute it and/or modify 5 | ;; it under the terms of the GNU Affero General Public License as 6 | ;; published by the Free Software Foundation, either version 3 of the 7 | ;; License, or (at your option) any later version. 8 | 9 | ;; This program is distributed in the hope that it will be useful, 10 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ;; GNU Affero General Public License for more details. 13 | 14 | ;; You should have received a copy of the GNU Affero General Public License 15 | ;; along with this program. If not, see 16 | 17 | (ns pronouns.web 18 | (:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]] 19 | [compojure.handler :refer [site]] 20 | [compojure.route :as route] 21 | [clojure.string :as s] 22 | [clojure.java.io :as io] 23 | [ring.adapter.jetty :as jetty] 24 | [ring.middleware.logger :as logger] 25 | [ring.middleware.stacktrace :as trace] 26 | [ring.middleware.params :as params] 27 | [ring.middleware.resource :refer [wrap-resource]] 28 | [ring.middleware.content-type :refer [wrap-content-type]] 29 | [ring.middleware.not-modified :refer [wrap-not-modified]] 30 | [environ.core :refer [env]] 31 | [pronouns.util :as u] 32 | [pronouns.pages :as pages])) 33 | 34 | (defroutes app-routes 35 | (GET "/" [] 36 | {:status 200 37 | :headers {"Content-Type" "text/html"} 38 | :body (pages/front)}) 39 | 40 | (GET "/all-pronouns" [] 41 | {:status 200 42 | :headers {"Content-Type" "text/html"} 43 | :body (pages/all-pronouns)}) 44 | 45 | (GET "/pronouns.css" [] 46 | {:status 200 47 | :headers {"Content-Type" "text/css"} 48 | :body (slurp (io/resource "pronouns.css"))}) 49 | 50 | (GET "/*" {params :params} 51 | {:status 200 52 | :headers {"Content-Type" "text/html"} 53 | :body (pages/pronouns params)}) 54 | 55 | (ANY "*" [] 56 | (route/not-found (slurp (io/resource "404.html"))))) 57 | 58 | (defn wrap-gnu-natalie-nguyen [handler] 59 | (fn [req] 60 | (when-let [resp (handler req)] 61 | (assoc-in resp [:headers "X-Clacks-Overhead"] "GNU Natalie Nguyen")))) 62 | 63 | (defn wrap-error-page [handler] 64 | (fn [req] 65 | (try (handler req) 66 | (catch Exception e 67 | (binding [*out* *err*] 68 | {:status 500 69 | :headers {"Content-Type" "text/html"} 70 | :body (slurp (io/resource "500.html"))}))))) 71 | 72 | (def app 73 | (-> app-routes 74 | ;; FIXME morgan.astra <2018-11-14 Wed> 75 | ;; use this resource or delete it 76 | ;; (wrap-resource "images") 77 | wrap-content-type 78 | wrap-not-modified 79 | logger/wrap-with-logger 80 | wrap-error-page 81 | wrap-gnu-natalie-nguyen 82 | trace/wrap-stacktrace 83 | params/wrap-params)) 84 | 85 | (defn -main [] 86 | (let [port (Integer. (:port env))] 87 | (jetty/run-jetty app {:port port}))) 88 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project maintainer, @morganastra. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /src/pronouns/util.clj: -------------------------------------------------------------------------------- 1 | ;; pronoun.is - a website for pronoun usage examples 2 | ;; Copyright (C) 2014 - 2018 Morgan Astra 3 | 4 | ;; This program is free software: you can redistribute it and/or modify 5 | ;; it under the terms of the GNU Affero General Public License as 6 | ;; published by the Free Software Foundation, either version 3 of the 7 | ;; License, or (at your option) any later version. 8 | 9 | ;; This program is distributed in the hope that it will be useful, 10 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ;; GNU Affero General Public License for more details. 13 | 14 | ;; You should have received a copy of the GNU Affero General Public License 15 | ;; along with this program. If not, see 16 | 17 | (ns pronouns.util 18 | (:require [clojure.string :as s])) 19 | 20 | (defn slurp-tabfile 21 | "Read a tabfile from a filesystem as a table" 22 | [path] 23 | (let [lines (s/split (slurp path) #"\n")] 24 | (map #(s/split % #"\t") lines))) 25 | 26 | (defn table-front-filter 27 | "filter a to the rows which begin with " 28 | [query-key table] 29 | (let [arity (count query-key)] 30 | (filter #(= query-key (take arity %)) table))) 31 | 32 | (defn table-end-filter 33 | "filter a
to the rows which end with " 34 | [query-key table] 35 | (let [table-arity (count (first table)) 36 | query-arity (count query-key)] 37 | (filter #(= query-key (drop (- table-arity query-arity) %)) table))) 38 | 39 | (defn table-lookup 40 | "find the row corresponding to in
" 41 | [query-key table] 42 | (if (some #(= "..." %) query-key) 43 | (let [[query-front query-end-] (split-with #(not= "..." %) query-key) 44 | query-end (drop 1 query-end-) 45 | front-matches (table-front-filter query-front table)] 46 | (first (table-end-filter query-end front-matches))) 47 | (first (table-front-filter query-key table)))) 48 | 49 | (defn shortest-unambiguous-forward-path 50 | "Compute the shortest (in number of path elements) forward path which 51 | unambiguously refers to a specific in a
. The behavior of 52 | this function is undefined if given a that is not in the
. 53 | 54 | See also: shortest-unambiguous-path" 55 | [table row] 56 | (loop [n 1] 57 | (let [row-front (take n row)] 58 | (if (>= 1 (count (table-front-filter row-front table))) 59 | row-front 60 | (recur (inc n)))))) 61 | 62 | (defn shortest-unambiguous-ellipses-path 63 | "Compute the shortest (in number of path elements) ellipses path which 64 | unambiguously refers to a specific in a
. The behavior of 65 | this function is undefined if given a that is not in the
. 66 | 67 | See also: shortest-unambiguous-path" 68 | [table row] 69 | (let [row-end (last row) 70 | filtered-table (table-end-filter [row-end] table)] 71 | (loop [n 1] 72 | (let [row-front (take n row)] 73 | (if (>= 1 (count (table-front-filter row-front filtered-table))) 74 | (concat row-front ["..." row-end]) 75 | (recur (inc n))))))) 76 | 77 | (defn shortest-unambiguous-path 78 | "Compute the shortest (in number of path elements) path which unambiguously 79 | refers to a specific in a
. The behavior of this function is 80 | undefined if given a that is not in the
. 81 | 82 | A path can either be a 'forward path', in which it specifies the row with 83 | elements from the front (e.g. ze/zir), or an 'ellipses path', which elides 84 | unnecessary elements from the middle (e.g. they/.../themselves). If the 85 | shortest forward and ellipses paths are the same length, prefer the forward 86 | path" 87 | [table row] 88 | (let [forward-path (shortest-unambiguous-forward-path table row) 89 | ellipses-path (shortest-unambiguous-ellipses-path table row)] 90 | (s/join "/" 91 | (if (> (count forward-path) (count ellipses-path)) 92 | ellipses-path 93 | forward-path)))) 94 | 95 | (defn abbreviate 96 | "return the list of minimum unabiguous paths from a
" 97 | [table] 98 | (map (partial shortest-unambiguous-path table) table)) 99 | 100 | (defn vec-coerce 101 | "wrap a value in a vector if it is not already in one. note that if 102 | is already in a sequence for which vector? is false, this will add 103 | another layer of nesting." 104 | [x] 105 | (if (vector? x) x [x])) 106 | 107 | (defn strip-markup [form] 108 | (s/join " " (filter string? (flatten form)))) 109 | 110 | -------------------------------------------------------------------------------- /src/pronouns/pages.clj: -------------------------------------------------------------------------------- 1 | ;; pronoun.is - a website for pronoun usage examples 2 | ;; Copyright (C) 2014 - 2018 Morgan Astra 3 | 4 | ;; This program is free software: you can redistribute it and/or modify 5 | ;; it under the terms of the GNU Affero General Public License as 6 | ;; published by the Free Software Foundation, either version 3 of the 7 | ;; License, or (at your option) any later version. 8 | 9 | ;; This program is distributed in the hope that it will be useful, 10 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | ;; GNU Affero General Public License for more details. 13 | 14 | ;; You should have received a copy of the GNU Affero General Public License 15 | ;; along with this program. If not, see 16 | 17 | (ns pronouns.pages 18 | (:require [clojure.string :as s] 19 | [pronouns.config :refer [pronouns-table]] 20 | [pronouns.util :as u] 21 | [hiccup.core :refer :all] 22 | [hiccup.element :as e] 23 | [hiccup.util :refer [escape-html]])) 24 | 25 | (defn prose-comma-list 26 | [items] 27 | (let [c (count items)] 28 | (cond 29 | (<= c 1) (or (first items) "") 30 | (= c 2) (s/join " and " items) 31 | :else (str (s/join ", " (butlast items)) ", and " (last items))))) 32 | 33 | (defn href 34 | [url text] 35 | [:a {:href url} text]) 36 | 37 | ;; FIXME morgan.astra <2018-11-14 Wed> 38 | ;; use a div for this instead of a plain bold tag 39 | (defn wrap-pronoun 40 | [pronoun] 41 | [:b pronoun]) 42 | 43 | (defn render-sentence [& content] 44 | [:p [:span.sentence content]]) 45 | 46 | (defn subject-example 47 | [subject] 48 | (render-sentence (wrap-pronoun (s/capitalize subject)) " went to the park.")) 49 | 50 | (defn object-example 51 | [object] 52 | (render-sentence "I went with " (wrap-pronoun object) ".")) 53 | 54 | (defn posessive-determiner-example 55 | [subject possessive-determiner] 56 | (render-sentence (wrap-pronoun (s/capitalize subject)) 57 | " brought " 58 | (wrap-pronoun possessive-determiner) 59 | " frisbee.")) 60 | 61 | (defn possessive-pronoun-example 62 | [possessive-pronoun] 63 | (render-sentence "At least I think it was " 64 | (wrap-pronoun possessive-pronoun) 65 | ".")) 66 | 67 | (defn reflexive-example 68 | [subject reflexive] 69 | (render-sentence (wrap-pronoun (s/capitalize subject)) 70 | " threw the frisbee to " 71 | (wrap-pronoun reflexive) 72 | ".")) 73 | 74 | (defn header-block [header] 75 | [:div {:class "section title"} 76 | (href "/" [:h1 header])]) 77 | 78 | (defn examples-block 79 | [subject object possessive-determiner possessive-pronoun reflexive] 80 | (let [sub-obj (s/join "/" [subject object]) 81 | header-str (str "Here are some example sentences using my " 82 | sub-obj 83 | " pronouns:")] 84 | [:div {:class "section examples"} 85 | [:h2 header-str] 86 | [:p (subject-example subject) 87 | (object-example object) 88 | (posessive-determiner-example subject possessive-determiner) 89 | (possessive-pronoun-example possessive-pronoun) 90 | (reflexive-example subject reflexive)]])) 91 | 92 | (defn usage-block [] 93 | [:div {:class "section usage"} 94 | [:p "Full usage: " 95 | ;; FIXME morgan.astra <2018-11-14 Wed> 96 | ;; This looks really ugly in the browser 97 | [:tt "https://pronoun.is/subject-pronoun/object-pronoun/possessive-determiner/possessive-pronoun/reflexive"] 98 | " displays examples of your pronouns."] 99 | [:p "This is a bit unwieldy. If we have a good guess we'll let you use" 100 | " just the first one or two."]]) 101 | 102 | (defn contact-block [] 103 | (let [twitter-name (fn [handle] (href (str "https://www.twitter.com/" handle) 104 | (str "@" handle)))] 105 | [:div {:class "section contact"} 106 | [:p "Written by " 107 | (twitter-name "morganastra") 108 | ", whose " 109 | (href "https://pronoun.is/she" "pronoun.is/she")] 110 | [:p "pronoun.is is free software under the " 111 | (href "https://www.gnu.org/licenses/agpl.html" "AGPLv3") 112 | "! visit the project on " 113 | (href "https://github.com/witch-house/pronoun.is" "github")] 114 | [:p "<3"]])) 115 | 116 | (defn footer-block [] 117 | [:footer (usage-block) (contact-block)]) 118 | 119 | (defn format-pronoun-examples 120 | [pronoun-declensions] 121 | (let [sub-objs (map #(s/join "/" (take 2 %)) pronoun-declensions) 122 | title (str "Pronoun Island: " (prose-comma-list sub-objs) " examples") 123 | examples (map #(apply examples-block %) pronoun-declensions)] 124 | (html 125 | [:html 126 | [:head 127 | [:title title] 128 | [:meta {:name "viewport" :content "width=device-width"}] 129 | [:meta {:charset "utf-8"}] 130 | [:meta {:name "description" :content (u/strip-markup examples)}] 131 | [:meta {:name "twitter:card" :content "summary"}] 132 | [:meta {:name "twitter:title" :content title}] 133 | [:meta {:name "twitter:description" :content (u/strip-markup examples)}] 134 | [:link {:rel "stylesheet" :href "/pronouns.css"}]] 135 | [:body 136 | (header-block title) 137 | examples 138 | (footer-block)]]))) 139 | 140 | (defn table-lookup* [pronouns-string] 141 | (let [inputs (s/split pronouns-string #"/") 142 | n (count inputs)] 143 | (if (>= n 5) 144 | (take 5 inputs) 145 | (u/table-lookup inputs @pronouns-table)))) 146 | 147 | (defn lookup-pronouns 148 | "Given a seq of pronoun sets, look up each set in the pronouns table" 149 | [pronoun-sets] 150 | (->> pronoun-sets 151 | (map (comp table-lookup* escape-html)) 152 | (filter some?))) 153 | 154 | (defn make-link [path] 155 | (let [link (str "/" path) 156 | label path] 157 | [:li (href link label)])) 158 | 159 | (defn front [] 160 | (let [abbreviations (take 6 (u/abbreviate @pronouns-table)) 161 | links (map make-link abbreviations) 162 | title "Pronoun Island" 163 | description "Pronoun.is is a website for personal pronoun usage examples."] 164 | (html 165 | [:html 166 | [:head 167 | [:title title] 168 | [:meta {:name "description" :content description}] 169 | [:meta {:name "twitter:card" :content "summary"}] 170 | [:meta {:name "twitter:title" :content title}] 171 | [:meta {:name "twitter:description" :content description}] 172 | [:meta {:name "viewport" :content "width=device-width"}] 173 | [:meta {:charset "utf-8"}] 174 | [:link {:rel "stylesheet" :href "/pronouns.css"}]] 175 | [:body 176 | (header-block title) 177 | [:div {:class "section table"} 178 | [:p "pronoun.is is a website for personal pronoun usage examples"] 179 | [:p "here are some pronouns the site knows about:"] 180 | [:ul links] 181 | [:p [:small (href "all-pronouns" "see all pronouns in the database")]]]] 182 | (footer-block)]))) 183 | 184 | (defn all-pronouns [] 185 | (let [abbreviations (u/abbreviate @pronouns-table) 186 | links (map make-link abbreviations) 187 | title "Pronoun Island"] 188 | (html 189 | [:html 190 | [:head 191 | [:title title] 192 | [:meta {:name "viewport" :content "width=device-width"}] 193 | [:meta {:charset "utf-8"}] 194 | [:link {:rel "stylesheet" :href "/pronouns.css"}]] 195 | [:body 196 | (header-block title) 197 | [:div {:class "section table"} 198 | [:p "All pronouns the site knows about:"] 199 | [:ul links]]] 200 | (footer-block)]))) 201 | 202 | (defn not-found [path] 203 | (let [title "Pronoun Island: English Language Examples" 204 | or-re #"/[oO][rR]/"] 205 | (html 206 | [:html 207 | [:head 208 | [:title title] 209 | [:meta {:name "viewport" :content "width=device-width"}] 210 | [:meta {:charset "utf-8"}] 211 | [:link {:rel "stylesheet" :href "/pronouns.css"}]] 212 | [:body 213 | (header-block title) 214 | [:div {:class "section examples"} 215 | [:p [:h2 "We couldn't find those pronouns in our database :("] 216 | "If you think we should have them, please reach out!"] 217 | (when (re-find or-re path) 218 | (let [alts (s/split path or-re) 219 | new-path (str "/" (s/join "/:OR/" alts))] 220 | [:div 221 | "Did you mean: " 222 | (href new-path 223 | (str "pronoun.is" 224 | new-path))]))] 225 | (footer-block)]]))) 226 | 227 | (defn pronouns [params] 228 | (let [path (params :*) 229 | param-alts (u/vec-coerce (or (params "or") [])) 230 | path-alts (s/split path #"/:[oO][rR]/") 231 | pronouns (lookup-pronouns (concat path-alts param-alts))] 232 | (if (seq pronouns) 233 | (format-pronoun-examples pronouns) 234 | (not-found path)))) 235 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pronoun.is 2 | 3 | [pronoun.is](https://pronoun.is) is a website for personal pronoun usage examples 4 | 5 | 6 | **Table of Contents** 7 | 8 | - [pronoun.is](#pronounis) 9 | - [For users](#for-users) 10 | - [For developers](#for-developers) 11 | - [The database](#the-database) 12 | - [The code](#the-code) 13 | - [Tests](#tests) 14 | - [Running the app in a dev environment](#running-the-app-in-a-dev-environment) 15 | - [The git repo](#the-git-repo) 16 | - [Philosophy on pronoun inclusion](#philosophy-on-pronoun-inclusion) 17 | - [FAQ](#faq) 18 | - [Can we translate pronoun.is into another language?](#can-we-translate-pronounis-into-another-language) 19 | - [Can we change the example sentences?](#can-we-change-the-example-sentences) 20 | - [Can we add pronunciation guides?](#can-we-add-pronunciation-guides) 21 | - [Can we add pluralization support (i.e. themself vs themselves)](#can-we-add-pluralization-support-ie-themself-vs-themselves) 22 | - [License](#license) 23 | 24 | 25 | 26 | 27 | ## For users 28 | 29 | You can use any pronouns you like simply by filling them into the 30 | url path. For example, https://pronoun.is/ze/zir/zir/zirs/zirself 31 | 32 | That's pretty unwieldy! Fortunately you can also give it only the 33 | first pronoun or two: https://pronoun.is/she/her or https://pronoun.is/they 34 | 35 | Automatically filling in the rest from only one or two forms only 36 | works for pronouns in the [database][pronoun-database]. If the 37 | pronouns you or a friend uses aren't supported, please let us know and 38 | we'll add them. Alternatively you could add them yourself and submit a 39 | pull request (see the next section for details) 40 | 41 | ## For developers 42 | 43 | ### The database 44 | 45 | The pronouns "database" is a tab-delimited file located in [resources/pronouns.tab][pronoun-database] with fields and example values as follows: 46 | 47 | subject|object|possessive-determiner|possessive-pronoun|reflexive 48 | -------|------|---------------------|------------------|--------- 49 | they | them | their | theirs | themselves 50 | 51 | The top 6 pronouns are displayed on the front page. Please don't edit these 52 | without talking to me, they've been hand-curated based on usage frequency. 53 | Below the top 6, the remaining pronouns are sorted in alphabetical order by 54 | subject and then in roughly frequency order for sets that have the same subject 55 | pronoun. If you're adding a set that shares the same object pronoun as other 56 | set(s) already in the database, please insert it immediately below those ones. 57 | 58 | If you edit the database with a text editor, make sure your editor inputs real 59 | tab characters in that file (a thing your editor might normally be configured 60 | not to do!) In Emacs, you can input real tabs by doing Ctrl+q . 61 | In Vi you can use Ctrl+v . 62 | 63 | [pronoun-database]: resources/pronouns.tab 64 | 65 | ### The code 66 | 67 | The top-level logic for running the server lives in [`pronouns.web`](src/pronouns/web.clj) 68 | 69 | Page rendering markup is in [`pronouns.pages`](src/pronouns/pages.clj), it uses 70 | [hiccup](https://github.com/weavejester/hiccup) for rendering HTML from Clojure 71 | datastructures. 72 | 73 | [`pronouns.config`](src/pronouns/config.clj) is currently used only for loading 74 | the [pronouns database][pronoun-database] 75 | 76 | The unfortunately-named [`pronouns.util`](src/pronouns/util.clj) includes both 77 | actual utility functions used elsewhere in the code, but also what you might 78 | think of as "controllers" if you're used to the MVC model of web design - code 79 | that does the computations necessary for the `pages` (analogous to "views") 80 | to render themselves. We should probably break up `util` into (at least) two 81 | namespaces and be a little more deliberate about where everything currently 82 | in that namespace should live! 83 | 84 | ### Tests 85 | 86 | Run the suite with `lein test` 87 | 88 | Test coverage is not great but getting better. Please run the tests and 89 | confirm that everything passes before merging changes, and please include 90 | tests with any new logic you introduce in a PR! 91 | 92 | Goals for the future include setting up automated CI to run the tests for 93 | us on every PR branch 94 | 95 | ### Running the app in a dev environment 96 | 97 | First, install [leiningen](https://leiningen.org/). Then you can launch the app 98 | on your own computer by running the following command: 99 | 100 | ``` 101 | $ lein ring server 102 | ``` 103 | 104 | This will launch a server running the app and open your default web browser to 105 | the index page. The server will automatically reload files as you edit them - 106 | with the unfortunate exception of `pronouns.tab`, which is loaded as a resource 107 | and requires an app restart to reload. 108 | 109 | ### The git repo 110 | 111 | For most of this project's history we had separate `master` and `develop` 112 | branches but that's proven to be more trouble than it's worth. Going 113 | forward we'll be doing all development in feature branches off of `master`, 114 | and PRs should be issued against `master`. 115 | 116 | Please follow [this guide](https://chris.beams.io/posts/git-commit/) 117 | for writing good commit messages :) 118 | 119 | ## Philosophy on pronoun inclusion 120 | 121 | Pronoun.is aims foremost and exclusively to be a useful resource for people to communicate the personal pronoun they use for themselves. 122 | 123 | It is possible to use these example sentences to demonstrate the usage of words that are not personal pronouns, or even cleverly insert an [entire story](https://pronoun.is/she/or%20they,%20those%20ships%20who%20were%20docked%20and%20still%20equipped%20with%20ancillaries,%20arranged%20to%20share%20the%20duty%20of%20monitoring%20our%20guest%20as%20it%20fit%20into%20their%20routines;%20that%20was%20the%20agreement,%20despite%20it%20being%20less%20convenient%20for%20me%20to%20participate%20at%20all,%20on%20the%20grounds%20that%20certain%20visitors%20might%20prefer%20a%20constant%20individual%20companion%20to%20what%20might%20seem,%20depending%20on%20their%20past%20experiences,%20to%20be%20undue%20attention%20from%20every%20soldier%20they%20passed.%20As%20usual,%20then,%20I%20took%20the%20first%20shift/the%20one%20possession%20of%20hers%20that%20Station%20Security%20hadn't%20confiscated,%20a/knowingly%20left%20with%20her.%20What%20a%20Presger%20frisbee%20might%20do%20or%20even%20look%20like%20I%20couldn't%20say.%20She%20hadn't%20seemed%20the%20sort%20to%20have%20alien%20technology,%20but,%20then%20again,%20neither%20had%20I/another%20unremarkable%20stranger,%20quite%20a%20ways%20down%20the%20concourse,%20who%20caught%20it%20with%20a%20degree%20of%20coordination%20that%20most%20would%20have%20overlooked.%20It%20did%20not%20escape%20my%20notice,%20however.%20"Cousin,"%20I%20said,%20enough%20to%20convey%20-%20unless%20our%20visitor%20were%20quite%20ignorant,%20but,%20of%20course,%20at%20this%20point%20I%20was%20certain%20that%20she%20couldn't%20be%20-%20both%20that%20I%20knew%20what%20she%20was%20not%20and%20that%20I%20was%20giving%20her%20the%20benefit%20of%20the%20doubt%20as%20to%20what,%20or%20who,%20she%20was)! However, as a policy we will not include such entries in the database. 124 | 125 | 126 | ## FAQ 127 | 128 | ### Can we translate pronoun.is into another language? 129 | 130 | I'd love to see pronoun.is-like apps exist in the world for other languages. 131 | I'll answer any questions you need answered if you decide to fork the code to 132 | create a similar site for a different language, and I'll also entertain the 133 | idea of patching the pronoun.is codebase to support rending pages in different 134 | languages as long as it doesn't make the code substantially more complicated. 135 | 136 | Even if we add I18N support to the code, other language versions of the site 137 | should have their own domains names (ideally with clever TLD puns like 138 | pronoun.is has for english!) 139 | 140 | (This was discussed in issues #13, #14, and #66) 141 | 142 | ### Can we change the example sentences? 143 | 144 | Probably not, sorry, I really like these ones! Maybe in the future we can add 145 | multiple different example sentence sets, though. 146 | 147 | ### Can we add pronunciation guides? 148 | 149 | The short answer is, this is very hard! I'd love to have them if someone can 150 | come up with a design for how to do this that'd work (including the logistics 151 | of hosting media files and stuff). 152 | 153 | (This was discussed in issues #43 and #80) 154 | 155 | ### Can we add pluralization support (i.e. themself vs themselves) 156 | 157 | All of the ways I can think of to do this are pretty ugly (both visually 158 | and in the code) so I'm pretty reluctant to do it. That's not an absolute no, 159 | but any proposed solution would need to keep the pronouns database simple 160 | enough that non-programmers can edit it and keep the URLs short, pretty, and 161 | readable to humans as a sentence if you take all the punctuation out. 162 | 163 | ## License 164 | Copyright © 2014-2018 Morgan Astra 165 | 166 | This program is free software: you can redistribute it and/or modify 167 | it under the terms of the GNU Affero General Public License as 168 | published by the Free Software Foundation, either version 3 of the 169 | License, or (at your option) any later version. 170 | 171 | This program is distributed in the hope that it will be useful, 172 | but WITHOUT ANY WARRANTY; without even the implied warranty of 173 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 174 | GNU Affero General Public License for more details. 175 | 176 | You should have received a copy of the GNU Affero General Public License 177 | along with this program. If not, see 178 | 179 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 19 November 2007 4 | 5 | Copyright © 2007 Free Software Foundation, Inc. Everyone is 6 | permitted to copy and distribute verbatim copies of this license document, but 7 | changing it is not allowed. Preamble 8 | 9 | The GNU Affero General Public License is a free, copyleft license for software 10 | and other kinds of works, specifically designed to ensure cooperation with the 11 | community in the case of network server software. 12 | 13 | The licenses for most software and other practical works are designed to take 14 | away your freedom to share and change the works. By contrast, our General Public 15 | Licenses are intended to guarantee your freedom to share and change all versions 16 | of a program--to make sure it remains free software for all its users. 17 | 18 | When we speak of free software, we are referring to freedom, not price. Our 19 | General Public Licenses are designed to make sure that you have the freedom to 20 | distribute copies of free software (and charge for them if you wish), that you 21 | receive source code or can get it if you want it, that you can change the 22 | software or use pieces of it in new free programs, and that you know you can do 23 | these things. 24 | 25 | Developers that use our General Public Licenses protect your rights with two 26 | steps: (1) assert copyright on the software, and (2) offer you this License 27 | which gives you legal permission to copy, distribute and/or modify the software. 28 | 29 | A secondary benefit of defending all users' freedom is that improvements made in 30 | alternate versions of the program, if they receive widespread use, become 31 | available for other developers to incorporate. Many developers of free software 32 | are heartened and encouraged by the resulting cooperation. However, in the case 33 | of software used on network servers, this result may fail to come about. The GNU 34 | General Public License permits making a modified version and letting the public 35 | access it on a server without ever releasing its source code to the public. 36 | 37 | The GNU Affero General Public License is designed specifically to ensure that, 38 | in such cases, the modified source code becomes available to the community. It 39 | requires the operator of a network server to provide the source code of the 40 | modified version running there to the users of that server. Therefore, public 41 | use of a modified version, on a publicly accessible server, gives the public 42 | access to the source code of the modified version. 43 | 44 | An older license, called the Affero General Public License and published by 45 | Affero, was designed to accomplish similar goals. This is a different license, 46 | not a version of the Affero GPL, but Affero has released a new version of the 47 | Affero GPL which permits relicensing under this license. 48 | 49 | The precise terms and conditions for copying, distribution and modification 50 | follow. TERMS AND CONDITIONS 0. Definitions. 51 | 52 | "This License" refers to version 3 of the GNU Affero General Public License. 53 | 54 | "Copyright" also means copyright-like laws that apply to other kinds of works, 55 | such as semiconductor masks. 56 | 57 | "The Program" refers to any copyrightable work licensed under this License. Each 58 | licensee is addressed as "you". "Licensees" and "recipients" may be individuals 59 | or organizations. 60 | 61 | To "modify" a work means to copy from or adapt all or part of the work in a 62 | fashion requiring copyright permission, other than the making of an exact copy. 63 | The resulting work is called a "modified version" of the earlier work or a work 64 | "based on" the earlier work. 65 | 66 | A "covered work" means either the unmodified Program or a work based on the 67 | Program. 68 | 69 | To "propagate" a work means to do anything with it that, without permission, 70 | would make you directly or secondarily liable for infringement under applicable 71 | copyright law, except executing it on a computer or modifying a private copy. 72 | Propagation includes copying, distribution (with or without modification), 73 | making available to the public, and in some countries other activities as well. 74 | 75 | To "convey" a work means any kind of propagation that enables other parties to 76 | make or receive copies. Mere interaction with a user through a computer network, 77 | with no transfer of a copy, is not conveying. 78 | 79 | An interactive user interface displays "Appropriate Legal Notices" to the extent 80 | that it includes a convenient and prominently visible feature that (1) displays 81 | an appropriate copyright notice, and (2) tells the user that there is no 82 | warranty for the work (except to the extent that warranties are provided), that 83 | licensees may convey the work under this License, and how to view a copy of this 84 | License. If the interface presents a list of user commands or options, such as a 85 | menu, a prominent item in the list meets this criterion. 1. Source Code. 86 | 87 | The "source code" for a work means the preferred form of the work for making 88 | modifications to it. "Object code" means any non-source form of a work. 89 | 90 | A "Standard Interface" means an interface that either is an official standard 91 | defined by a recognized standards body, or, in the case of interfaces specified 92 | for a particular programming language, one that is widely used among developers 93 | working in that language. 94 | 95 | The "System Libraries" of an executable work include anything, other than the 96 | work as a whole, that (a) is included in the normal form of packaging a Major 97 | Component, but which is not part of that Major Component, and (b) serves only to 98 | enable use of the work with that Major Component, or to implement a Standard 99 | Interface for which an implementation is available to the public in source code 100 | form. A "Major Component", in this context, means a major essential component 101 | (kernel, window system, and so on) of the specific operating system (if any) on 102 | which the executable work runs, or a compiler used to produce the work, or an 103 | object code interpreter used to run it. 104 | 105 | The "Corresponding Source" for a work in object code form means all the source 106 | code needed to generate, install, and (for an executable work) run the object 107 | code and to modify the work, including scripts to control those activities. 108 | However, it does not include the work's System Libraries, or general-purpose 109 | tools or generally available free programs which are used unmodified in 110 | performing those activities but which are not part of the work. For example, 111 | Corresponding Source includes interface definition files associated with source 112 | files for the work, and the source code for shared libraries and dynamically 113 | linked subprograms that the work is specifically designed to require, such as by 114 | intimate data communication or control flow between those subprograms and other 115 | parts of the work. 116 | 117 | The Corresponding Source need not include anything that users can regenerate 118 | automatically from other parts of the Corresponding Source. 119 | 120 | The Corresponding Source for a work in source code form is that same work. 2. 121 | Basic Permissions. 122 | 123 | All rights granted under this License are granted for the term of copyright on 124 | the Program, and are irrevocable provided the stated conditions are met. This 125 | License explicitly affirms your unlimited permission to run the unmodified 126 | Program. The output from running a covered work is covered by this License only 127 | if the output, given its content, constitutes a covered work. This License 128 | acknowledges your rights of fair use or other equivalent, as provided by 129 | copyright law. 130 | 131 | You may make, run and propagate covered works that you do not convey, without 132 | conditions so long as your license otherwise remains in force. You may convey 133 | covered works to others for the sole purpose of having them make modifications 134 | exclusively for you, or provide you with facilities for running those works, 135 | provided that you comply with the terms of this License in conveying all 136 | material for which you do not control copyright. Those thus making or running 137 | the covered works for you must do so exclusively on your behalf, under your 138 | direction and control, on terms that prohibit them from making any copies of 139 | your copyrighted material outside their relationship with you. 140 | 141 | Conveying under any other circumstances is permitted solely under the conditions 142 | stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. 143 | Protecting Users' Legal Rights From Anti-Circumvention Law. 144 | 145 | No covered work shall be deemed part of an effective technological measure under 146 | any applicable law fulfilling obligations under article 11 of the WIPO copyright 147 | treaty adopted on 20 December 1996, or similar laws prohibiting or restricting 148 | circumvention of such measures. 149 | 150 | When you convey a covered work, you waive any legal power to forbid 151 | circumvention of technological measures to the extent such circumvention is 152 | effected by exercising rights under this License with respect to the covered 153 | work, and you disclaim any intention to limit operation or modification of the 154 | work as a means of enforcing, against the work's users, your or third parties' 155 | legal rights to forbid circumvention of technological measures. 4. Conveying 156 | Verbatim Copies. 157 | 158 | You may convey verbatim copies of the Program's source code as you receive it, 159 | in any medium, provided that you conspicuously and appropriately publish on each 160 | copy an appropriate copyright notice; keep intact all notices stating that this 161 | License and any non-permissive terms added in accord with section 7 apply to the 162 | code; keep intact all notices of the absence of any warranty; and give all 163 | recipients a copy of this License along with the Program. 164 | 165 | You may charge any price or no price for each copy that you convey, and you may 166 | offer support or warranty protection for a fee. 5. Conveying Modified Source 167 | Versions. 168 | 169 | You may convey a work based on the Program, or the modifications to produce it 170 | from the Program, in the form of source code under the terms of section 4, 171 | provided that you also meet all of these conditions: 172 | 173 | a) The work must carry prominent notices stating that you modified it, and 174 | giving a relevant date. b) The work must carry prominent notices stating that it 175 | is released under this License and any conditions added under section 7. This 176 | requirement modifies the requirement in section 4 to "keep intact all notices". 177 | c) You must license the entire work, as a whole, under this License to anyone 178 | who comes into possession of a copy. This License will therefore apply, along 179 | with any applicable section 7 additional terms, to the whole of the work, and 180 | all its parts, regardless of how they are packaged. This License gives no 181 | permission to license the work in any other way, but it does not invalidate such 182 | permission if you have separately received it. d) If the work has interactive 183 | user interfaces, each must display Appropriate Legal Notices; however, if the 184 | Program has interactive interfaces that do not display Appropriate Legal 185 | Notices, your work need not make them do so. 186 | 187 | A compilation of a covered work with other separate and independent works, which 188 | are not by their nature extensions of the covered work, and which are not 189 | combined with it such as to form a larger program, in or on a volume of a 190 | storage or distribution medium, is called an "aggregate" if the compilation and 191 | its resulting copyright are not used to limit the access or legal rights of the 192 | compilation's users beyond what the individual works permit. Inclusion of a 193 | covered work in an aggregate does not cause this License to apply to the other 194 | parts of the aggregate. 6. Conveying Non-Source Forms. 195 | 196 | You may convey a covered work in object code form under the terms of sections 4 197 | and 5, provided that you also convey the machine-readable Corresponding Source 198 | under the terms of this License, in one of these ways: 199 | 200 | a) Convey the object code in, or embodied in, a physical product (including a 201 | physical distribution medium), accompanied by the Corresponding Source fixed on 202 | a durable physical medium customarily used for software interchange. b) Convey 203 | the object code in, or embodied in, a physical product (including a physical 204 | distribution medium), accompanied by a written offer, valid for at least three 205 | years and valid for as long as you offer spare parts or customer support for 206 | that product model, to give anyone who possesses the object code either (1) a 207 | copy of the Corresponding Source for all the software in the product that is 208 | covered by this License, on a durable physical medium customarily used for 209 | software interchange, for a price no more than your reasonable cost of 210 | physically performing this conveying of source, or (2) access to copy the 211 | Corresponding Source from a network server at no charge. c) Convey individual 212 | copies of the object code with a copy of the written offer to provide the 213 | Corresponding Source. This alternative is allowed only occasionally and 214 | noncommercially, and only if you received the object code with such an offer, in 215 | accord with subsection 6b. d) Convey the object code by offering access from a 216 | designated place (gratis or for a charge), and offer equivalent access to the 217 | Corresponding Source in the same way through the same place at no further 218 | charge. You need not require recipients to copy the Corresponding Source along 219 | with the object code. If the place to copy the object code is a network server, 220 | the Corresponding Source may be on a different server (operated by you or a 221 | third party) that supports equivalent copying facilities, provided you maintain 222 | clear directions next to the object code saying where to find the Corresponding 223 | Source. Regardless of what server hosts the Corresponding Source, you remain 224 | obligated to ensure that it is available for as long as needed to satisfy these 225 | requirements. e) Convey the object code using peer-to-peer transmission, 226 | provided you inform other peers where the object code and Corresponding Source 227 | of the work are being offered to the general public at no charge under 228 | subsection 6d. 229 | 230 | A separable portion of the object code, whose source code is excluded from the 231 | Corresponding Source as a System Library, need not be included in conveying the 232 | object code work. 233 | 234 | A "User Product" is either (1) a "consumer product", which means any tangible 235 | personal property which is normally used for personal, family, or household 236 | purposes, or (2) anything designed or sold for incorporation into a dwelling. In 237 | determining whether a product is a consumer product, doubtful cases shall be 238 | resolved in favor of coverage. For a particular product received by a particular 239 | user, "normally used" refers to a typical or common use of that class of 240 | product, regardless of the status of the particular user or of the way in which 241 | the particular user actually uses, or expects or is expected to use, the 242 | product. A product is a consumer product regardless of whether the product has 243 | substantial commercial, industrial or non-consumer uses, unless such uses 244 | represent the only significant mode of use of the product. 245 | 246 | "Installation Information" for a User Product means any methods, procedures, 247 | authorization keys, or other information required to install and execute 248 | modified versions of a covered work in that User Product from a modified version 249 | of its Corresponding Source. The information must suffice to ensure that the 250 | continued functioning of the modified object code is in no case prevented or 251 | interfered with solely because modification has been made. 252 | 253 | If you convey an object code work under this section in, or with, or 254 | specifically for use in, a User Product, and the conveying occurs as part of a 255 | transaction in which the right of possession and use of the User Product is 256 | transferred to the recipient in perpetuity or for a fixed term (regardless of 257 | how the transaction is characterized), the Corresponding Source conveyed under 258 | this section must be accompanied by the Installation Information. But this 259 | requirement does not apply if neither you nor any third party retains the 260 | ability to install modified object code on the User Product (for example, the 261 | work has been installed in ROM). 262 | 263 | The requirement to provide Installation Information does not include a 264 | requirement to continue to provide support service, warranty, or updates for a 265 | work that has been modified or installed by the recipient, or for the User 266 | Product in which it has been modified or installed. Access to a network may be 267 | denied when the modification itself materially and adversely affects the 268 | operation of the network or violates the rules and protocols for communication 269 | across the network. 270 | 271 | Corresponding Source conveyed, and Installation Information provided, in accord 272 | with this section must be in a format that is publicly documented (and with an 273 | implementation available to the public in source code form), and must require no 274 | special password or key for unpacking, reading or copying. 7. Additional Terms. 275 | 276 | "Additional permissions" are terms that supplement the terms of this License by 277 | making exceptions from one or more of its conditions. Additional permissions 278 | that are applicable to the entire Program shall be treated as though they were 279 | included in this License, to the extent that they are valid under applicable 280 | law. If additional permissions apply only to part of the Program, that part may 281 | be used separately under those permissions, but the entire Program remains 282 | governed by this License without regard to the additional permissions. 283 | 284 | When you convey a copy of a covered work, you may at your option remove any 285 | additional permissions from that copy, or from any part of it. (Additional 286 | permissions may be written to require their own removal in certain cases when 287 | you modify the work.) You may place additional permissions on material, added by 288 | you to a covered work, for which you have or can give appropriate copyright 289 | permission. 290 | 291 | Notwithstanding any other provision of this License, for material you add to a 292 | covered work, you may (if authorized by the copyright holders of that material) 293 | supplement the terms of this License with terms: 294 | 295 | a) Disclaiming warranty or limiting liability differently from the terms of 296 | sections 15 and 16 of this License; or b) Requiring preservation of specified 297 | reasonable legal notices or author attributions in that material or in the 298 | Appropriate Legal Notices displayed by works containing it; or c) Prohibiting 299 | misrepresentation of the origin of that material, or requiring that modified 300 | versions of such material be marked in reasonable ways as different from the 301 | original version; or d) Limiting the use for publicity purposes of names of 302 | licensors or authors of the material; or e) Declining to grant rights under 303 | trademark law for use of some trade names, trademarks, or service marks; or f) 304 | Requiring indemnification of licensors and authors of that material by anyone 305 | who conveys the material (or modified versions of it) with contractual 306 | assumptions of liability to the recipient, for any liability that these 307 | contractual assumptions directly impose on those licensors and authors. 308 | 309 | All other non-permissive additional terms are considered "further restrictions" 310 | within the meaning of section 10. If the Program as you received it, or any part 311 | of it, contains a notice stating that it is governed by this License along with 312 | a term that is a further restriction, you may remove that term. If a license 313 | document contains a further restriction but permits relicensing or conveying 314 | under this License, you may add to a covered work material governed by the terms 315 | of that license document, provided that the further restriction does not survive 316 | such relicensing or conveying. 317 | 318 | If you add terms to a covered work in accord with this section, you must place, 319 | in the relevant source files, a statement of the additional terms that apply to 320 | those files, or a notice indicating where to find the applicable terms. 321 | 322 | Additional terms, permissive or non-permissive, may be stated in the form of a 323 | separately written license, or stated as exceptions; the above requirements 324 | apply either way. 8. Termination. 325 | 326 | You may not propagate or modify a covered work except as expressly provided 327 | under this License. Any attempt otherwise to propagate or modify it is void, and 328 | will automatically terminate your rights under this License (including any 329 | patent licenses granted under the third paragraph of section 11). 330 | 331 | However, if you cease all violation of this License, then your license from a 332 | particular copyright holder is reinstated (a) provisionally, unless and until 333 | the copyright holder explicitly and finally terminates your license, and (b) 334 | permanently, if the copyright holder fails to notify you of the violation by 335 | some reasonable means prior to 60 days after the cessation. 336 | 337 | Moreover, your license from a particular copyright holder is reinstated 338 | permanently if the copyright holder notifies you of the violation by some 339 | reasonable means, this is the first time you have received notice of violation 340 | of this License (for any work) from that copyright holder, and you cure the 341 | violation prior to 30 days after your receipt of the notice. 342 | 343 | Termination of your rights under this section does not terminate the licenses of 344 | parties who have received copies or rights from you under this License. If your 345 | rights have been terminated and not permanently reinstated, you do not qualify 346 | to receive new licenses for the same material under section 10. 9. Acceptance 347 | Not Required for Having Copies. 348 | 349 | You are not required to accept this License in order to receive or run a copy of 350 | the Program. Ancillary propagation of a covered work occurring solely as a 351 | consequence of using peer-to-peer transmission to receive a copy likewise does 352 | not require acceptance. However, nothing other than this License grants you 353 | permission to propagate or modify any covered work. These actions infringe 354 | copyright if you do not accept this License. Therefore, by modifying or 355 | propagating a covered work, you indicate your acceptance of this License to do 356 | so. 10. Automatic Licensing of Downstream Recipients. 357 | 358 | Each time you convey a covered work, the recipient automatically receives a 359 | license from the original licensors, to run, modify and propagate that work, 360 | subject to this License. You are not responsible for enforcing compliance by 361 | third parties with this License. 362 | 363 | An "entity transaction" is a transaction transferring control of an 364 | organization, or substantially all assets of one, or subdividing an 365 | organization, or merging organizations. If propagation of a covered work results 366 | from an entity transaction, each party to that transaction who receives a copy 367 | of the work also receives whatever licenses to the work the party's predecessor 368 | in interest had or could give under the previous paragraph, plus a right to 369 | possession of the Corresponding Source of the work from the predecessor in 370 | interest, if the predecessor has it or can get it with reasonable efforts. 371 | 372 | You may not impose any further restrictions on the exercise of the rights 373 | granted or affirmed under this License. For example, you may not impose a 374 | license fee, royalty, or other charge for exercise of rights granted under this 375 | License, and you may not initiate litigation (including a cross-claim or 376 | counterclaim in a lawsuit) alleging that any patent claim is infringed by 377 | making, using, selling, offering for sale, or importing the Program or any 378 | portion of it. 11. Patents. 379 | 380 | A "contributor" is a copyright holder who authorizes use under this License of 381 | the Program or a work on which the Program is based. The work thus licensed is 382 | called the contributor's "contributor version". 383 | 384 | A contributor's "essential patent claims" are all patent claims owned or 385 | controlled by the contributor, whether already acquired or hereafter acquired, 386 | that would be infringed by some manner, permitted by this License, of making, 387 | using, or selling its contributor version, but do not include claims that would 388 | be infringed only as a consequence of further modification of the contributor 389 | version. For purposes of this definition, "control" includes the right to grant 390 | patent sublicenses in a manner consistent with the requirements of this License. 391 | 392 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent 393 | license under the contributor's essential patent claims, to make, use, sell, 394 | offer for sale, import and otherwise run, modify and propagate the contents of 395 | its contributor version. 396 | 397 | In the following three paragraphs, a "patent license" is any express agreement 398 | or commitment, however denominated, not to enforce a patent (such as an express 399 | permission to practice a patent or covenant not to sue for patent infringement). 400 | To "grant" such a patent license to a party means to make such an agreement or 401 | commitment not to enforce a patent against the party. 402 | 403 | If you convey a covered work, knowingly relying on a patent license, and the 404 | Corresponding Source of the work is not available for anyone to copy, free of 405 | charge and under the terms of this License, through a publicly available network 406 | server or other readily accessible means, then you must either (1) cause the 407 | Corresponding Source to be so available, or (2) arrange to deprive yourself of 408 | the benefit of the patent license for this particular work, or (3) arrange, in a 409 | manner consistent with the requirements of this License, to extend the patent 410 | license to downstream recipients. "Knowingly relying" means you have actual 411 | knowledge that, but for the patent license, your conveying the covered work in a 412 | country, or your recipient's use of the covered work in a country, would 413 | infringe one or more identifiable patents in that country that you have reason 414 | to believe are valid. 415 | 416 | If, pursuant to or in connection with a single transaction or arrangement, you 417 | convey, or propagate by procuring conveyance of, a covered work, and grant a 418 | patent license to some of the parties receiving the covered work authorizing 419 | them to use, propagate, modify or convey a specific copy of the covered work, 420 | then the patent license you grant is automatically extended to all recipients of 421 | the covered work and works based on it. 422 | 423 | A patent license is "discriminatory" if it does not include within the scope of 424 | its coverage, prohibits the exercise of, or is conditioned on the non-exercise 425 | of one or more of the rights that are specifically granted under this License. 426 | You may not convey a covered work if you are a party to an arrangement with a 427 | third party that is in the business of distributing software, under which you 428 | make payment to the third party based on the extent of your activity of 429 | conveying the work, and under which the third party grants, to any of the 430 | parties who would receive the covered work from you, a discriminatory patent 431 | license (a) in connection with copies of the covered work conveyed by you (or 432 | copies made from those copies), or (b) primarily for and in connection with 433 | specific products or compilations that contain the covered work, unless you 434 | entered into that arrangement, or that patent license was granted, prior to 28 435 | March 2007. 436 | 437 | Nothing in this License shall be construed as excluding or limiting any implied 438 | license or other defenses to infringement that may otherwise be available to you 439 | under applicable patent law. 12. No Surrender of Others' Freedom. 440 | 441 | If conditions are imposed on you (whether by court order, agreement or 442 | otherwise) that contradict the conditions of this License, they do not excuse 443 | you from the conditions of this License. If you cannot convey a covered work so 444 | as to satisfy simultaneously your obligations under this License and any other 445 | pertinent obligations, then as a consequence you may not convey it at all. For 446 | example, if you agree to terms that obligate you to collect a royalty for 447 | further conveying from those to whom you convey the Program, the only way you 448 | could satisfy both those terms and this License would be to refrain entirely 449 | from conveying the Program. 13. Remote Network Interaction; Use with the GNU 450 | General Public License. 451 | 452 | Notwithstanding any other provision of this License, if you modify the Program, 453 | your modified version must prominently offer all users interacting with it 454 | remotely through a computer network (if your version supports such interaction) 455 | an opportunity to receive the Corresponding Source of your version by providing 456 | access to the Corresponding Source from a network server at no charge, through 457 | some standard or customary means of facilitating copying of software. This 458 | Corresponding Source shall include the Corresponding Source for any work covered 459 | by version 3 of the GNU General Public License that is incorporated pursuant to 460 | the following paragraph. 461 | 462 | Notwithstanding any other provision of this License, you have permission to link 463 | or combine any covered work with a work licensed under version 3 of the GNU 464 | General Public License into a single combined work, and to convey the resulting 465 | work. The terms of this License will continue to apply to the part which is the 466 | covered work, but the work with which it is combined will remain governed by 467 | version 3 of the GNU General Public License. 14. Revised Versions of this 468 | License. 469 | 470 | The Free Software Foundation may publish revised and/or new versions of the GNU 471 | Affero General Public License from time to time. Such new versions will be 472 | similar in spirit to the present version, but may differ in detail to address 473 | new problems or concerns. 474 | 475 | Each version is given a distinguishing version number. If the Program specifies 476 | that a certain numbered version of the GNU Affero General Public License "or any 477 | later version" applies to it, you have the option of following the terms and 478 | conditions either of that numbered version or of any later version published by 479 | the Free Software Foundation. If the Program does not specify a version number 480 | of the GNU Affero General Public License, you may choose any version ever 481 | published by the Free Software Foundation. 482 | 483 | If the Program specifies that a proxy can decide which future versions of the 484 | GNU Affero General Public License can be used, that proxy's public statement of 485 | acceptance of a version permanently authorizes you to choose that version for 486 | the Program. 487 | 488 | Later license versions may give you additional or different permissions. 489 | However, no additional obligations are imposed on any author or copyright holder 490 | as a result of your choosing to follow a later version. 15. Disclaimer of 491 | Warranty. 492 | 493 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 494 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER 495 | PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 496 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 497 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE 498 | QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 499 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 500 | 16. Limitation of Liability. 501 | 502 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY 503 | COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS 504 | PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, 505 | INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE 506 | THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 507 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE 508 | PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY 509 | HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of 510 | Sections 15 and 16. 511 | 512 | If the disclaimer of warranty and limitation of liability provided above cannot 513 | be given local legal effect according to their terms, reviewing courts shall 514 | apply local law that most closely approximates an absolute waiver of all civil 515 | liability in connection with the Program, unless a warranty or assumption of 516 | liability accompanies a copy of the Program in return for a fee. 517 | 518 | END OF TERMS AND CONDITIONS --------------------------------------------------------------------------------