diff options
-rw-r--r-- | README.md | 23 | ||||
-rw-r--r-- | project.clj | 14 | ||||
-rw-r--r-- | resources/images/purple-flag.svg | 112 | ||||
-rw-r--r-- | resources/images/purple-flag64.png | bin | 0 -> 3717 bytes | |||
-rw-r--r-- | resources/pronouns.tab | 10 | ||||
-rw-r--r-- | src/pronouns/pages.clj | 19 | ||||
-rw-r--r-- | src/pronouns/util.clj | 12 | ||||
-rw-r--r-- | src/pronouns/web.clj | 14 | ||||
-rw-r--r-- | test/pronouns/pages_test.clj | 16 |
9 files changed, 183 insertions, 37 deletions
diff --git a/README.md b/README.md index f4bdae5..a037e48 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -**[pronoun.is](http://pronoun.is) is a website for personal pronoun usage examples** +**[pronoun.is](https://pronoun.is) is a website for personal pronoun usage examples** ## For users You can use any pronouns you like simply by filling them into the -url path. For example, http://pronoun.is/ze/zir/zir/zirs/zirself +url path. For example, https://pronoun.is/ze/zir/zir/zirs/zirself That's pretty unwieldy! Fortunately you can also give it only the -first pronoun or two: http://pronoun.is/she/her or http://pronoun.is/they +first pronoun or two: https://pronoun.is/she/her or https://pronoun.is/they Automatically filling in the rest from only one or two forms only -works for pronouns in the [database](resources/pronouns.tab). If the +works for pronouns in the [database][pronoun-database]. If the pronouns you or a friend uses aren't supported, please let us know and we'll add them. Alternatively you could add them yourself and submit a pull request (see the next section for details) @@ -18,8 +18,7 @@ pull request (see the next section for details) ### The database -The pronouns "database" is a tab-delimited file with fields and -example values as follows: +The pronouns "database" is a tab-delimited file located in [resources/pronouns.tab][pronoun-database] with fields and example values as follows: subject|object|possessive-determiner|possessive-pronoun|reflexive -------|------|---------------------|------------------|--------- @@ -28,12 +27,14 @@ they | them | their | theirs | themselves If you edit it with a text editor, make sure your editor inputs real tab characters in that file (a thing your editor might normally be configured not to do!) In Emacs, you can input real tabs by doing -Ctrl+q <tab> +Ctrl+q <tab>. In Vi you can use Ctrl+v <tab>. + +[pronoun-database]: resources/pronouns.tab ### Running the app in a dev environment -You can launch the app on your own computer by running the following -command: +First, install [leiningen](https://leiningen.org/). Then you can launch the app +on your own computer by running the following command: ``` $ lein ring server @@ -45,7 +46,7 @@ This will launch a server running the app and open your default web browser to t Pronoun.is aims foremost and exclusively to be a useful resource for people to communicate the personal pronoun they use for themselves. -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](http://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. +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. ## License @@ -62,5 +63,5 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License -along with this program. If not, see <http://www.gnu.org/licenses/> +along with this program. If not, see <https://www.gnu.org/licenses/> diff --git a/project.clj b/project.clj index b14ac4e..bcb1454 100644 --- a/project.clj +++ b/project.clj @@ -2,18 +2,16 @@ :description "Pronoun.is is a website for personal pronoun usage examples" :url "http://pronoun.is" :license "GNU Affero General Public License 3.0" - :dependencies [[org.clojure/clojure "1.6.0"] - [compojure "1.1.8"] - [ring/ring-jetty-adapter "1.2.2"] - [ring.middleware.logger "0.5.0"] - [ring/ring-devel "1.2.2"] - [environ "0.5.0"] + :dependencies [[org.clojure/clojure "1.9.0"] + [compojure "1.6.1"] + [ring/ring-jetty-adapter "1.7.1"] + [ring/ring-devel "1.7.1"] + [environ "1.1.0"] [hiccup "1.0.5"]] :min-lein-version "2.0.0" :plugins [[environ/environ.lein "0.2.1"] [lein-ring "0.9.7"]] :hooks [environ.leiningen.hooks] :uberjar-name "pronouns-standalone.jar" - :profiles {:production {:env {:production true}} - :dev {:dependencies [[midje "1.6.3"]]}} + :profiles {:production {:env {:production true}}} :ring {:handler pronouns.web/app}) diff --git a/resources/images/purple-flag.svg b/resources/images/purple-flag.svg new file mode 100644 index 0000000..c8e231c --- /dev/null +++ b/resources/images/purple-flag.svg @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + sodipodi:docname="antifascist-action-red.svg" + viewBox="0 0 847.19 847.85" + version="1.1" + inkscape:version="0.92.1 r" + width="903.66931" + height="904.37329"> + <defs + id="defs72" /> + <sodipodi:namedview + id="base" + bordercolor="#666666" + inkscape:pageshadow="2" + inkscape:window-y="14" + fit-margin-left="0" + pagecolor="#ffffff" + inkscape:window-height="1426" + inkscape:window-maximized="0" + inkscape:zoom="0.35" + inkscape:window-x="0" + showgrid="true" + borderopacity="1.0" + inkscape:current-layer="layer1" + inkscape:cx="1059.3962" + inkscape:cy="231.88159" + fit-margin-top="0" + fit-margin-right="0" + fit-margin-bottom="0" + inkscape:window-width="2560" + inkscape:pageopacity="0.0" + inkscape:document-units="px"> + <inkscape:grid + type="xygrid" + id="grid3896" /> + </sodipodi:namedview> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer" + transform="translate(300.74,2.9901)" + style="display:inline"> + <g + id="layer1-4" + transform="translate(-248.4,-65.648)" + style="display:inline" + inkscape:label="layer1-4"> + <g + id="g2844" + transform="translate(591.43,-22.857)" + style="display:inline" + inkscape:export-filename="/home/morgan/purple-antifa.png" + inkscape:export-xdpi="13.16275" + inkscape:export-ydpi="13.16275"> + <path + style="display:inline;fill:#441650;stroke-width:1.0666666" + d="m 452.93359,0 c -32.7392,0 -76.3332,5.5336609 -110.25,13.994141 C 181.71293,54.143473 53.679087,182.17431 13.732422,342.93164 2.9588756,386.28951 -1.8818978,434.80054 0.66796875,473.85547 3.5170353,517.4896 9.4941306,550.76056 21.216797,588.26562 35.544263,634.10136 60.679082,683.01508 89.738281,721.59961 151.44495,803.53134 235.9611,861.08483 334.6875,888.4043 c 29.28533,8.10346 66.26027,13.58111 104,15.4082 v 0.008 c 3.52,0.17041 7.59974,0.39795 9.06641,0.50586 5.44426,0.40064 43.66587,-2.0326 57.0664,-3.63281 63.36,-7.56587 123.73282,-28.1417 178.13281,-60.70703 119.7344,-71.68 199.50098,-193.50399 217.00391,-331.44531 4.97173,-39.18507 4.95718,-72.39455 -0.0469,-112.81055 C 887.68616,296.96781 842.62357,205.08233 771.48438,133.8418 762.09771,124.44233 748.89706,112.13975 742.15039,106.50391 676.44373,51.618575 598.93304,16.941328 514.95117,4.8613281 499.53997,2.6445815 465.80826,0 452.93359,0 Z m -0.99023,79.412109 c 17.71293,-0.008 35.36016,0.64903 44.87109,1.972657 65.2256,9.077333 116.91799,29.064654 169.33399,65.478514 18.1152,12.58667 31.64788,24.06424 49.95508,42.37891 60.82559,60.81066 97.11922,136.94968 107.33789,225.15234 2.03087,17.54133 1.71722,61.65641 -0.57227,80.5332 -10.54933,86.93333 -49.2038,164.93918 -111.80859,225.58985 -58.50667,56.68266 -130.9428,91.64734 -212.39453,102.52734 l -0.006,-0.008 c -14.9792,2.00016 -66.86526,2.94976 -79.70899,1.45898 -18.1792,-2.11018 -27.75033,-3.48347 -37.65625,-5.40625 -38.8704,-7.54346 -78.73449,-22.21952 -112.21289,-41.30859 -95.20839,-54.28247 -162.56442,-147.23093 -183.337749,-252.992 -5.442347,-27.70773 -6.44336,-38.97587 -6.44336,-72.5332 0,-34.35413 1.010435,-45.21451 6.986328,-75.05664 22.026671,-109.96266 96.829801,-207.46963 198.197271,-258.33789 39.75679,-19.953068 76.4746,-31.200562 122.19726,-37.435549 9.77067,-1.332373 27.54879,-2.005645 45.26172,-2.013672 z" + transform="matrix(0.93750003,0,0,0.93750003,-643.77,85.5149)" + id="path2842" + inkscape:connector-curvature="0" /> + <path + id="path2838" + style="display:inline;fill:#440055" + inkscape:connector-curvature="0" + d="m -207.89,837.3 c -5.1627,-0.4682 -9.9894,-1.1886 -10.726,-1.6009 -1.3981,-0.7824 -0.67608,-2.1126 28.603,-52.697 7.0037,-12.1 22.745,-39.325 34.98,-60.5 12.235,-21.175 26.083,-45.025 30.773,-53 4.6897,-7.975 9.8972,-16.975 11.572,-20 1.675,-3.025 7.2342,-12.62 12.354,-21.322 l 9.3084,-15.822 -1.6179,-3.1782 c -0.88987,-1.748 -3.2198,-5.4282 -5.1776,-8.1782 -20.999,-29.495 -49.249,-43.679 -94.486,-47.436 -17.446,-1.4492 -35.251,-1.3275 -67.196,0.45919 -54.969,3.0744 -64.467,3.4592 -85.605,3.4681 -53.988,0.0226 -91.809,-7.1507 -127.82,-24.242 -25.855,-12.273 -47.999,-29.036 -69,-52.234 l -6.3236,-6.9852 0.6444,-7.0148 c 0.89957,-9.7926 6.0692,-34.518 10.115,-48.38 15.053,-51.571 40.075,-95.111 76.901,-133.82 9.6865,-10.18 29.975,-28.359 38.195,-34.223 l 3.3677,-2.4024 9.7603,9.9933 c 31.285,32.032 69.391,46.287 123.76,46.298 26.683,0.005 50.245,-2.5668 114.5,-12.499 51.119,-7.9016 75.315,-10.083 101.5,-9.1517 35.249,1.2541 59.006,7.9246 82.528,23.173 10.45,6.774 27.996,24.711 36.185,36.991 7.3856,11.076 15.72,27.867 21.213,42.736 l 3.5966,9.7364 -5.8674,10.264 c -3.227,5.645 -12.073,21.064 -19.657,34.264 -7.5845,13.2 -14.555,25.35 -15.491,27 -3.6231,6.3902 -24.958,43.116 -38.341,66 -7.7197,13.2 -15.452,26.475 -17.182,29.5 -6.1405,10.733 -42.194,72.514 -66.236,113.5 -8.9544,15.265 -41.094,70.555 -44.468,76.5 -1.405,2.475 -8.5307,14.85 -15.835,27.5 -7.3041,12.65 -15.186,26.375 -17.516,30.5 -10.378,18.375 -13.403,23.576 -14.351,24.674 -0.55748,0.64576 -3.6152,1.4499 -6.7951,1.787 -3.1798,0.33711 -6.9065,0.74228 -8.2815,0.90038 -1.375,0.15809 -6.724,-0.0956 -11.887,-0.56384 z" /> + <path + id="path2834" + style="display:inline;fill:#440055" + inkscape:connector-curvature="0" + d="m -318.25,822.21 c -9.2125,-1.1324 -16.75,-2.4701 -16.75,-2.9726 0,-0.50247 16.237,-32.636 36.082,-71.409 19.845,-38.772 35.846,-70.732 35.556,-71.021 -0.90422,-0.90422 -12.694,-3.1167 -25.166,-4.7226 -15.132,-1.9485 -31.447,-3.1691 -67.973,-5.0852 -45.969,-2.4115 -66.404,-4.8472 -88.337,-10.529 -65.525,-16.975 -97.683,-60.834 -106.66,-145.47 -2.3545,-22.204 -3.4922,-21.599 11.744,-6.2436 39.823,40.134 85.237,59.474 152.25,64.835 17.913,1.4332 64.877,0.64751 95.5,-1.5978 30.813,-2.2591 65.509,-2.9705 79.165,-1.6231 14.394,1.4202 28.444,4.901 36.913,9.1448 9.8945,4.9583 9.7003,3.7696 2.7542,16.858 -10.389,19.575 -33.785,62.219 -62.34,113.63 -26.68,48.033 -51.838,93.87 -60.51,110.25 -2.4022,4.5375 -4.6185,8.1974 -4.9251,8.133 -0.30657,-0.0643 -8.0949,-1.0435 -17.307,-2.176 z" /> + </g> + </g> + </g> + <metadata + id="metadata69"> + <rdf:RDF> + <cc:Work> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <cc:license + rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" /> + <dc:publisher> + <cc:Agent + rdf:about="http://openclipart.org/"> + <dc:title>Openclipart</dc:title> + </cc:Agent> + </dc:publisher> + <dc:title></dc:title> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/publicdomain/zero/1.0/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> + </rdf:RDF> + </metadata> +</svg> diff --git a/resources/images/purple-flag64.png b/resources/images/purple-flag64.png new file mode 100644 index 0000000..ba63aee --- /dev/null +++ b/resources/images/purple-flag64.png Binary files differdiff --git a/resources/pronouns.tab b/resources/pronouns.tab index 69120c3..c5b6788 100644 --- a/resources/pronouns.tab +++ b/resources/pronouns.tab @@ -5,6 +5,7 @@ he him his his himself they them their theirs themselves they them their theirs themself xey xem xyr xyrs xemself +xey xem xeir xeirs xemself sie hir hir hirs hirself it it its its itself ey em eir eirs eirself @@ -29,4 +30,11 @@ zie hir hir hirs hirself si hyr hyr hyrs hyrself kit kit kits kits kitself ne nem nir nirs nemself -fey fem feir feirs femself +fey fem feir feirs feirself +xie xer xer xers xerself +vi ver ver vers verself +vi vim vir virs vimself +vi vim vim vims vimself +yo yo yos yos yosself +shi hir hir hirs hirself +ae aer aer aers aerself diff --git a/src/pronouns/pages.clj b/src/pronouns/pages.clj index 62007bc..56830d0 100644 --- a/src/pronouns/pages.clj +++ b/src/pronouns/pages.clj @@ -19,6 +19,7 @@ [pronouns.config :refer [*pronouns-table*]] [pronouns.util :as u] [hiccup.core :refer :all] + [hiccup.element :as e] [hiccup.util :refer [escape-html]])) (defn prose-comma-list @@ -70,7 +71,7 @@ (defn header-block [header] [:div {:class "section title"} - (href "/" [:h1 header])]) + (href "/" [:h1 (e/image "/purple-flag64.png" "flag logo") header])]) (defn examples-block [subject object possessive-determiner possessive-pronoun reflexive] @@ -111,19 +112,31 @@ (defn footer-block [] [:footer (usage-block) (contact-block)]) +;; <meta name="twitter:card" content="summary" /> +;; <meta name="twitter:site" content="@flickr" /> +;; <meta name="twitter:title" content="Small Island Developing States Photo Submission" /> +;; <meta name="twitter:description" content="View the album on Flickr." /> +;; <meta name="twitter:image" content="https://farm6.staticflickr.com/5510/14338202952_93595258ff_z.jpg" /> +;; not all of these are required! + (defn format-pronoun-examples [pronoun-declensions] (let [sub-objs (map #(s/join "/" (take 2 %)) pronoun-declensions) - title (str "Pronoun Island: " (prose-comma-list sub-objs) " examples")] + title (str "Pronoun Island: " (prose-comma-list sub-objs) " examples") + examples (map #(apply examples-block %) pronoun-declensions)] (html [:html [:head [:title title] [:meta {:name "viewport" :content "width=device-width"}] + [:meta {:name "description" :content (u/strip-markup examples)}] + [:meta {:name "twitter:card" :content "summary"}] + [:meta {:name "twitter:title" :content title}] + [:meta {:name "twitter:description" :content (u/strip-markup examples)}] [:link {:rel "stylesheet" :href "/pronouns.css"}]] [:body (header-block title) - (map #(apply examples-block %) pronoun-declensions) + examples (footer-block)]]))) (defn lookup-pronouns [pronouns-string] diff --git a/src/pronouns/util.clj b/src/pronouns/util.clj index a000201..01571b6 100644 --- a/src/pronouns/util.clj +++ b/src/pronouns/util.clj @@ -19,8 +19,9 @@ (defn print-and-return "for debugging" [x] (println x) x) -(defn slurp-tabfile [path] - "read a tabfile from a filesystem <path> as a table" +(defn slurp-tabfile + "Read a tabfile from a filesystem <path> as a table" + [path] (let [lines (s/split (slurp path) #"\n")] (map #(s/split % #"\t") lines))) @@ -98,8 +99,13 @@ [table] (map (partial shortest-unambiguous-path table) table)) -(defn vec-coerce [x] +(defn vec-coerce "wrap a value <x> in a vector if it is not already in one. note that if <x> is already in a sequence for which vector? is false, this will add another layer of nesting." + [x] (if (vector? x) x [x])) + +(defn strip-markup [form] + (s/join " " (filter string? (flatten form)))) + diff --git a/src/pronouns/web.clj b/src/pronouns/web.clj index bbbce82..ab4bbb6 100644 --- a/src/pronouns/web.clj +++ b/src/pronouns/web.clj @@ -18,12 +18,15 @@ (:require [compojure.core :refer [defroutes GET PUT POST DELETE ANY]] [compojure.handler :refer [site]] [compojure.route :as route] - [clojure.java.io :as io] [clojure.string :as s] - [ring.middleware.logger :as logger] + [clojure.java.io :as io] + [ring.adapter.jetty :as jetty] + ;[ring.middleware.logger :as logger] [ring.middleware.stacktrace :as trace] [ring.middleware.params :as params] - [ring.adapter.jetty :as jetty] + [ring.middleware.resource :refer [wrap-resource]] + [ring.middleware.content-type :refer [wrap-content-type]] + [ring.middleware.not-modified :refer [wrap-not-modified]] [environ.core :refer [env]] [pronouns.util :as u] [pronouns.pages :as pages])) @@ -63,7 +66,10 @@ (def app (-> app-routes - logger/wrap-with-logger + (wrap-resource "images") + wrap-content-type + wrap-not-modified + ;logger/wrap-with-logger wrap-error-page wrap-gnu-natalie-nguyen trace/wrap-stacktrace diff --git a/test/pronouns/pages_test.clj b/test/pronouns/pages_test.clj index 04c14ce..e32a2ee 100644 --- a/test/pronouns/pages_test.clj +++ b/test/pronouns/pages_test.clj @@ -1,10 +1,12 @@ (ns pronouns.pages-test (:require [pronouns.pages :as pages] - [midje.sweet :refer :all])) + [clojure.test :refer [deftest testing is are]])) -(fact "prose-comma-list turns a list of strings into a prose list with commas" - (pages/prose-comma-list ["foo"]) => "foo" - (pages/prose-comma-list ["foo" "bar"]) => "foo and bar" - (pages/prose-comma-list ["foo" "bar" "baz"]) => "foo, bar, and baz" - (pages/prose-comma-list ["foo" "bar" "baz" "bobble"]) => "foo, bar, baz, and bobble" - (pages/prose-comma-list []) => "") +(deftest prose-comma-list + (testing "prose-comma-list turns a list of strings into a prose list" + (are [call result] (= call result) + (pages/prose-comma-list ["foo"]) "foo" + (pages/prose-comma-list ["foo" "bar"]) "foo and bar" + (pages/prose-comma-list ["foo" "bar" "baz"]) "foo, bar, and baz" + (pages/prose-comma-list ["foo" "bar" "baz" "bobble"]) "foo, bar, baz, and bobble" + (pages/prose-comma-list []) ""))) |