From eb96418015f0f081adae06a6ee7701e110d26f47 Mon Sep 17 00:00:00 2001 From: Sorrel Bri Date: Fri, 28 Feb 2020 11:47:24 -0800 Subject: [PATCH] Updates --- asset-manifest.json | 14 +++++++------- index.html | 2 +- ...he-manifest.b2b4d149a76c2731cd39ee892eb5a673.js | 10 +++++----- service-worker.js | 2 +- static/css/main.20f5ed3b.chunk.css | 2 ++ static/css/main.20f5ed3b.chunk.css.map | 1 + static/css/main.23d018f5.chunk.css | 2 -- static/css/main.23d018f5.chunk.css.map | 1 - static/js/main.19748fc6.chunk.js | 2 ++ static/js/main.19748fc6.chunk.js.map | 1 + static/js/main.e83b5fcd.chunk.js | 2 -- static/js/main.e83b5fcd.chunk.js.map | 1 - stylesheets/_variables.scss | 1 + 13 files changed, 21 insertions(+), 20 deletions(-) rename precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js => precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js (67%) create mode 100644 static/css/main.20f5ed3b.chunk.css create mode 100644 static/css/main.20f5ed3b.chunk.css.map delete mode 100644 static/css/main.23d018f5.chunk.css delete mode 100644 static/css/main.23d018f5.chunk.css.map create mode 100644 static/js/main.19748fc6.chunk.js create mode 100644 static/js/main.19748fc6.chunk.js.map delete mode 100644 static/js/main.e83b5fcd.chunk.js delete mode 100644 static/js/main.e83b5fcd.chunk.js.map diff --git a/asset-manifest.json b/asset-manifest.json index e81134f..08607df 100644 --- a/asset-manifest.json +++ b/asset-manifest.json @@ -1,22 +1,22 @@ { "files": { - "main.css": "/feature-change-applier/static/css/main.23d018f5.chunk.css", - "main.js": "/feature-change-applier/static/js/main.e83b5fcd.chunk.js", - "main.js.map": "/feature-change-applier/static/js/main.e83b5fcd.chunk.js.map", + "main.css": "/feature-change-applier/static/css/main.20f5ed3b.chunk.css", + "main.js": "/feature-change-applier/static/js/main.19748fc6.chunk.js", + "main.js.map": "/feature-change-applier/static/js/main.19748fc6.chunk.js.map", "runtime-main.js": "/feature-change-applier/static/js/runtime-main.7788e262.js", "runtime-main.js.map": "/feature-change-applier/static/js/runtime-main.7788e262.js.map", "static/js/2.0d82b9df.chunk.js": "/feature-change-applier/static/js/2.0d82b9df.chunk.js", "static/js/2.0d82b9df.chunk.js.map": "/feature-change-applier/static/js/2.0d82b9df.chunk.js.map", "index.html": "/feature-change-applier/index.html", - "precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js": "/feature-change-applier/precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js", + "precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js": "/feature-change-applier/precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js", "service-worker.js": "/feature-change-applier/service-worker.js", - "static/css/main.23d018f5.chunk.css.map": "/feature-change-applier/static/css/main.23d018f5.chunk.css.map", + "static/css/main.20f5ed3b.chunk.css.map": "/feature-change-applier/static/css/main.20f5ed3b.chunk.css.map", "static/js/2.0d82b9df.chunk.js.LICENSE": "/feature-change-applier/static/js/2.0d82b9df.chunk.js.LICENSE" }, "entrypoints": [ "static/js/runtime-main.7788e262.js", "static/js/2.0d82b9df.chunk.js", - "static/css/main.23d018f5.chunk.css", - "static/js/main.e83b5fcd.chunk.js" + "static/css/main.20f5ed3b.chunk.css", + "static/js/main.19748fc6.chunk.js" ] } \ No newline at end of file diff --git a/index.html b/index.html index e5965e3..60bd007 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -Phono Change Applier
\ No newline at end of file +Phono Change Applier
\ No newline at end of file diff --git a/precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js b/precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js similarity index 67% rename from precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js rename to precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js index 37f0e90..1377a94 100644 --- a/precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js +++ b/precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js @@ -1,11 +1,11 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ { - "revision": "2ea152c12e88cbef01b4ff372f191088", + "revision": "25ff9b1fd72d6626113070a921792fcf", "url": "/feature-change-applier/index.html" }, { - "revision": "17ec5f2eebae0376c012", - "url": "/feature-change-applier/static/css/main.23d018f5.chunk.css" + "revision": "22556df5700d6c766122", + "url": "/feature-change-applier/static/css/main.20f5ed3b.chunk.css" }, { "revision": "1f9fb9541153efbb7662", @@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/feature-change-applier/static/js/2.0d82b9df.chunk.js.LICENSE" }, { - "revision": "17ec5f2eebae0376c012", - "url": "/feature-change-applier/static/js/main.e83b5fcd.chunk.js" + "revision": "22556df5700d6c766122", + "url": "/feature-change-applier/static/js/main.19748fc6.chunk.js" }, { "revision": "3e2239a2ec4a190765bc", diff --git a/service-worker.js b/service-worker.js index 103815a..f1057f3 100644 --- a/service-worker.js +++ b/service-worker.js @@ -14,7 +14,7 @@ importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts( - "/feature-change-applier/precache-manifest.01f7cbe2671ab45415f2d4c01206cd1b.js" + "/feature-change-applier/precache-manifest.b2b4d149a76c2731cd39ee892eb5a673.js" ); self.addEventListener('message', (event) => { diff --git a/static/css/main.20f5ed3b.chunk.css b/static/css/main.20f5ed3b.chunk.css new file mode 100644 index 0000000..ec3a90b --- /dev/null +++ b/static/css/main.20f5ed3b.chunk.css @@ -0,0 +1,2 @@ +body{margin:0;font-family:Catamaran,Arial,Helvetica,sans-serif;background-color:#281734;color:#d5bfbf}body input[type=text],body textarea{background-color:#1d191a;color:#e8e22e;border:1px solid #d5bfbf;font-family:Fira Code,monospace}body code{font-family:Fira Code,monospace}body p.error{color:red}.App{text-align:center}.App-logo{height:40vmin}.App-header{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;font-size:calc(10px + 2vmin)}.App-link{color:#09d3ac}div.App{max-height:100vh;max-width:100vw;line-height:1.25em;padding:1em}div.App h1{font-size:2em;padding:1em 0}div.App h3{font-size:1.25em;padding:.5em 0}div.App h5{font-size:1.1em;padding:.1em 0;font-weight:800}div.App div.PhonoChangeApplier{display:grid;width:100%;place-items:center center;grid-template-columns:repeat(auto-fit,minmax(20em,1fr));grid-template-rows:repeat(auto-fill,minmax(300px,1fr))}div.App div.PhonoChangeApplier div{max-width:100%;max-height:85vh;margin:1em;overflow-y:scroll}div.Features ul.Features__list li{display:grid;grid-template-columns:1fr 1fr}div.Features ul.Features__list li span.feature--names-and-phones{display:grid;grid-template-columns:repeat(auto-fit,minmax(60px,1fr))}div.Features ul.Features__list li span.feature-name{font-weight:600}div.Features form{display:flex;flex-flow:column}div.Features form input{margin:.1em;font-size:1em}div.Options form{display:flex;flex-flow:column nowrap}div.Output div.Output__container{display:flex;flex-flow:row wrap}div.Output div.Output-epoch{display:flex;flex-flow:column}div.Output div.Output-epoch p.lexicon{display:grid;grid-template-columns:repeat(auto-fit,minmax(5em,1fr))} +/*# sourceMappingURL=main.20f5ed3b.chunk.css.map */ \ No newline at end of file diff --git a/static/css/main.20f5ed3b.chunk.css.map b/static/css/main.20f5ed3b.chunk.css.map new file mode 100644 index 0000000..3fc80c0 --- /dev/null +++ b/static/css/main.20f5ed3b.chunk.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["index.scss","../public/stylesheets/_variables.scss","App.css","PhonoChangeApplier.scss","Features.scss","Options.scss","Output.scss"],"names":[],"mappings":"AAEA,KACE,QAAS,CACT,gDAAsD,CACtD,wBCJmB,CDKnB,aCJe,CDAjB,oCAOI,wBCLuB,CDMvB,aCPmB,CDQnB,wBCTa,CDUb,+BAAmC,CAVvC,UAcI,+BAAmC,CAdvC,aAkBI,SCfc,CCLlB,KACE,iBACF,CAEA,UACE,aACF,CAEA,YACE,gBAAiB,CACjB,YAAa,CACb,qBAAsB,CACtB,kBAAmB,CACnB,sBAAuB,CACvB,4BACF,CAEA,UACE,aACF,CCnBA,QACE,gBAAiB,CACjB,eAAgB,CAChB,kBAAmB,CACnB,WAAY,CAJd,WAOI,aAAc,CACd,aAAc,CARlB,WAYI,gBAAiB,CACjB,cAAgB,CAbpB,WAiBI,eAAgB,CAChB,cAAgB,CAChB,eAAgB,CAnBpB,+BAuBI,YAAa,CACb,UAAW,CACX,yBAA0B,CAC1B,uDAA0D,CAC1D,sDAAyD,CA3B7D,mCA8BM,cAAe,CACf,eAAgB,CAChB,UAAW,CACX,iBAAkB,CCjCxB,kCAGI,YAAa,CACb,6BAA8B,CAJlC,iEAOM,YAAa,CACb,uDAA0D,CARhE,oDAYM,eAAgB,CAZtB,kBAiBI,YAAa,CACb,gBAAiB,CAlBrB,wBAqBM,WAAa,CACb,aAAc,CCtBpB,iBAGI,YAAa,CACb,uBAAwB,CCJ5B,iCAGI,YAAa,CACb,kBAAmB,CAJvB,4BAQI,YAAa,CACb,gBAAiB,CATrB,sCAYM,YAAa,CACb,sDAAyD","file":"main.20f5ed3b.chunk.css","sourcesContent":["@import '../public/stylesheets/variables';\n\nbody {\n margin: 0;\n font-family: 'Catamaran', Arial, Helvetica, sans-serif;\n background-color: map-get($colors, 'main--bg');\n color: map-get($colors, 'main');\n \n textarea, input[type=\"text\"] {\n background-color: map-get($colors, 'text-input--bg');\n color: map-get($colors, 'text-input');\n border: 1px solid map-get($colors, 'main');\n font-family: 'Fira Code', monospace;\n }\n\n code {\n font-family: 'Fira Code', monospace;\n }\n\n p.error {\n color: map-get($colors, 'error');\n }\n\n}\n","$colors: (\n \"main--bg\": #281734,\n \"main\": #d5bfbf,\n \"text-input\": #e8e22e,\n \"text-input--bg\": #1d191a,\n \"error\": #ff0000\n );",".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n}\n\n.App-header {\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n}\n\n.App-link {\n color: #09d3ac;\n}\n","div.App {\n max-height: 100vh;\n max-width: 100vw;\n line-height: 1.25em;\n padding: 1em;\n\n h1 {\n font-size: 2em;\n padding: 1em 0;\n }\n\n h3 {\n font-size: 1.25em;\n padding: 0.5em 0;\n }\n\n h5 {\n font-size: 1.1em;\n padding: 0.1em 0;\n font-weight: 800;\n }\n\n div.PhonoChangeApplier {\n display: grid;\n width: 100%;\n place-items: center center;\n grid-template-columns: repeat(auto-fit, minmax(20em, 1fr));\n grid-template-rows: repeat(auto-fill, minmax(300px, 1fr));\n \n div {\n max-width: 100%;\n max-height: 85vh;\n margin: 1em;\n overflow-y: scroll;\n }\n }\n}","div.Features {\n\n ul.Features__list li {\n display: grid;\n grid-template-columns: 1fr 1fr;\n\n span.feature--names-and-phones {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));\n }\n\n span.feature-name {\n font-weight: 600;\n }\n }\n\n form {\n display: flex;\n flex-flow: column;\n\n input {\n margin: 0.1em;\n font-size: 1em;\n }\n }\n}","div.Options {\n\n form {\n display: flex;\n flex-flow: column nowrap;\n }\n\n}","div.Output {\n\n div.Output__container {\n display: flex;\n flex-flow: row wrap;\n }\n\n div.Output-epoch {\n display: flex;\n flex-flow: column;\n\n p.lexicon {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(5em, 1fr));\n }\n }\n\n}"]} \ No newline at end of file diff --git a/static/css/main.23d018f5.chunk.css b/static/css/main.23d018f5.chunk.css deleted file mode 100644 index 2b07904..0000000 --- a/static/css/main.23d018f5.chunk.css +++ /dev/null @@ -1,2 +0,0 @@ -body{margin:0;font-family:Catamaran,Arial,Helvetica,sans-serif;background-color:#281734;color:#d5bfbf}body input[type=text],body textarea{background-color:#1d191a;color:#e8e22e;border:1px solid #d5bfbf;font-family:Fira Code,monospace}body code{font-family:Fira Code,monospace}.App{text-align:center}.App-logo{height:40vmin}.App-header{min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;font-size:calc(10px + 2vmin)}.App-link{color:#09d3ac}div.App{max-height:100vh;max-width:100vw;line-height:1.25em;padding:1em}div.App h1{font-size:2em;padding:1em 0}div.App h3{font-size:1.25em;padding:.5em 0}div.App h5{font-size:1.1em;padding:.1em 0;font-weight:800}div.App div.PhonoChangeApplier{display:grid;width:100%;place-items:center center;grid-template-columns:repeat(auto-fit,minmax(20em,1fr));grid-template-rows:repeat(auto-fill,minmax(300px,1fr))}div.App div.PhonoChangeApplier div{max-width:100%;max-height:85vh;margin:1em;overflow-y:scroll}div.Features ul.Features__list li{display:grid;grid-template-columns:1fr 1fr}div.Features ul.Features__list li span.feature--names-and-phones{display:grid;grid-template-columns:repeat(auto-fit,minmax(60px,1fr))}div.Features ul.Features__list li span.feature-name{font-weight:600}div.Features form{display:flex;flex-flow:column}div.Features form input{margin:.1em;font-size:1em}div.Options form{display:flex;flex-flow:column nowrap}div.Output div.Output__container{display:flex;flex-flow:row wrap}div.Output div.Output-epoch{display:flex;flex-flow:column}div.Output div.Output-epoch p.lexicon{display:grid;grid-template-columns:repeat(auto-fit,minmax(5em,1fr))} -/*# sourceMappingURL=main.23d018f5.chunk.css.map */ \ No newline at end of file diff --git a/static/css/main.23d018f5.chunk.css.map b/static/css/main.23d018f5.chunk.css.map deleted file mode 100644 index 0db898a..0000000 --- a/static/css/main.23d018f5.chunk.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["index.scss","../public/stylesheets/_variables.scss","App.css","PhonoChangeApplier.scss","Features.scss","Options.scss","Output.scss"],"names":[],"mappings":"AAEA,KACE,QAAS,CACT,gDAAsD,CACtD,wBCJmB,CDKnB,aCJe,CDAjB,oCAOI,wBCLuB,CDMvB,aCPmB,CDQnB,wBCTa,CDUb,+BAAmC,CAVvC,UAcI,+BAAmC,CEhBvC,KACE,iBACF,CAEA,UACE,aACF,CAEA,YACE,gBAAiB,CACjB,YAAa,CACb,qBAAsB,CACtB,kBAAmB,CACnB,sBAAuB,CACvB,4BACF,CAEA,UACE,aACF,CCnBA,QACE,gBAAiB,CACjB,eAAgB,CAChB,kBAAmB,CACnB,WAAY,CAJd,WAOI,aAAc,CACd,aAAc,CARlB,WAYI,gBAAiB,CACjB,cAAgB,CAbpB,WAiBI,eAAgB,CAChB,cAAgB,CAChB,eAAgB,CAnBpB,+BAuBI,YAAa,CACb,UAAW,CACX,yBAA0B,CAC1B,uDAA0D,CAC1D,sDAAyD,CA3B7D,mCA8BM,cAAe,CACf,eAAgB,CAChB,UAAW,CACX,iBAAkB,CCjCxB,kCAGI,YAAa,CACb,6BAA8B,CAJlC,iEAOM,YAAa,CACb,uDAA0D,CARhE,oDAYM,eAAgB,CAZtB,kBAiBI,YAAa,CACb,gBAAiB,CAlBrB,wBAqBM,WAAa,CACb,aAAc,CCtBpB,iBAGI,YAAa,CACb,uBAAwB,CCJ5B,iCAGI,YAAa,CACb,kBAAmB,CAJvB,4BAQI,YAAa,CACb,gBAAiB,CATrB,sCAYM,YAAa,CACb,sDAAyD","file":"main.23d018f5.chunk.css","sourcesContent":["@import '../public/stylesheets/variables';\n\nbody {\n margin: 0;\n font-family: 'Catamaran', Arial, Helvetica, sans-serif;\n background-color: map-get($colors, 'main--bg');\n color: map-get($colors, 'main');\n \n textarea, input[type=\"text\"] {\n background-color: map-get($colors, 'text-input--bg');\n color: map-get($colors, 'text-input');\n border: 1px solid map-get($colors, 'main');\n font-family: 'Fira Code', monospace;\n }\n\n code {\n font-family: 'Fira Code', monospace;\n }\n\n}\n","$colors: (\n \"main--bg\": #281734,\n \"main\": #d5bfbf,\n \"text-input\": #e8e22e,\n \"text-input--bg\": #1d191a,\n );",".App {\n text-align: center;\n}\n\n.App-logo {\n height: 40vmin;\n}\n\n.App-header {\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n}\n\n.App-link {\n color: #09d3ac;\n}\n","div.App {\n max-height: 100vh;\n max-width: 100vw;\n line-height: 1.25em;\n padding: 1em;\n\n h1 {\n font-size: 2em;\n padding: 1em 0;\n }\n\n h3 {\n font-size: 1.25em;\n padding: 0.5em 0;\n }\n\n h5 {\n font-size: 1.1em;\n padding: 0.1em 0;\n font-weight: 800;\n }\n\n div.PhonoChangeApplier {\n display: grid;\n width: 100%;\n place-items: center center;\n grid-template-columns: repeat(auto-fit, minmax(20em, 1fr));\n grid-template-rows: repeat(auto-fill, minmax(300px, 1fr));\n \n div {\n max-width: 100%;\n max-height: 85vh;\n margin: 1em;\n overflow-y: scroll;\n }\n }\n}","div.Features {\n\n ul.Features__list li {\n display: grid;\n grid-template-columns: 1fr 1fr;\n\n span.feature--names-and-phones {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));\n }\n\n span.feature-name {\n font-weight: 600;\n }\n }\n\n form {\n display: flex;\n flex-flow: column;\n\n input {\n margin: 0.1em;\n font-size: 1em;\n }\n }\n}","div.Options {\n\n form {\n display: flex;\n flex-flow: column nowrap;\n }\n\n}","div.Output {\n\n div.Output__container {\n display: flex;\n flex-flow: row wrap;\n }\n\n div.Output-epoch {\n display: flex;\n flex-flow: column;\n\n p.lexicon {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(5em, 1fr));\n }\n }\n\n}"]} \ No newline at end of file diff --git a/static/js/main.19748fc6.chunk.js b/static/js/main.19748fc6.chunk.js new file mode 100644 index 0000000..64b71f7 --- /dev/null +++ b/static/js/main.19748fc6.chunk.js @@ -0,0 +1,2 @@ +(this["webpackJsonpfeature-change-applier"]=this["webpackJsonpfeature-change-applier"]||[]).push([[0],[,,,,,,,,,,,,function(e,t,n){e.exports=n(28)},,,,,function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},,,function(e,t,n){},function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),o=n(5),c=n.n(o),u=(n(17),n(18),n(3)),i=(n(19),n(20),function(e){var t=e.lexicon,n=e.dispatch;return r.a.createElement("div",{className:"ProtoLang","data-testid":"ProtoLang"},r.a.createElement("h3",null,"Proto Language Lexicon"),r.a.createElement("br",null),r.a.createElement("form",{"data-testid":"ProtoLang-Lexicon"},r.a.createElement("textarea",{name:"lexicon",cols:"30",rows:"10","data-testid":"ProtoLang-Lexicon__textarea",value:function(){return t?t.map((e="lexeme",function(t){return t[e]})).join("\n"):"";var e}(),onChange:function(e){console.log(e.target.value.split(/\n/).map((function(e){return{lexeme:e.split("#")[0].trim(),epoch:e.split("#")[1]||""}}))),n({type:"SET_LEXICON",value:e.target.value.split(/\n/).map((function(e){return{lexeme:e.split("#")[0].trim(),epoch:e.split("#")[1]||""}}))})}})))}),s=n(4),l=(n(21),function(e){return""===e?[""]:e.split("/").map((function(e){return e.trim()}))}),p=function(e){var t=Object(u.a)(e,3),n=t[0],a=t[1],r=t[2];return{type:"ADD_FEATURE",value:{positivePhones:l(n),negativePhones:l(a),feature:r}}},m=function(e){var t=e.phones,n=e.features,o=e.dispatch,c=Object(a.useState)("aspirated"),i=Object(u.a)(c,2),l=i[0],m=i[1],h=Object(a.useState)("t\u02b0 / p\u02b0 / k\u02b0"),f=Object(u.a)(h,2),v=f[0],g=f[1],d=Object(a.useState)("t / p / k"),E=Object(u.a)(d,2),b=E[0],O=E[1];return r.a.createElement("div",{className:"Features","data-testid":"Features"},r.a.createElement("h3",null,"Phonetic Features"),r.a.createElement("ul",{className:"Features__list","data-testid":"Features-list"},t?r.a.createElement(r.a.Fragment,null,function(e){var t=function(e){return function(t){return t[e]}};return function(e){return e.map((function(e,t){var n=Object.keys(e),a=e[n],o=a.plus,c=a.minus;return r.a.createElement("li",{key:"feature__".concat(n)},r.a.createElement("span",{className:"feature--names-and-phones"},r.a.createElement("span",{className:"feature--feature-name"},"[+ ".concat(n,"]")),r.a.createElement("span",{className:"feature--feature-phones"},o)),r.a.createElement("span",{className:"feature--names-and-phones"},r.a.createElement("span",{className:"feature--feature-name"},"[- ".concat(n,"]")),r.a.createElement("span",{className:"feature--feature-phones"},c)))}))}(function(e){return Object.keys(e).map((function(n){var a=e[n].positive.map(t("grapheme")).join(" / "),r=e[n].negative.map(t("grapheme")).join(" / ");return Object(s.a)({},n,{plus:a,minus:r})}))}(e))}(n)):r.a.createElement(r.a.Fragment,null)),r.a.createElement("form",{className:"Features__form","data-testid":"Features-form"},r.a.createElement("input",{type:"text",name:"feature",value:l,onChange:function(e){return m(e.target.value)}}),r.a.createElement("label",{htmlFor:"positive-phones"},"+",r.a.createElement("input",{id:"positive-phones",type:"text",name:"phonemes",value:v,onChange:function(e){return g(e.target.value)}})),r.a.createElement("label",{htmlFor:"negative-phones"},"-",r.a.createElement("input",{id:"negative-phones",type:"text",name:"phonemes",value:b,onChange:function(e){return O(e.target.value)}})),r.a.createElement("input",{type:"submit",onClick:function(e){return function(e){return function(t){return function(n){return function(a){return e.preventDefault(),t(n(a))}}}}(e)(o)(p)([v,b,l])},value:"Add feature"})))},h=(n(22),n(2)),f=(n(23),function(e){var t=e.epochIndex,n=e.error,o=e.removeEpoch,c=e.epochs,i=Object(a.useState)(e.epoch?e.epoch:{name:"",changes:[""],parent:"none"}),s=Object(u.a)(i,2),l=s[0],p=s[1],m=function(n,a){a(n),e.updateEpoch(l,t)};Object(a.useEffect)((function(){e.updateEpoch(l,t)}),[l]);var f=function(e){return r.a.createElement("option",{key:"".concat(l.name,"__parent-option--").concat(e.name),value:e.name},e.name)},v=function(e){return e.name===l.name?{name:"none"}:e},g=function(e){return!e.parent||e.parent!==l.name};return r.a.createElement(r.a.Fragment,null,r.a.createElement("h4",null,l.name),n?r.a.createElement("p",{className:"error"},n):r.a.createElement(r.a.Fragment,null),r.a.createElement("form",{className:"SoundChangeSuite__form","data-testid":"".concat(l.name,"_SoundChangeSuite_changes")},r.a.createElement("label",{htmlFor:"".concat(l.name,"-name")},"Name:"),r.a.createElement("input",{type:"text",name:"epoch",id:"".concat(l.name,"-name"),cols:"30",rows:"1",value:l.name,onChange:function(e){return m(e,(function(){p(Object(h.a)({},l,{name:e.target.value}))}))}}),t?r.a.createElement(r.a.Fragment,null,r.a.createElement("label",{htmlFor:"".concat(l.name,"-parent")},"Parent Epoch:"),r.a.createElement("select",{name:"parent",list:"".concat(l.name,"-parents-list"),value:l.parent||"none",onChange:function(e){return m(e,(function(){console.log(e.target.value),p(Object(h.a)({},l,{parent:e.target.value}))}))}},c.map(v).filter(g).map(f))):r.a.createElement(r.a.Fragment,null),r.a.createElement("textarea",{name:"changes",id:"",cols:"30",rows:"10",value:l.changes.join("\n"),onChange:function(e){return m(e,(function(){return p(Object(h.a)({},l,{changes:e.target.value.split(/\n/).map((function(e){return" "===e?"[+ feature]>[- feature]/_#":e}))}))}))}})),r.a.createElement("form",{onSubmit:function(e){return o(e,l.name)}},r.a.createElement("input",{type:"submit",name:"remove-epoch",value:"remove ".concat(l.name)})))}),v=function(e){var t=e.epochs,n=e.errors,a=e.dispatch,o=function(e,t){e.preventDefault(),a({type:"REMOVE_EPOCH",value:{name:t}})},c=function(e,t){var n={name:e.name,index:t,changes:e.changes,parent:e.parent};a({type:"SET_EPOCH",value:n})},u=function(e){return e===t.length-1?r.a.createElement("form",{onSubmit:function(e){return function(e){e.preventDefault();var n=t.length+1;a({type:"ADD_EPOCH",value:{name:"Epoch ".concat(n)}})}(e)}},r.a.createElement("input",{type:"submit",name:"add-epoch",value:"Add Epoch"})):r.a.createElement(r.a.Fragment,null)};return r.a.createElement(r.a.Fragment,null,t.length?t.map((function(e,a){var i=n.epoch?n.error:null;return r.a.createElement("div",{className:"SoundChangeSuite","data-testid":"".concat(e.name,"_SoundChangeSuite"),key:"epoch-".concat(a)},r.a.createElement(f,{epochIndex:a,epoch:e,updateEpoch:c,removeEpoch:o,epochs:t,error:i}),u(a))})):u(-1))},g=(n(24),n(10)),d=n.n(g),E=function(e){var t=e.options,n=e.dispatch,o=Object(a.useState)(""),c=Object(u.a)(o,2),i=c[0],s=c[1],l=function(e){var t=e.target,a=t.name,r=t.id;n({type:"SET_OPTIONS",value:{option:a,setValue:r}})};return r.a.createElement("div",{className:"Options","data-testid":"Options"},r.a.createElement("h3",null,"Modeling Options"),r.a.createElement("form",{onSubmit:function(e){return function(e,t){e.preventDefault(),n({type:"RUN",value:t})}(e,t)},"data-testid":"Options-form"},r.a.createElement("input",{type:"radio",name:"output",id:"default",checked:!t||"default"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"default"},"Default",r.a.createElement("span",{className:"Options__output-example"}," output")),r.a.createElement("input",{type:"radio",name:"output",id:"proto",checked:!!t&&"proto"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"proto"},"Proto",r.a.createElement("span",{className:"Options__output-example"}," output [proto]")),r.a.createElement("input",{type:"radio",name:"output",id:"diachronic",checked:!!t&&"diachronic"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"diachronic"},"Diachronic",r.a.createElement("span",{className:"Options__output-example"}," *proto > *epoch > output")),r.a.createElement("input",{type:"submit",value:"Run Changes"})),r.a.createElement("form",{onSubmit:function(){}},r.a.createElement("label",null,"Load from a prior run:",r.a.createElement("select",{value:i,onChange:function(e){return s(e.target.value)}},localStorage.phonoChange?d.a.get("phonoChange").map((function(e){return r.a.createElement("option",{key:e.name,value:e.name},e.name)})):r.a.createElement(r.a.Fragment,null))),r.a.createElement("input",{type:"submit",value:"Submit"})))},b=(n(27),function(e){var t=e.results,n=e.options,a=(e.errors,function(){return t.map((function(e,t){var n=e.lexicon.map((function(t,n){return r.a.createElement("span",{key:"".concat(e.pass,"-").concat(n)},t)}));return r.a.createElement("div",{key:"epoch-".concat(t),className:"Output-epoch"},r.a.createElement("h5",null,e.pass),r.a.createElement("p",{className:"lexicon"},n))}))});return r.a.createElement("div",{className:"Output","data-testid":"Output"},r.a.createElement("h3",null,"Results of Run"),r.a.createElement("div",{"data-testid":"Output-lexicon",className:"Output__container"},t&&t.length?function(){switch(n.output){case"default":return a();default:return r.a.createElement(r.a.Fragment,null)}}():r.a.createElement(r.a.Fragment,null)))}),O=n(1),j=function(e,t,n){var a={lexeme:e,epoch:n.epochs[0]};if(t){var r=n.epochs.findIndex((function(e){return e.name===t}));r>0&&(a.epoch=n.epochs[r])}return a},x=function(e,t){return t.split("").reduce((function(t,n,a){return t=0===a?e[n]:t[n]}),{})},_=function(e,t,n,a){var r={};return t.split("").forEach((function(o,c){r=0===c?e[o]:r[o],c===t.split("").length-1&&(r.features=Object(h.a)({},r.features,Object(s.a)({},n,a)))})),e},w=n(11),y=n(6);function F(){var e=Object(y.a)(["Error in line ",": ",""]);return F=function(){return e},e}function N(){var e=Object(y.a)(["Error in line ",": ",""]);return N=function(){return e},e}var C=function(e){return function(t){return t[e]}},S=function(e,t,n){var a=Object(u.a)(e,2),r=a[0],o=a[1];return"".concat(r).concat(t).concat(o).concat(n)},k=function(e,t){try{var n=function(e){if(!e.match(/>/g))throw"Insert '>' operator between target and result";if(!e.match(/\//g))throw"Insert '/' operator between change and environment";if(!e.match(/_/g))throw"Insert '_' operator in environment";if(e.match(/>/g).length>1)throw"Too many '>' operators";if(e.match(/\//g).length>1)throw"Too many '/' operators";if(e.match(/_/g).length>1)throw"Too many '_' operators";return e.split(/>|\/|_/g)}(e),a=Object(u.a)(n,4),r=a[0],o=a[1];return{environment:{pre:a[2],position:r,post:a[3]},newFeatures:o}}catch(c){throw S(N(),t+1,c)}},P=function(e){return"-"!==e&&"+"!==e&&"]"!==e&&"["!==e&&" "!==e},D=function(e,t){try{var n=t?/(?=\+.).*(?<=\-)|(?=\+.).*(?!\-).*(?<=\])/g:/(?=\-.).*(?<=\+)|(?=\-.).*(?!\+).*(?<=\])/g,a=e.match(n)||[null],r=Object(u.a)(a,1)[0];return r?(function(e){var t=e.match(/\W/g).filter(P);if(t.length)throw"Unknown token '".concat(t[0],"'")}(r),r.trim().match(/\w+/g).reduce((o=t,function(e,t){return Object(h.a)({},e,Object(s.a)({},t,o))}),{})):{}}catch(c){throw c}var o},A=function(e){return Object(h.a)({},D(e,!0),{},D(e,!1))},T=function(e,t){if(e){if("."===e)return[];if("#"===e)return["#"];if("0"===e)return[];var n=e.match(/\[.*\]/);try{return n?e.split("[").filter((function(e){return e})).map(A):function(e,t){var n=[],a=t.length-1,r={};return Object(O.a)(t).forEach((function(t,o){return o||a||n.push(e[t].features),o?o===a?r[t]?n.push(r[t]):n.push(r,e[t]):!r[t]&&r.features?(n.push(r),r=e[t]):r[t]?void 0:r=r[t]:r=e[t]})),n}(t,e)}catch(a){throw a}}return{}},I=function(e,t){var n=e.changes;try{return n.map(k).map(function(e){return function(t,n){try{var a=t.newFeatures,r=t.environment,o=r.pre,c=r.position,u=r.post;return{environment:{pre:T(o,e),position:T(c,e),post:T(u,e)},newFeatures:T(a,e)}}catch(i){throw S(F(),n+1,i)}}}(t))}catch(a){throw{epoch:e.name,error:a}}},L=function(e,t){return!t||t.filter(function(e){return function(t,n){var a=e[n].features;return Object.entries(t).reduce((function(e,t){var n=Object(u.a)(t,2),r=n[0],o=n[1];return!!e&&(!!a.hasOwnProperty(r)&&(!a[r]&&!o||a[r]===o))}),!0)}}(e)).length===t.length},R=function(e){return Object.entries(e)},H=function(e,t){var n=Object(u.a)(t,2),a=n[0],r=n[1];return Object(h.a)({},e,Object(s.a)({},a,r))},U=function(e,t,n){if(!t)return{};var a=R(t).reduce(H,Object(h.a)({},e.features)),r=R(a).map(function(e){return function(t){var n=Object(u.a)(t,2),a=n[0],r=n[1];return e[a][r?"positive":"negative"]}}(n));return r.reduce((function(e,t,n,a){return e.filter(function(e,t){return function(n){return e.map(C(t)).includes(n[t])}}(t,"grapheme"))}),r[r.length-1])[0]},M=function(e,t,n){var a=t.environment,r=a.pre,o=a.post,c=a.position;return e.reduce((function(a,u,i){if(r.find((function(e){return"#"===e})))return function(e,t,n,a,r,o,c,u,i){if(o!==t.length-1)return[].concat(Object(O.a)(e),[r]);if(!L([r],a))return[].concat(Object(O.a)(e),[r]);if(!L(c.slice(o+a.length,o+n.length+a.length),n))return[].concat(Object(O.a)(e),[r]);var s=U(r,u[0],i);return s.grapheme?[].concat(Object(O.a)(e),[s]):Object(O.a)(e)}(a,r,o,c,u,i,e,t.newFeatures,n);if(o.find((function(e){return"#"===e})))return function(e,t,n,a,r,o,c,u,i){if(o+n.length!==c.length)return[].concat(Object(O.a)(e),[r]);if(!L(c.slice(o-t.length,o),t))return[].concat(Object(O.a)(e),[r]);if(!L([r],a))return[].concat(Object(O.a)(e),[r]);var s=U(r,u[0],i);return s.grapheme?[].concat(Object(O.a)(e),[s]):Object(O.a)(e)}(a,r,o,c,u,i,e,t.newFeatures,n);if(i=e.length-o.length)return[].concat(Object(O.a)(a),[u]);if(!L(e.slice(i-r.length,i),r))return[].concat(Object(O.a)(a),[u]);if(!L([u],c))return[].concat(Object(O.a)(a),[u]);if(!L(e.slice(i,i+o.length),o))return[].concat(Object(O.a)(a),[u]);var s=U(u,t.newFeatures[0],n);return s&&s.grapheme?[].concat(Object(O.a)(a),[s]):Object(O.a)(a)}),[])},V=function(e){return function(t){return e.map((function(e){var n=e.lexeme;return function(e,t){var n=[],a=t.length-1,r={};return Object(O.a)(t).forEach((function(t,o){return o?o===a?r[t]?n.push(r[t]):n.push(r,e[t]):!r[t]&&r.features?(n.push(r),r=e[t]):r[t]?void 0:r=r[t]:r=e[t]})),n}(t,n)}))}},W=function(e){return e.map(C("grapheme")).join("")},X=function(e){var t=e.lexicon,n=Object(w.a)(e,["lexicon"]);return Object(h.a)({},n,{lexicon:t.map(W)})},B=function(e,t){try{var n=e.epochs.reduce((function(t,n,a){var r,o=e.phones,c=e.features,u=e.lexicon;n.parent&&(r=t.find((function(e){return e.pass===n.parent})).lexicon),n.parent||(r=V(u)(o));var i=I(n,o),s=function(e){return function(t){return function(n){return e.map((function(e){return t.reduce((function(e,t,a){return M(e,t,n)}),e)}))}}}(r)(i)(c),l={pass:n.name,lexicon:s};return n.parent&&(l.parent=n.parent),[].concat(Object(O.a)(t),[l])}),[]).map(X);return Object(h.a)({},e,{results:n,errors:{}})}catch(a){return console.log(a),Object(h.a)({},e,{errors:a})}},J=function(e){var t={epochs:[{name:"epoch 1",changes:["[+ occlusive - nasal]>[+ occlusive + nasal]/n_.","a>\u026f/._#","[+ sonorant - low rounded high back]>0/._.","[+ obstruent]>[+ obstruent aspirated ]/#_.","[+ sonorant - rounded]>[+ sonorant + rounded]/._#"]}],phones:{a:{grapheme:"a",features:{sonorant:!0,back:!0,low:!0,high:!1,rounded:!1}},u:{grapheme:"u",features:{sonorant:!0,back:!0,low:!1,high:!0,rounded:!0}},"\u026f":{grapheme:"\u026f",features:{sonorant:!0,back:!0,low:!1,high:!0,rounded:!1}},"\u0259":{grapheme:"\u0259",features:{sonorant:!0,low:!1,rounded:!1,high:!1,back:!1}},t:{grapheme:"t",features:{occlusive:!0,coronal:!0,obstruent:!0,nasal:!1},"\u02b0":{grapheme:"t\u02b0",features:{occlusive:!0,coronal:!0,obstruent:!0,aspirated:!0}}},n:{grapheme:"n",features:{sonorant:!0,nasal:!0,occlusive:!0,coronal:!0}}},options:{output:"default",save:!1},results:[],errors:{},features:{},lexicon:[]};return t.features={sonorant:{positive:[t.phones.a,t.phones.u,t.phones.\u026f,t.phones.\u0259,t.phones.n],negative:[]},back:{positive:[t.phones.a,t.phones.u,t.phones.\u026f],negative:[t.phones.\u0259]},low:{positive:[t.phones.a],negative:[t.phones.u,t.phones.\u026f,t.phones.\u0259]},high:{positive:[t.phones.u,t.phones.\u026f],negative:[t.phones.a,t.phones.\u0259]},rounded:{positive:[t.phones.u],negative:[t.phones.a,t.phones.\u026f,t.phones.\u0259]},occlusive:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},coronal:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},obstruent:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},nasal:{positive:[t.phones.n],negative:[t.phones.t,t.phones.t.\u02b0]},aspirated:{positive:[t.phones.t.\u02b0],negative:[t.phones.t]}},t.lexicon=[{lexeme:"anta",epoch:t.epochs[0]},{lexeme:"anat",epoch:t.epochs[0]},{lexeme:"an\u0259t",epoch:t.epochs[0]},{lexeme:"anna",epoch:t.epochs[0]},{lexeme:"tan",epoch:t.epochs[0]},{lexeme:"\u0259nta",epoch:t.epochs[0]}],e>-1&&(t.epochs[0].changes=t.epochs[0].changes.splice(0,e)),t},$=function(e,t){switch(t.type){case"INIT":return J();case"ADD_LEXEME":return function(e,t){var n=j(t.value.lexeme,t.value.epoch,e);return Object(h.a)({},e,{lexicon:[].concat(Object(O.a)(e.lexicon),[n])})}(e,t);case"SET_LEXICON":return function(e,t){var n=t.value;return n=n.map((function(t){return j(t.lexeme,t.epoch,e)})),Object(h.a)({},e,{lexicon:n})}(e,t);case"ADD_EPOCH":return function(e,t){var n={name:t.value.name,changes:t.value.changes||[""],parent:null};return Object(h.a)({},e,{epochs:[].concat(Object(O.a)(e.epochs),[n])})}(e,t);case"SET_EPOCH":return function(e,t){var n=t.value.index;if("number"!==typeof n)return e;var a=e.epochs;return a[n].name=t.value.name?t.value.name:a[n].name,a[n].changes=t.value.changes?t.value.changes:a[n].changes,a[n].parent=t.value.parent&&"none"!==t.value.parent?t.value.parent:null,Object(h.a)({},e,{epochs:Object(O.a)(a)})}(e,t);case"REMOVE_EPOCH":return function(e,t){var n=e.epochs.filter((function(e){return e.name!==t.value.name}));return Object(h.a)({},e,{epochs:Object(O.a)(n)})}(e,t);case"ADD_FEATURE":return function(e,t){var n=t.value.positivePhones||[],a=t.value.negativePhones||[],r=t.value.feature,o=[].concat(Object(O.a)(n),Object(O.a)(a)).reduce((function(e,t){return function(e,t){var n={};return t.split("").forEach((function(a,r){r&&(n[a]={}),r||e[a]||(e[a]={}),n=0===r?e[a]:n[a],r===t.length-1&&(n.grapheme=t)})),e}(e,t)}),e.phones);n&&(n.reduce((function(e,t){return _(e,t,r,!0)}),o),n=n.map((function(e){return x(o,e)}))),a&&(a.reduce((function(e,t){return _(e,t,r,!1)}),o),a=a.map((function(e){return x(o,e)})));var c=Object(s.a)({},t.value.feature,{positive:n,negative:a});return Object(h.a)({},e,{features:Object(h.a)({},e.features,{},c),phones:o})}(e,t);case"SET_OPTIONS":return function(e,t){var n=t.value.option,a=t.value.setValue;"true"===a&&(a=!0),"false"===a&&(a=!1);var r=Object(h.a)({},e);return r.options[n]=a,r}(e,t);case"RUN":return B(e);default:return e}},q=function(){var e=Object(a.useReducer)($,{},J),t=Object(u.a)(e,2),n=t[0],o=t[1],c=n.lexicon,s=n.phones,l=(n.phonemes,n.epochs),p=n.options,h=n.features,f=n.results,g=n.errors;return r.a.createElement("div",{className:"PhonoChangeApplier","data-testid":"PhonoChangeApplier"},r.a.createElement(i,{lexicon:c,dispatch:o}),r.a.createElement(m,{phones:s,features:h,dispatch:o}),r.a.createElement(v,{epochs:l,errors:g,dispatch:o}),r.a.createElement(E,{options:p,dispatch:o}),r.a.createElement(b,{results:f,options:p,dispatch:o}))};var z=function(){return r.a.createElement("div",{className:"App","data-testid":"App"},r.a.createElement("h1",null,"Phono Change Applier"),r.a.createElement(q,null))};Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));c.a.render(r.a.createElement(z,null),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then((function(e){e.unregister()}))}],[[12,1,2]]]); +//# sourceMappingURL=main.19748fc6.chunk.js.map \ No newline at end of file diff --git a/static/js/main.19748fc6.chunk.js.map b/static/js/main.19748fc6.chunk.js.map new file mode 100644 index 0000000..9865809 --- /dev/null +++ b/static/js/main.19748fc6.chunk.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["components/ProtoLang.js","components/Features.js","components/SoundChangeSuite.js","components/Epochs.js","components/Options.js","components/Output.js","reducers/reducer.lexicon.js","reducers/reducer.features.js","reducers/reducer.results.js","reducers/reducer.init.js","reducers/reducer.js","reducers/reducer.epochs.js","reducers/reducer.options.js","PhonoChangeApplier.js","App.js","serviceWorker.js","index.js"],"names":["ProtoLang","lexicon","dispatch","className","data-testid","name","cols","rows","value","map","property","object","join","renderLexicon","onChange","e","console","log","target","split","line","lexeme","trim","epoch","type","parseNewPhones","somePhones","phone","buildAddFeatureAction","newPositivePhones","newNegativePhones","feature","positivePhones","negativePhones","Features","phones","features","useState","setFeature","setNewPositivePhones","setNewNegativePhones","featureObject","getProperty","featureMap","index","featureName","Object","keys","plus","minus","key","getFeatureMapJSX","plusPhones","positive","minusPhones","negative","getFeatureMap","parsePhonesFromFeatureObject","htmlFor","id","onClick","dispatchFunction","actionBuilder","actionParameters","preventDefault","handleClickDispatch","SoundChangeSuite","props","epochIndex","error","removeEpoch","epochs","changes","parent","setEpoch","changeHandler","cb","updateEpoch","useEffect","renderOptionFromEpoch","thisEpoch","replaceCurrentEpoch","isViableParent","list","filter","change","onSubmit","Epochs","errors","epochName","dispatchValue","renderAddEpochButton","length","addEpoch","epochError","Options","options","load","setLoad","handleRadioChange","option","setValue","handleFormSubmit","checked","output","localStorage","phonoChange","ls","get","priorRun","Output","results","renderDefault","i","pass","renderResults","makeLexeme","state","newLexeme","findIndex","findPhone","reduce","node","graph","addFeatureToPhone","featureKey","featureValue","forEach","errorMessage","location","err","prefix","separator","decomposeRule","rule","match","lintRule","position","newFeatures","environment","pre","post","isUnknownFeatureToken","token","getFeatures","phoneme","featureBoolean","featureMatch","unknownTokens","doesFeatureRuleContainUnknownToken","bool","mapToPositiveAndNegativeFeatures","mapStringToFeatures","ruleString","ruleBrackets","v","featureBundle","lastIndex","push","findFeaturesFromGrapheme","decomposeRules","ruleBundle","mapRuleBundleToFeatureBundle","isEnvironmentBoundByRule","phonemeFeatures","ruleFeatures","ruleFeature","entries","hasOwnProperty","isPhonemeBoundByRule","getEntries","reduceFeatureValues","newPhoneme","newFeature","newValue","transformPhoneme","newPhonemeFeatures","newPhonemeCandidates","transformFeatureValues","candidates","candidatesSubset","array","candidate","includes","isObjectWithPropertyInArray","transformLexeme","lexemeBundle","find","val","slice","grapheme","transformLexemeInitial","transformLexemeCoda","formBundleFromLexicon","findFeaturesFromLexeme","stringifyLexeme","stringifyResults","passResults","run","action","_","lexiconBundle","result","transformLexicon","initState","changesArgument","a","sonorant","back","low","high","rounded","u","ɯ","ə","t","occlusive","coronal","obstruent","nasal","ʰ","aspirated","n","save","splice","stateReducer","addLexeme","newLexicon","setLexicon","newEpoch","mutatedEpochs","newFeatureName","newPhoneObject","phoneObject","addPhones","positivePhone","negativePhone","addFeature","mutatedState","setOptions","PhonoChangeApplier","useReducer","phonemes","App","Boolean","window","hostname","ReactDOM","render","document","getElementById","navigator","serviceWorker","ready","then","registration","unregister"],"mappings":"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","file":"static/js/main.19748fc6.chunk.js","sourcesContent":["import React from 'react';\nimport './ProtoLang.scss';\n\nconst ProtoLang = ({ lexicon, dispatch }) => {\n const getProperty = property => object => object[property];\n const renderLexicon = () => {\n if (!lexicon) return '';\n // Code for optionally rendering epoch name with lexeme\n // `\\t#${lexeme.epoch.name}`\n return lexicon.map(getProperty('lexeme')).join('\\n');\n }\n\n return (\n
\n

Proto Language Lexicon

\n
\n
\n {\n console.log(e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n }))\n dispatch({\n type: 'SET_LEXICON', \n value: e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n })\n })\n }\n }>\n \n \n
\n );\n}\n\nexport default ProtoLang;","// @flow\nimport React, {useState} from 'react';\nimport './Features.scss';\n\nimport type { featureAction } from '../reducers/reducer.features';\n\nconst parsePhonesFromFeatureObject = featureObject => {\n const getProperty = property => object => object[property]\n \n const getFeatureMap = (featureObject) => {\n return Object.keys(featureObject).map(feature => {\n const plusPhones = featureObject[feature].positive.map(getProperty('grapheme')).join(' / ');\n const minusPhones = featureObject[feature].negative.map(getProperty('grapheme')).join(' / ');\n return {[feature]: {plus: plusPhones, minus: minusPhones}}\n })\n }\n\n const getFeatureMapJSX = (featureMap) => {\n return featureMap.map((feature, index) => {\n const featureName = Object.keys(feature);\n const { plus, minus } = feature[featureName];\n return (\n
  • \n \n \n {`[+ ${featureName}]`}\n \n \n {plus}\n \n \n \n \n {`[- ${featureName}]`}\n \n \n {minus}\n \n \n
  • \n )\n })\n }\n\n const featureMap = getFeatureMap(featureObject);\n const featureMapJSX = getFeatureMapJSX(featureMap);\n return featureMapJSX;\n}\n\nconst parseNewPhones = somePhones => {\n if (somePhones === '') return [''];\n return somePhones.split('/').map(phone => phone.trim());\n}\n\nconst handleClickDispatch = e => dispatchFunction => actionBuilder => actionParameters => {\n e.preventDefault();\n return dispatchFunction(actionBuilder(actionParameters));\n}\n\nconst buildAddFeatureAction = ([newPositivePhones, newNegativePhones, feature]): featureAction => (\n {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: parseNewPhones(newPositivePhones),\n negativePhones: parseNewPhones(newNegativePhones),\n feature\n }\n }\n)\n\nconst Features = ({ phones, features, dispatch }) => {\n const [feature, setFeature] = useState('aspirated')\n const [ newPositivePhones, setNewPositivePhones ] = useState('tʰ / pʰ / kʰ');\n const [ newNegativePhones, setNewNegativePhones ] = useState('t / p / k');\n \n const newFeaturesSubmit = e => {\n e.preventDefault();\n setFeature('');\n setNewPositivePhones('');\n setNewNegativePhones('');\n }\n\n return (\n
    \n \n

    Phonetic Features

    \n \n
      \n {phones ? <>{parsePhonesFromFeatureObject(features)} : <>}\n
    \n\n
    \n setFeature(e.target.value)}\n >\n\n {/* ! Positive Phones */}\n \n \n {/* ! Negative Phones */}\n \n\n handleClickDispatch(e)(dispatch)(buildAddFeatureAction)([newPositivePhones, newNegativePhones, feature])} \n value=\"Add feature\"\n >\n
    \n\n
    \n );\n}\n\nexport default Features;","import React, { useState, useEffect } from 'react';\nimport './SoundChangeSuite.scss';\n\nconst SoundChangeSuite = props => {\n const { epochIndex, error, removeEpoch, epochs } = props;\n const [ epoch, setEpoch ] = useState(props.epoch ? props.epoch : {name:'', changes:[''], parent:'none'});\n \n const changeHandler = (e,cb) => {\n cb(e);\n props.updateEpoch(epoch, epochIndex);\n }\n \n useEffect(() => {\n props.updateEpoch(epoch, epochIndex);\n }, [epoch])\n\n const renderOptionFromEpoch = thisEpoch => (\n \n )\n\n const replaceCurrentEpoch = thisEpoch => {\n if (thisEpoch.name === epoch.name) return {name: 'none'}\n return thisEpoch;\n }\n\n const isViableParent = thisEpoch => {\n if (thisEpoch.parent && thisEpoch.parent === epoch.name) return false;\n return true;\n }\n\n const parentsOptions = () => {\n return epochs.map(replaceCurrentEpoch).filter(isViableParent).map(renderOptionFromEpoch)\n }\n\n const renderParentInput = () => {\n if (epochIndex) return (\n <>\n \n \n \n )\n return <>\n }\n\n const renderError = () => {\n if (error) return (\n

    {error}

    \n )\n return <>\n }\n\n return (\n <>\n

    {epoch.name}

    \n {renderError()}\n
    \n \n changeHandler(\n e, () => {\n setEpoch({...epoch, name:e.target.value})\n }\n )} \n >\n {renderParentInput()}\n \n \n
    \n
    removeEpoch(e, epoch.name)}>\n \n
    \n \n );\n}\n\nexport default SoundChangeSuite;","import React from 'react';\nimport './Epochs.scss';\n\nimport SoundChangeSuite from './SoundChangeSuite';\nimport { render } from 'react-dom';\n\n\n\nconst Epochs = ({epochs, errors, dispatch}) => {\n \n const addEpoch = e => {\n e.preventDefault()\n let index = epochs.length + 1;\n dispatch({\n type: 'ADD_EPOCH',\n value: {name: `Epoch ${index}`}\n })\n }\n\n const removeEpoch = (e, epochName) => {\n e.preventDefault()\n dispatch({\n type: 'REMOVE_EPOCH',\n value: {name: epochName}\n });\n }\n\n const updateEpoch = (epoch, epochIndex) => {\n const dispatchValue = {\n name: epoch.name,\n index: epochIndex,\n changes: epoch.changes,\n parent: epoch.parent\n }\n dispatch({\n type: \"SET_EPOCH\",\n value: dispatchValue\n })\n }\n \n const renderAddEpochButton = index => {\n if (index === epochs.length - 1 ) return (\n
    addEpoch(e)}>\n \n
    \n )\n return <>\n }\n\n const renderEpochs = () => {\n if (epochs.length) return epochs.map((epoch, index) => {\n const epochError = errors.epoch ? errors.error : null\n return (\n
    \n \n {renderAddEpochButton(index)}\n
    \n )});\n return renderAddEpochButton(-1)\n }\n\n return (\n <>\n { renderEpochs() }\n \n );\n}\n\nexport default Epochs;","import React, { useState } from 'react';\nimport './Options.scss';\nimport ls from 'local-storage';\n\nconst Options = ({ options, dispatch }) => {\n const [ load, setLoad ] = useState('');\n\n const handleRadioChange = e => {\n const { name, id } = e.target;\n dispatch({\n type: 'SET_OPTIONS',\n value: {\n option: name,\n setValue: id\n }\n });\n }\n \n const handleFormSubmit = (e, options) => {\n e.preventDefault();\n dispatch({\n type: 'RUN',\n value: options\n });\n }\n\n return (\n
    \n

    Modeling Options

    \n\n
    handleFormSubmit(e, options)} data-testid=\"Options-form\">\n \n {/*
    Output
    */}\n\n handleRadioChange(e)}\n />\n \n \n handleRadioChange(e)}\n />\n \n \n handleRadioChange(e)}\n />\n \n \n \n
    \n\n\n
    {}}>\n \n \n
    \n
    \n );\n}\n\nexport default Options;","import React from 'react';\nimport './Output.scss';\n\nconst Output = props => {\n const { results, options, errors } = props;\n const renderResults = () => {\n switch(options.output) {\n case 'default':\n return renderDefault();\n default:\n return <>\n }\n }\n\n const renderDefault = () => {\n return results.map((epoch, i) => {\n const lexicon = epoch.lexicon.map((lexeme, i) => {lexeme});\n return (\n
    \n
    {epoch.pass}
    \n

    {lexicon}

    \n
    \n )\n })\n }\n\n return (\n
    \n

    Results of Run

    \n
    \n {results && results.length ? renderResults() : <>}\n
    \n
    \n );\n}\n\nexport default Output;","// @flow\nimport type { stateType } from './reducer';\n\ntype lexemeType = {\n lexeme: string,\n epoch?: string\n}\n\ntype addLexemeAction = {\n type: 'ADD_LEXEME',\n value: lexemeType\n}\n\ntype setLexiconAction = {\n type: 'SET_LEXICON',\n value: Array\n}\n\nconst makeLexeme = (lexeme: string, epochName: ?string, state: stateType) => {\n const newLexeme = {lexeme: lexeme, epoch: state.epochs[0]};\n if (epochName) {\n const epochIndex = state.epochs.findIndex(epoch => epoch.name === epochName);\n if (epochIndex > 0) {\n newLexeme.epoch = state.epochs[epochIndex];\n };\n }\n return newLexeme;\n}\n\nexport type lexiconAction = addLexemeAction | setLexiconAction\n\nexport const addLexeme = (state: stateType, action: addLexemeAction): stateType => {\n const newLexeme = makeLexeme(action.value.lexeme, action.value.epoch, state);\n return {...state, lexicon:[...state.lexicon, newLexeme]}\n}\n\nexport const setLexicon = (state: stateType, action: setLexiconAction): stateType => {\n let newLexicon = action.value;\n newLexicon = newLexicon.map(lexeme => makeLexeme(lexeme.lexeme, lexeme.epoch, state));\n return {...state, lexicon: newLexicon}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type featureAction = {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: Array,\n negativePhones: Array,\n feature: string\n }\n}\n\nconst addPhones = (phones: {}, phone: string): {} => {\n let node = {};\n\n phone.split('').forEach((graph, index) => {\n if (index) node[graph] = {}\n if (!index && !phones[graph]) phones[graph] = {} \n node = index === 0 ? phones[graph] : node[graph];\n if (index === phone.length - 1) node.grapheme = phone;\n })\n\n return phones;\n}\n\nconst findPhone = (phones: {}, phone: string): {} => {\n return phone\n .split('')\n .reduce((node, graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n return node;\n }, {});\n}\n\nconst addFeatureToPhone = (\n phones: {}, phone: string, featureKey: string, featureValue: boolean\n): {} => {\n let node = {}\n phone.split('').forEach((graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n \n if (index === phone.split('').length - 1) {\n node.features = {...node.features, [featureKey]: featureValue}\n }\n });\n return phones;\n}\n\nexport const addFeature = (state: stateType, action: featureAction): stateType => {\n let positivePhones = action.value.positivePhones || [];\n let negativePhones = action.value.negativePhones || [];\n let newFeatureName = action.value.feature;\n let newPhoneObject = [\n ...positivePhones, ...negativePhones\n ]\n .reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)\n \n if (positivePhones) {\n\n positivePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)\n , newPhoneObject\n );\n\n positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )\n }\n \n if (negativePhones) {\n \n negativePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)\n , newPhoneObject\n );\n \n negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )\n }\n \n let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};\n return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}\n}","// @flow\nimport type { stateType, epochType, phoneType } from './reducer';\n\nexport type resultsAction = {\n type: 'RUN'\n}\n\nexport type decomposedRulesType = [\n {\n environment: {\n pre: [{[key: string]: boolean}],\n position: [{[key: string]: boolean}],\n post: [{[key: string]: boolean}]\n },\n newFeatures: [{[key: string]: boolean}]\n }\n]\n\ntype ruleBundle = {\n environment: {\n pre: string,\n position: string,\n post: string\n },\n newFeatures: string\n}\n\nconst getProperty = property => object => object[property]\n\nconst findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index && !lastIndex) featureBundle.push(phones[graph].features)\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst errorMessage = ([prefix, separator], location, err) => `${prefix}${location}${separator}${err}`\n\nconst lintRule = (rule) => {\n if (!rule.match(/>/g)) throw `Insert '>' operator between target and result`\n if (!rule.match(/\\//g)) throw `Insert '/' operator between change and environment`\n if (!rule.match(/_/g)) throw `Insert '_' operator in environment`\n if (rule.match(/>/g).length > 1) throw `Too many '>' operators`\n if (rule.match(/\\//g).length > 1) throw `Too many '/' operators`\n if (rule.match(/_/g).length > 1) throw `Too many '_' operators`\n return rule.split(/>|\\/|_/g);\n}\n\nconst decomposeRule = (rule: string, index: number): ruleBundle => {\n try {\n // splits rule at '>' '/' and '_' substrings resulting in array of length 4\n const [position, newFeatures, pre, post] = lintRule(rule); \n return { environment: { pre, position, post }, newFeatures }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nconst isUnknownFeatureToken = token => token !== '-' && token !== '+' && token !== ']' && token !== '[' && token !== ' ';\n\nconst doesFeatureRuleContainUnknownToken = features => {\n const unknownTokens = features\n .match(/\\W/g)\n .filter(isUnknownFeatureToken)\n if (unknownTokens.length) throw `Unknown token '${unknownTokens[0]}'`;\n return true\n}\n\nconst reduceFeaturesToBoolean = bool => (map, feature) => ({...map, [feature]: bool})\n\nconst getFeatures = (phoneme: string, featureBoolean): {} => {\n try {\n const featureMatch = featureBoolean\n // regEx to pull positive features\n ? /(?=\\+.).*(?<=\\-)|(?=\\+.).*(?!\\-).*(?<=\\])/g \n // regEx to pull negative features\n : /(?=\\-.).*(?<=\\+)|(?=\\-.).*(?!\\+).*(?<=\\])/g\n const [ features ] = phoneme.match(featureMatch) || [ null ];\n if (features) {\n doesFeatureRuleContainUnknownToken(features)\n return features\n .trim()\n .match(/\\w+/g)\n .reduce(reduceFeaturesToBoolean(featureBoolean), {})\n }\n return {}\n } catch (err) {\n throw err;\n }\n}\n\nconst mapToPositiveAndNegativeFeatures = phoneme => (\n { ...getFeatures(phoneme, true), ...getFeatures(phoneme, false) } )\n\nconst mapStringToFeatures = (ruleString, phones) => {\n if (ruleString) {\n if (ruleString === '.') return [];\n if (ruleString === '#') return ['#']\n if (ruleString === '0') return [];\n const ruleBrackets = ruleString.match(/\\[.*\\]/)\n try {\n if (ruleBrackets) {\n return ruleString\n .split('[')\n // filter out empty strings\n .filter(v => v)\n .map(mapToPositiveAndNegativeFeatures)\n }\n return findFeaturesFromGrapheme(phones, ruleString);\n } catch (err) {\n throw err;\n }\n }\n return {};\n}\n\nconst mapRuleBundleToFeatureBundle = phones => ( ruleBundle, index ) => {\n // for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs\n try {\n const { newFeatures, environment:{ pre, position, post } } = ruleBundle;\n return {\n environment: {\n pre: mapStringToFeatures(pre, phones),\n position: mapStringToFeatures(position, phones),\n post: mapStringToFeatures(post, phones),\n },\n newFeatures: mapStringToFeatures(newFeatures, phones)\n }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nexport const decomposeRules = (epoch: epochType, phones: {[key: string]: phoneType}): decomposedRulesType => {\n const { changes } = epoch\n try {\n return changes\n .map(decomposeRule)\n .map(mapRuleBundleToFeatureBundle(phones));\n } catch (err) {\n const ruleError = {epoch: epoch.name, error: err}\n throw ruleError;\n }\n}\n\nconst isPhonemeBoundByRule = phonemeFeatures => (ruleFeature, index) => {\n const phoneme = phonemeFeatures[index].features;\n return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {\n if (!bool) return false;\n if (!phoneme.hasOwnProperty(feature)) return false;\n if (!phoneme[feature] && !value) return true;\n if (phoneme[feature] !== value) return false;\n return true;\n }, true);\n} \n\nconst isEnvironmentBoundByRule = (phonemeFeatures, ruleFeatures) => {\n if (!ruleFeatures) return true;\n return ruleFeatures.filter(isPhonemeBoundByRule(phonemeFeatures)).length === ruleFeatures.length;\n}\n\nconst getEntries = object => Object.entries(object);\nconst isObjectWithPropertyInArray = (array, property) => candidate => array.map(getProperty(property)).includes(candidate[property]);\nconst transformFeatureValues = features => ([newFeature, newValue]) => features[newFeature][newValue ? 'positive': 'negative'];\nconst reduceFeatureValues = (newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })\n\nconst transformPhoneme = (phoneme, newFeatures, features) => {\n if (!newFeatures) return {}\n const newPhonemeFeatures = getEntries(newFeatures).reduce(reduceFeatureValues, {...phoneme.features});\n const newPhonemeCandidates = getEntries(newPhonemeFeatures).map(transformFeatureValues(features));\n return newPhonemeCandidates\n .reduce((candidates, candidatesSubset, index, array) => candidates.filter(isObjectWithPropertyInArray(candidatesSubset, 'grapheme'))\n , newPhonemeCandidates[newPhonemeCandidates.length - 1])[0];\n}\n\nconst transformLexemeInitial = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index !== pre.length - 1) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index + position.length, index + post.length + position.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nconst transformLexemeCoda = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index + post.length !== lexemeBundle.length) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nexport const transformLexeme = (lexemeBundle, rule, features) => {\n const {pre, post, position} = rule.environment;\n const newLexeme = lexemeBundle.reduce((newLexeme, phoneme, index) => {\n if (pre.find(val => val === '#')) return transformLexemeInitial(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if (post.find(val => val === '#')) return transformLexemeCoda(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if ( index < pre.length || index >= lexemeBundle.length - post.length ) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, rule.newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme || !newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n }, [])\n return newLexeme;\n}\n\nconst formBundleFromLexicon = lexicon => phones => lexicon.map(({lexeme}) => findFeaturesFromLexeme(phones, lexeme))\n\nconst transformLexicon = lexiconBundle => \n ruleBundle => \n features => \n lexiconBundle.map(lexemeBundle => ruleBundle.reduce(\n (lexeme, rule, i) => transformLexeme(lexeme, rule, features)\n , lexemeBundle\n ))\n\nconst getGraphemeFromEntry = ([_, phoneme]) => phoneme.grapheme\nconst stringifyLexeme = (lexeme) => lexeme.map(getProperty('grapheme')).join('')\nconst stringifyResults = ({lexicon, ...passResults}) => ({...passResults, lexicon: lexicon.map(stringifyLexeme)})\n\nexport const run = (state: stateType, action: resultsAction): stateType => {\n\n // TODO iterate through each epoch\n try {\n const passResults = state.epochs.reduce((results, epoch, _) => {\n const { phones, features, lexicon } = state;\n let lexiconBundle;\n if ( epoch.parent ) {\n lexiconBundle = results.find(result => result.pass === epoch.parent).lexicon\n }\n if (!epoch.parent) {\n lexiconBundle = formBundleFromLexicon(lexicon)(phones); \n }\n const ruleBundle = decomposeRules(epoch, phones);\n const passResults = transformLexicon(lexiconBundle)(ruleBundle)(features)\n const pass = { pass: epoch.name, lexicon: passResults }\n if ( epoch.parent ) pass.parent = epoch.parent;\n return [...results, pass];\n }, []);\n \n const results = passResults.map(stringifyResults);\n return {...state, results, errors: {} }\n } catch (err) {\n console.log(err)\n return {...state, errors: err };\n }\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type initAction = {\n type: \"INIT\"\n}\n\nexport const initState = (changesArgument: number): stateType => {\n const state = {\n epochs: [\n {\n name: 'epoch 1',\n changes: [\n '[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',\n 'a>ɯ/._#',\n '[+ sonorant - low rounded high back]>0/._.',\n '[+ obstruent]>[+ obstruent aspirated ]/#_.',\n '[+ sonorant - rounded]>[+ sonorant + rounded]/._#',\n // 'at>ta/._#'\n ]\n }\n ],\n phones: {\n a: {\n grapheme: 'a', features: {\n sonorant: true, back: true, low: true, high: false, rounded: false\n }\n },\n u: {\n grapheme: 'u', features: {\n sonorant: true, back: true, low: false, high: true, rounded: true, \n }\n },\n ɯ: {\n grapheme: 'ɯ', features: {\n sonorant: true, back: true, low: false, high: true, rounded: false,\n }\n },\n ə: {\n grapheme: 'ə', features: {\n sonorant: true, low: false, rounded: false, high: false, back: false\n }\n },\n t: {\n grapheme: 't', features: {\n occlusive: true, coronal: true, obstruent: true, nasal: false\n },\n ʰ: {\n grapheme: 'tʰ', features: {\n occlusive: true, coronal: true, obstruent: true, aspirated: true\n }\n }\n },\n n: {\n grapheme: 'n', features: {\n sonorant: true, nasal: true, occlusive: true, coronal: true\n }\n }\n },\n options: {\n output: 'default', save: false\n },\n results: [],\n errors: {},\n features: {},\n lexicon: []\n };\n state.features = {\n sonorant: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ, state.phones.ə, state.phones.n], negative: [] },\n back: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ ], negative: [ state.phones.ə ] },\n low: { positive:[ state.phones.a ], negative: [ state.phones.u, state.phones.ɯ, state.phones.ə ] },\n high: { positive:[ state.phones.u, state.phones.ɯ ], negative: [ state.phones.a, state.phones.ə ] },\n rounded: { positive:[ state.phones.u ], negative: [ state.phones.a, state.phones.ɯ, state.phones.ə ] },\n occlusive: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n coronal: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n obstruent: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n nasal: { positive:[ state.phones.n ], negative: [state.phones.t, state.phones.t.ʰ] },\n aspirated: { positive:[ state.phones.t.ʰ ], negative: [ state.phones.t ] },\n }\n state.lexicon = [\n {lexeme: 'anta', epoch: state.epochs[0]}, \n {lexeme: 'anat', epoch: state.epochs[0]},\n {lexeme: 'anət', epoch: state.epochs[0]},\n {lexeme: 'anna', epoch: state.epochs[0]}, \n {lexeme: 'tan', epoch: state.epochs[0]},\n {lexeme: 'ənta', epoch: state.epochs[0]}\n ]\n\n if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(0, changesArgument)\n\n return state;\n}","// @flow\nimport { addLexeme, setLexicon } from './reducer.lexicon';\nimport type { lexiconAction } from './reducer.lexicon';\nimport { addEpoch, setEpoch, removeEpoch } from './reducer.epochs';\nimport type { epochAction } from './reducer.epochs';\nimport { addFeature } from './reducer.features';\nimport type { featureAction } from './reducer.features';\nimport type { optionsAction } from './reducer.options';\nimport { setOptions } from './reducer.options';\nimport { run } from './reducer.results';\nimport type { resultsAction } from './reducer.results'\nimport { initState } from './reducer.init';\nimport type { initAction } from './reducer.init';\n\nexport type stateType = {\n lexicon: Array<{lexeme: string, epoch: epochType}>,\n epochs: Array,\n phones: {[key: string]: phoneType},\n options: {output: string, save: boolean},\n results: [],\n errors: {},\n features: featureType\n}\n\ntype epochType = {\n name: string, changes: Array\n}\n\ntype phoneType = {\n grapheme: string,\n features: {[key: string]: boolean}\n}\n\ntype featureType = {\n [key: string]: {[key: string]: Array}\n}\n\ntype actionType = featureAction | epochAction | initAction | resultsAction | lexiconAction\n\nexport const stateReducer = (state: stateType, action: actionType): stateType => {\n switch (action.type) {\n case 'INIT': {\n return initState();\n }\n \n case 'ADD_LEXEME': return addLexeme(state, action);\n \n case 'SET_LEXICON': return setLexicon(state, action);\n\n case 'ADD_EPOCH': return addEpoch(state, action);\n\n case 'SET_EPOCH': return setEpoch(state, action);\n\n case 'REMOVE_EPOCH': return removeEpoch(state, action);\n\n case 'ADD_FEATURE': return addFeature(state, action);\n\n case 'SET_OPTIONS': return setOptions(state, action);\n\n case 'RUN': return run(state, action);\n\n default: return state;\n }\n}\n","// @flow\nimport type { stateType } from './reducer';\n\nexport type epochAction = {\n type: \"ADD_EPOCH\" | \"SET_EPOCH\" | \"REMOVE_EPOCH\",\n value: {\n index?: number,\n name: string,\n changes?: Array,\n parent?: string\n }\n}\n\nexport const addEpoch = (state: stateType, action: epochAction): stateType => {\n const newEpoch = { name: action.value.name, changes: action.value.changes || [''], parent: null};\n return {...state, epochs: [...state.epochs, newEpoch]}\n}\n\nexport const setEpoch = (state: stateType, action: epochAction): stateType => {\n const index = action.value.index;\n if (typeof index !== 'number') return state;\n \n const mutatedEpochs = state.epochs;\n mutatedEpochs[index].name = action.value.name \n ? action.value.name \n : mutatedEpochs[index].name;\n\n mutatedEpochs[index].changes = action.value.changes \n ? action.value.changes \n : mutatedEpochs[index].changes;\n\n mutatedEpochs[index].parent = action.value.parent && action.value.parent !== 'none'\n ? action.value.parent\n : null\n return {...state, epochs: [...mutatedEpochs]}\n}\n\nexport const removeEpoch = (state: stateType, action: epochAction): stateType => {\n const mutatedEpochs = state.epochs.filter(epoch => epoch.name !== action.value.name )\n return {...state, epochs: [...mutatedEpochs]}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type optionAction = {\n type: 'SET_OPTIONS',\n value: {\n option: string,\n setValue: string\n }\n};\n\nexport const setOptions = (state: stateType, action: optionAction): stateType => {\n const option = action.value.option;\n let value = action.value.setValue;\n if (value === 'true') value = true;\n if (value === 'false') value = false;\n const mutatedState = {...state};\n mutatedState.options[option] = value;\n return mutatedState;\n}","import React, { useState, useReducer } from 'react';\nimport './PhonoChangeApplier.scss';\n\nimport ProtoLang from './components/ProtoLang';\nimport Features from './components/Features';\nimport Epochs from './components/Epochs';\nimport Options from './components/Options';\nimport Output from './components/Output';\n\nimport { stateReducer } from './reducers/reducer';\nimport { initState } from './reducers/reducer.init';\n\nconst PhonoChangeApplier = () => {\n const [ state, dispatch ] = useReducer(\n stateReducer,\n {},\n initState\n )\n const { lexicon, phones, phonemes, epochs, options, features, results, errors } = state;\n\n return (\n
    \n \n \n \n \n \n
    \n );\n}\n\nexport default PhonoChangeApplier;","import React from 'react';\nimport './App.css';\nimport PhonoChangeApplier from './PhonoChangeApplier';\n\nfunction App() {\n return (\n
    \n

    Phono Change Applier

    \n \n
    \n );\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.scss';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/static/js/main.e83b5fcd.chunk.js b/static/js/main.e83b5fcd.chunk.js deleted file mode 100644 index 14e9dd6..0000000 --- a/static/js/main.e83b5fcd.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this["webpackJsonpfeature-change-applier"]=this["webpackJsonpfeature-change-applier"]||[]).push([[0],[,,,,,,,,,,,,function(e,t,n){e.exports=n(28)},,,,,function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},,,function(e,t,n){},function(e,t,n){"use strict";n.r(t);var a=n(0),r=n.n(a),o=n(5),c=n.n(o),u=(n(17),n(18),n(3)),i=(n(19),n(20),function(e){var t=e.lexicon,n=e.dispatch;return r.a.createElement("div",{className:"ProtoLang","data-testid":"ProtoLang"},r.a.createElement("h3",null,"Proto Language Lexicon"),r.a.createElement("br",null),r.a.createElement("form",{"data-testid":"ProtoLang-Lexicon"},r.a.createElement("textarea",{name:"lexicon",cols:"30",rows:"10","data-testid":"ProtoLang-Lexicon__textarea",value:function(){return t?t.map((e="lexeme",function(t){return t[e]})).join("\n"):"";var e}(),onChange:function(e){console.log(e.target.value.split(/\n/).map((function(e){return{lexeme:e.split("#")[0].trim(),epoch:e.split("#")[1]||""}}))),n({type:"SET_LEXICON",value:e.target.value.split(/\n/).map((function(e){return{lexeme:e.split("#")[0].trim(),epoch:e.split("#")[1]||""}}))})}})))}),s=n(4),l=(n(21),function(e){return""===e?[""]:e.split("/").map((function(e){return e.trim()}))}),p=function(e){var t=Object(u.a)(e,3),n=t[0],a=t[1],r=t[2];return{type:"ADD_FEATURE",value:{positivePhones:l(n),negativePhones:l(a),feature:r}}},m=function(e){var t=e.phones,n=e.features,o=e.dispatch,c=Object(a.useState)("aspirated"),i=Object(u.a)(c,2),l=i[0],m=i[1],h=Object(a.useState)("t\u02b0 / p\u02b0 / k\u02b0"),f=Object(u.a)(h,2),v=f[0],g=f[1],d=Object(a.useState)("t / p / k"),E=Object(u.a)(d,2),b=E[0],O=E[1];return r.a.createElement("div",{className:"Features","data-testid":"Features"},r.a.createElement("h3",null,"Phonetic Features"),r.a.createElement("ul",{className:"Features__list","data-testid":"Features-list"},t?r.a.createElement(r.a.Fragment,null,function(e){var t=function(e){return function(t){return t[e]}};return function(e){return e.map((function(e,t){var n=Object.keys(e),a=e[n],o=a.plus,c=a.minus;return r.a.createElement("li",{key:"feature__".concat(n)},r.a.createElement("span",{className:"feature--names-and-phones"},r.a.createElement("span",{className:"feature--feature-name"},"[+ ".concat(n,"]")),r.a.createElement("span",{className:"feature--feature-phones"},o)),r.a.createElement("span",{className:"feature--names-and-phones"},r.a.createElement("span",{className:"feature--feature-name"},"[- ".concat(n,"]")),r.a.createElement("span",{className:"feature--feature-phones"},c)))}))}(function(e){return Object.keys(e).map((function(n){var a=e[n].positive.map(t("grapheme")).join(" / "),r=e[n].negative.map(t("grapheme")).join(" / ");return Object(s.a)({},n,{plus:a,minus:r})}))}(e))}(n)):r.a.createElement(r.a.Fragment,null)),r.a.createElement("form",{className:"Features__form","data-testid":"Features-form"},r.a.createElement("input",{type:"text",name:"feature",value:l,onChange:function(e){return m(e.target.value)}}),r.a.createElement("label",{htmlFor:"positive-phones"},"+",r.a.createElement("input",{id:"positive-phones",type:"text",name:"phonemes",value:v,onChange:function(e){return g(e.target.value)}})),r.a.createElement("label",{htmlFor:"negative-phones"},"-",r.a.createElement("input",{id:"negative-phones",type:"text",name:"phonemes",value:b,onChange:function(e){return O(e.target.value)}})),r.a.createElement("input",{type:"submit",onClick:function(e){return function(e){return function(t){return function(n){return function(a){return e.preventDefault(),t(n(a))}}}}(e)(o)(p)([v,b,l])},value:"Add feature"})))},h=(n(22),n(2)),f=(n(23),function(e){var t=e.epochIndex,n=e.removeEpoch,o=e.epochs,c=Object(a.useState)(e.epoch?e.epoch:{name:"",changes:[""],parent:"none"}),i=Object(u.a)(c,2),s=i[0],l=i[1],p=function(n,a){a(n),e.updateEpoch(s,t)};Object(a.useEffect)((function(){e.updateEpoch(s,t)}),[s]);var m=function(e){return r.a.createElement("option",{key:"".concat(s.name,"__parent-option--").concat(e.name),value:e.name},e.name)},f=function(e){return e.name===s.name?{name:"none"}:e},v=function(e){return!e.parent||e.parent!==s.name};return r.a.createElement(r.a.Fragment,null,r.a.createElement("h4",null,s.name),r.a.createElement("form",{className:"SoundChangeSuite__form","data-testid":"".concat(s.name,"_SoundChangeSuite_changes")},r.a.createElement("label",{htmlFor:"".concat(s.name,"-name")},"Name:"),r.a.createElement("input",{type:"text",name:"epoch",id:"".concat(s.name,"-name"),cols:"30",rows:"1",value:s.name,onChange:function(e){return p(e,(function(){l(Object(h.a)({},s,{name:e.target.value}))}))}}),t?r.a.createElement(r.a.Fragment,null,r.a.createElement("label",{htmlFor:"".concat(s.name,"-parent")},"Parent Epoch:"),r.a.createElement("select",{name:"parent",list:"".concat(s.name,"-parents-list"),value:s.parent,onChange:function(e){return p(e,(function(){l(Object(h.a)({},s,{parent:e.target.value}))}))}},o.map(f).filter(v).map(m))):r.a.createElement(r.a.Fragment,null),r.a.createElement("textarea",{name:"changes",id:"",cols:"30",rows:"10",value:s.changes.join("\n"),onChange:function(e){return p(e,(function(){return l(Object(h.a)({},s,{changes:e.target.value.split(/\n/).map((function(e){return" "===e?"[+ feature]>[- feature]/_#":e}))}))}))}})),r.a.createElement("form",{onSubmit:function(e){return n(e,s.name)}},r.a.createElement("input",{type:"submit",name:"remove-epoch",value:"remove ".concat(s.name)})))}),v=function(e){var t=e.epochs,n=e.dispatch,a=function(e,t){e.preventDefault(),n({type:"REMOVE_EPOCH",value:{name:t}})},o=function(e,t){var a={name:e.name,index:t,changes:e.changes,parent:e.parent};n({type:"SET_EPOCH",value:a})},c=function(e){return e===t.length-1?r.a.createElement("form",{onSubmit:function(e){return function(e){e.preventDefault();var a=t.length+1;n({type:"ADD_EPOCH",value:{name:"Epoch ".concat(a)}})}(e)}},r.a.createElement("input",{type:"submit",name:"add-epoch",value:"Add Epoch"})):r.a.createElement(r.a.Fragment,null)};return r.a.createElement(r.a.Fragment,null,t.length?t.map((function(e,n){return r.a.createElement("div",{className:"SoundChangeSuite","data-testid":"".concat(e.name,"_SoundChangeSuite"),key:"epoch-".concat(n)},r.a.createElement(f,{epochIndex:n,epoch:e,updateEpoch:o,removeEpoch:a,epochs:t}),c(n))})):c(-1))},g=(n(24),n(10)),d=n.n(g),E=function(e){var t=e.options,n=e.dispatch,o=Object(a.useState)(""),c=Object(u.a)(o,2),i=c[0],s=c[1],l=function(e){var t=e.target,a=t.name,r=t.id;n({type:"SET_OPTIONS",value:{option:a,setValue:r}})};return r.a.createElement("div",{className:"Options","data-testid":"Options"},r.a.createElement("h3",null,"Modeling Options"),r.a.createElement("form",{onSubmit:function(e){return function(e,t){e.preventDefault(),n({type:"RUN",value:t})}(e,t)},"data-testid":"Options-form"},r.a.createElement("input",{type:"radio",name:"output",id:"default",checked:!t||"default"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"default"},"Default",r.a.createElement("span",{className:"Options__output-example"}," output")),r.a.createElement("input",{type:"radio",name:"output",id:"proto",checked:!!t&&"proto"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"proto"},"Proto",r.a.createElement("span",{className:"Options__output-example"}," output [proto]")),r.a.createElement("input",{type:"radio",name:"output",id:"diachronic",checked:!!t&&"diachronic"===t.output,onChange:function(e){return l(e)}}),r.a.createElement("label",{htmlFor:"diachronic"},"Diachronic",r.a.createElement("span",{className:"Options__output-example"}," *proto > *epoch > output")),r.a.createElement("input",{type:"submit",value:"Run Changes"})),r.a.createElement("form",{onSubmit:function(){}},r.a.createElement("label",null,"Load from a prior run:",r.a.createElement("select",{value:i,onChange:function(e){return s(e.target.value)}},localStorage.phonoChange?d.a.get("phonoChange").map((function(e){return r.a.createElement("option",{key:e.name,value:e.name},e.name)})):r.a.createElement(r.a.Fragment,null))),r.a.createElement("input",{type:"submit",value:"Submit"})))},b=(n(27),function(e){var t=e.results,n=e.options,a=function(){return t.map((function(e,t){var n=e.lexicon.map((function(t,n){return r.a.createElement("span",{key:"".concat(e.pass,"-").concat(n)},t)}));return r.a.createElement("div",{key:"epoch-".concat(t),className:"Output-epoch"},r.a.createElement("h5",null,e.pass),r.a.createElement("p",{className:"lexicon"},n))}))};return r.a.createElement("div",{className:"Output","data-testid":"Output"},r.a.createElement("h3",null,"Results of Run"),r.a.createElement("div",{"data-testid":"Output-lexicon",className:"Output__container"},t&&t.length?function(){switch(n.output){case"default":return a();default:return r.a.createElement(r.a.Fragment,null)}}():r.a.createElement(r.a.Fragment,null)))}),O=n(1),j=function(e,t,n){var a={lexeme:e,epoch:n.epochs[0]};if(t){var r=n.epochs.findIndex((function(e){return e.name===t}));r>0&&(a.epoch=n.epochs[r])}return a},x=function(e,t){return t.split("").reduce((function(t,n,a){return t=0===a?e[n]:t[n]}),{})},_=function(e,t,n,a){var r={};return t.split("").forEach((function(o,c){r=0===c?e[o]:r[o],c===t.split("").length-1&&(r.features=Object(h.a)({},r.features,Object(s.a)({},n,a)))})),e},w=n(11),y=n(6);function F(){var e=Object(y.a)(["Error in line ",": ",""]);return F=function(){return e},e}function C(){var e=Object(y.a)(["Error in line ",": ",""]);return C=function(){return e},e}var N=function(e){return function(t){return t[e]}},S=function(e,t,n){var a=Object(u.a)(e,2),r=a[0],o=a[1];return"".concat(r).concat(t).concat(o).concat(n)},k=function(e,t){try{var n=function(e){if(!e.match(/>/g))throw"Insert '>' operator between target and result";if(!e.match(/\//g))throw"Insert '/' operator between change and environment";if(!e.match(/_/g))throw"Insert '_' operator in environment";if(e.match(/>/g).length>1)throw"Too many '>' operators";if(e.match(/\//g).length>1)throw"Too many '/' operators";if(e.match(/_/g).length>1)throw"Too many '_' operators";return e.split(/>|\/|_/g)}(e),a=Object(u.a)(n,4),r=a[0],o=a[1];return{environment:{pre:a[2],position:r,post:a[3]},newFeatures:o}}catch(c){throw S(C(),t+1,c)}},P=function(e){return"-"!==e&&"+"!==e&&"]"!==e&&"["!==e&&" "!==e},D=function(e,t){try{var n=t?/(?=\+.).*(?<=\-)|(?=\+.).*(?!\-).*(?<=\])/g:/(?=\-.).*(?<=\+)|(?=\-.).*(?!\+).*(?<=\])/g,a=e.match(n)||[null],r=Object(u.a)(a,1)[0];return r?(function(e){var t=e.match(/\W/g).filter(P);if(t.length)throw"Unknown token '".concat(t[0],"'")}(r),r.trim().match(/\w+/g).reduce((o=t,function(e,t){return Object(h.a)({},e,Object(s.a)({},t,o))}),{})):{}}catch(c){throw c}var o},A=function(e){return Object(h.a)({},D(e,!0),{},D(e,!1))},T=function(e,t){if(e){if("."===e)return[];if("#"===e)return["#"];if("0"===e)return[];var n=e.match(/\[.*\]/);try{return n?e.split("[").filter((function(e){return e})).map(A):function(e,t){var n=[],a=t.length-1,r={};return Object(O.a)(t).forEach((function(t,o){return o||a||n.push(e[t].features),o?o===a?r[t]?n.push(r[t]):n.push(r,e[t]):!r[t]&&r.features?(n.push(r),r=e[t]):r[t]?void 0:r=r[t]:r=e[t]})),n}(t,e)}catch(a){throw a}}return{}},I=function(e,t){var n=e.changes;try{return n.map(k).map(function(e){return function(t,n){try{var a=t.newFeatures,r=t.environment,o=r.pre,c=r.position,u=r.post;return{environment:{pre:T(o,e),position:T(c,e),post:T(u,e)},newFeatures:T(a,e)}}catch(i){throw S(F(),n+1,i)}}}(t))}catch(a){return a}},L=function(e,t){return!t||t.filter(function(e){return function(t,n){var a=e[n].features;return Object.entries(t).reduce((function(e,t){var n=Object(u.a)(t,2),r=n[0],o=n[1];return!!e&&(!!a.hasOwnProperty(r)&&(!a[r]&&!o||a[r]===o))}),!0)}}(e)).length===t.length},R=function(e){return Object.entries(e)},H=function(e,t){var n=Object(u.a)(t,2),a=n[0],r=n[1];return Object(h.a)({},e,Object(s.a)({},a,r))},U=function(e,t,n){if(!t)return{};var a=R(t).reduce(H,Object(h.a)({},e.features)),r=R(a).map(function(e){return function(t){var n=Object(u.a)(t,2),a=n[0],r=n[1];return e[a][r?"positive":"negative"]}}(n));return r.reduce((function(e,t,n,a){return e.filter(function(e,t){return function(n){return e.map(N(t)).includes(n[t])}}(t,"grapheme"))}),r[r.length-1])[0]},M=function(e,t,n){var a=t.environment,r=a.pre,o=a.post,c=a.position;return e.reduce((function(a,u,i){if(r.find((function(e){return"#"===e})))return function(e,t,n,a,r,o,c,u,i){if(o!==t.length-1)return[].concat(Object(O.a)(e),[r]);if(!L([r],a))return[].concat(Object(O.a)(e),[r]);if(!L(c.slice(o+a.length,o+n.length+a.length),n))return[].concat(Object(O.a)(e),[r]);var s=U(r,u[0],i);return s.grapheme?[].concat(Object(O.a)(e),[s]):Object(O.a)(e)}(a,r,o,c,u,i,e,t.newFeatures,n);if(o.find((function(e){return"#"===e})))return function(e,t,n,a,r,o,c,u,i){if(o+n.length!==c.length)return[].concat(Object(O.a)(e),[r]);if(!L(c.slice(o-t.length,o),t))return[].concat(Object(O.a)(e),[r]);if(!L([r],a))return[].concat(Object(O.a)(e),[r]);var s=U(r,u[0],i);return s.grapheme?[].concat(Object(O.a)(e),[s]):Object(O.a)(e)}(a,r,o,c,u,i,e,t.newFeatures,n);if(i=e.length-o.length)return[].concat(Object(O.a)(a),[u]);if(!L(e.slice(i-r.length,i),r))return[].concat(Object(O.a)(a),[u]);if(!L([u],c))return[].concat(Object(O.a)(a),[u]);if(!L(e.slice(i,i+o.length),o))return[].concat(Object(O.a)(a),[u]);var s=U(u,t.newFeatures[0],n);return s&&s.grapheme?[].concat(Object(O.a)(a),[s]):Object(O.a)(a)}),[])},V=function(e){return function(t){return e.map((function(e){var n=e.lexeme;return function(e,t){var n=[],a=t.length-1,r={};return Object(O.a)(t).forEach((function(t,o){return o?o===a?r[t]?n.push(r[t]):n.push(r,e[t]):!r[t]&&r.features?(n.push(r),r=e[t]):r[t]?void 0:r=r[t]:r=e[t]})),n}(t,n)}))}},W=function(e){return e.map(N("grapheme")).join("")},X=function(e){var t=e.lexicon,n=Object(w.a)(e,["lexicon"]);return Object(h.a)({},n,{lexicon:t.map(W)})},B=function(e,t){try{var n=e.epochs.reduce((function(t,n,a){var r,o=e.phones,c=e.features,u=e.lexicon;n.parent&&(r=t.find((function(e){return e.pass===n.parent})).lexicon),n.parent||(r=V(u)(o));var i=I(n,o),s=function(e){return function(t){return function(n){return e.map((function(e){return t.reduce((function(e,t,a){return M(e,t,n)}),e)}))}}}(r)(i)(c),l={pass:n.name,lexicon:s};return n.parent&&(l.parent=n.parent),[].concat(Object(O.a)(t),[l])}),[]).map(X);return Object(h.a)({},e,{results:n})}catch(a){return console.log(a),Object(h.a)({},e,{errors:a})}},J=function(e){var t={epochs:[{name:"epoch 1",changes:["[+ occlusive - nasal]>[+ occlusive + nasal]/n_.","a>\u026f/._#","[+ sonorant - low rounded high back]>0/._.","[+ obstruent]>[+ obstruent aspirated ]/#_.","[+ sonorant - rounded]>[+ sonorant + rounded]/._#"]}],phones:{a:{grapheme:"a",features:{sonorant:!0,back:!0,low:!0,high:!1,rounded:!1}},u:{grapheme:"u",features:{sonorant:!0,back:!0,low:!1,high:!0,rounded:!0}},"\u026f":{grapheme:"\u026f",features:{sonorant:!0,back:!0,low:!1,high:!0,rounded:!1}},"\u0259":{grapheme:"\u0259",features:{sonorant:!0,low:!1,rounded:!1,high:!1,back:!1}},t:{grapheme:"t",features:{occlusive:!0,coronal:!0,obstruent:!0,nasal:!1},"\u02b0":{grapheme:"t\u02b0",features:{occlusive:!0,coronal:!0,obstruent:!0,aspirated:!0}}},n:{grapheme:"n",features:{sonorant:!0,nasal:!0,occlusive:!0,coronal:!0}}},options:{output:"default",save:!1},results:[],errors:{},features:{},lexicon:[]};return t.features={sonorant:{positive:[t.phones.a,t.phones.u,t.phones.\u026f,t.phones.\u0259,t.phones.n],negative:[]},back:{positive:[t.phones.a,t.phones.u,t.phones.\u026f],negative:[t.phones.\u0259]},low:{positive:[t.phones.a],negative:[t.phones.u,t.phones.\u026f,t.phones.\u0259]},high:{positive:[t.phones.u,t.phones.\u026f],negative:[t.phones.a,t.phones.\u0259]},rounded:{positive:[t.phones.u],negative:[t.phones.a,t.phones.\u026f,t.phones.\u0259]},occlusive:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},coronal:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},obstruent:{positive:[t.phones.t,t.phones.n,t.phones.t.\u02b0],negative:[]},nasal:{positive:[t.phones.n],negative:[t.phones.t,t.phones.t.\u02b0]},aspirated:{positive:[t.phones.t.\u02b0],negative:[t.phones.t]}},t.lexicon=[{lexeme:"anta",epoch:t.epochs[0]},{lexeme:"anat",epoch:t.epochs[0]},{lexeme:"an\u0259t",epoch:t.epochs[0]},{lexeme:"anna",epoch:t.epochs[0]},{lexeme:"tan",epoch:t.epochs[0]},{lexeme:"\u0259nta",epoch:t.epochs[0]}],e>-1&&(t.epochs[0].changes=t.epochs[0].changes.splice(0,e)),t},$=function(e,t){switch(t.type){case"INIT":return J();case"ADD_LEXEME":return function(e,t){var n=j(t.value.lexeme,t.value.epoch,e);return Object(h.a)({},e,{lexicon:[].concat(Object(O.a)(e.lexicon),[n])})}(e,t);case"SET_LEXICON":return function(e,t){var n=t.value;return n=n.map((function(t){return j(t.lexeme,t.epoch,e)})),Object(h.a)({},e,{lexicon:n})}(e,t);case"ADD_EPOCH":return function(e,t){var n={name:t.value.name,changes:t.value.changes||[""]};return Object(h.a)({},e,{epochs:[].concat(Object(O.a)(e.epochs),[n])})}(e,t);case"SET_EPOCH":return function(e,t){var n=t.value.index;if("number"!==typeof n)return e;var a=e.epochs;return a[n].name=t.value.name?t.value.name:a[n].name,a[n].changes=t.value.changes?t.value.changes:a[n].changes,a[n].parent=t.value.parent&&"none"!==t.value.parent?t.value.parent:null,Object(h.a)({},e,{epochs:Object(O.a)(a)})}(e,t);case"REMOVE_EPOCH":return function(e,t){var n=e.epochs.filter((function(e){return e.name!==t.value.name}));return Object(h.a)({},e,{epochs:Object(O.a)(n)})}(e,t);case"ADD_FEATURE":return function(e,t){var n=t.value.positivePhones||[],a=t.value.negativePhones||[],r=t.value.feature,o=[].concat(Object(O.a)(n),Object(O.a)(a)).reduce((function(e,t){return function(e,t){var n={};return t.split("").forEach((function(a,r){r&&(n[a]={}),r||e[a]||(e[a]={}),n=0===r?e[a]:n[a],r===t.length-1&&(n.grapheme=t)})),e}(e,t)}),e.phones);n&&(n.reduce((function(e,t){return _(e,t,r,!0)}),o),n=n.map((function(e){return x(o,e)}))),a&&(a.reduce((function(e,t){return _(e,t,r,!1)}),o),a=a.map((function(e){return x(o,e)})));var c=Object(s.a)({},t.value.feature,{positive:n,negative:a});return Object(h.a)({},e,{features:Object(h.a)({},e.features,{},c),phones:o})}(e,t);case"SET_OPTIONS":return function(e,t){var n=t.value.option,a=t.value.setValue;"true"===a&&(a=!0),"false"===a&&(a=!1);var r=Object(h.a)({},e);return r.options[n]=a,r}(e,t);case"RUN":return B(e);default:return e}},q=function(){var e=Object(a.useReducer)($,{},J),t=Object(u.a)(e,2),n=t[0],o=t[1],c=n.lexicon,s=n.phones,l=(n.phonemes,n.epochs),p=n.options,h=n.features,f=n.results;return r.a.createElement("div",{className:"PhonoChangeApplier","data-testid":"PhonoChangeApplier"},r.a.createElement(i,{lexicon:c,dispatch:o}),r.a.createElement(m,{phones:s,features:h,dispatch:o}),r.a.createElement(v,{epochs:l,dispatch:o}),r.a.createElement(E,{options:p,dispatch:o}),r.a.createElement(b,{results:f,options:p,dispatch:o}))};var z=function(){return r.a.createElement("div",{className:"App","data-testid":"App"},r.a.createElement("h1",null,"Phono Change Applier"),r.a.createElement(q,null))};Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));c.a.render(r.a.createElement(z,null),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then((function(e){e.unregister()}))}],[[12,1,2]]]); -//# sourceMappingURL=main.e83b5fcd.chunk.js.map \ No newline at end of file diff --git a/static/js/main.e83b5fcd.chunk.js.map b/static/js/main.e83b5fcd.chunk.js.map deleted file mode 100644 index f125415..0000000 --- a/static/js/main.e83b5fcd.chunk.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["components/ProtoLang.js","components/Features.js","components/SoundChangeSuite.js","components/Epochs.js","components/Options.js","components/Output.js","reducers/reducer.lexicon.js","reducers/reducer.features.js","reducers/reducer.results.js","reducers/reducer.init.js","reducers/reducer.js","reducers/reducer.epochs.js","reducers/reducer.options.js","PhonoChangeApplier.js","App.js","serviceWorker.js","index.js"],"names":["ProtoLang","lexicon","dispatch","className","data-testid","name","cols","rows","value","map","property","object","join","renderLexicon","onChange","e","console","log","target","split","line","lexeme","trim","epoch","type","parseNewPhones","somePhones","phone","buildAddFeatureAction","newPositivePhones","newNegativePhones","feature","positivePhones","negativePhones","Features","phones","features","useState","setFeature","setNewPositivePhones","setNewNegativePhones","featureObject","getProperty","featureMap","index","featureName","Object","keys","plus","minus","key","getFeatureMapJSX","plusPhones","positive","minusPhones","negative","getFeatureMap","parsePhonesFromFeatureObject","htmlFor","id","onClick","dispatchFunction","actionBuilder","actionParameters","preventDefault","handleClickDispatch","SoundChangeSuite","props","epochIndex","removeEpoch","epochs","changes","parent","setEpoch","changeHandler","cb","updateEpoch","useEffect","renderOptionFromEpoch","thisEpoch","replaceCurrentEpoch","isViableParent","list","filter","change","onSubmit","Epochs","epochName","dispatchValue","renderAddEpochButton","length","addEpoch","Options","options","load","setLoad","handleRadioChange","option","setValue","handleFormSubmit","checked","output","localStorage","phonoChange","ls","get","priorRun","Output","results","renderDefault","i","pass","renderResults","makeLexeme","state","newLexeme","findIndex","findPhone","reduce","node","graph","addFeatureToPhone","featureKey","featureValue","forEach","errorMessage","location","err","prefix","separator","decomposeRule","rule","match","lintRule","position","newFeatures","environment","pre","post","isUnknownFeatureToken","token","getFeatures","phoneme","featureBoolean","featureMatch","unknownTokens","doesFeatureRuleContainUnknownToken","bool","mapToPositiveAndNegativeFeatures","mapStringToFeatures","ruleString","ruleBrackets","v","featureBundle","lastIndex","push","findFeaturesFromGrapheme","decomposeRules","ruleBundle","mapRuleBundleToFeatureBundle","isEnvironmentBoundByRule","phonemeFeatures","ruleFeatures","ruleFeature","entries","hasOwnProperty","isPhonemeBoundByRule","getEntries","reduceFeatureValues","newPhoneme","newFeature","newValue","transformPhoneme","newPhonemeFeatures","newPhonemeCandidates","transformFeatureValues","candidates","candidatesSubset","array","candidate","includes","isObjectWithPropertyInArray","transformLexeme","lexemeBundle","find","val","slice","grapheme","transformLexemeInitial","transformLexemeCoda","formBundleFromLexicon","findFeaturesFromLexeme","stringifyLexeme","stringifyResults","passResults","run","action","_","lexiconBundle","result","transformLexicon","errors","initState","changesArgument","a","sonorant","back","low","high","rounded","u","ɯ","ə","t","occlusive","coronal","obstruent","nasal","ʰ","aspirated","n","save","splice","stateReducer","addLexeme","newLexicon","setLexicon","newEpoch","mutatedEpochs","newFeatureName","newPhoneObject","phoneObject","addPhones","positivePhone","negativePhone","addFeature","mutatedState","setOptions","PhonoChangeApplier","useReducer","phonemes","App","Boolean","window","hostname","ReactDOM","render","document","getElementById","navigator","serviceWorker","ready","then","registration","unregister"],"mappings":"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","file":"static/js/main.e83b5fcd.chunk.js","sourcesContent":["import React from 'react';\nimport './ProtoLang.scss';\n\nconst ProtoLang = ({ lexicon, dispatch }) => {\n const getProperty = property => object => object[property];\n const renderLexicon = () => {\n if (!lexicon) return '';\n // Code for optionally rendering epoch name with lexeme\n // `\\t#${lexeme.epoch.name}`\n return lexicon.map(getProperty('lexeme')).join('\\n');\n }\n\n return (\n
    \n

    Proto Language Lexicon

    \n
    \n
    \n {\n console.log(e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n }))\n dispatch({\n type: 'SET_LEXICON', \n value: e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n })\n })\n }\n }>\n \n \n
    \n );\n}\n\nexport default ProtoLang;","// @flow\nimport React, {useState} from 'react';\nimport './Features.scss';\n\nimport type { featureAction } from '../reducers/reducer.features';\n\nconst parsePhonesFromFeatureObject = featureObject => {\n const getProperty = property => object => object[property]\n \n const getFeatureMap = (featureObject) => {\n return Object.keys(featureObject).map(feature => {\n const plusPhones = featureObject[feature].positive.map(getProperty('grapheme')).join(' / ');\n const minusPhones = featureObject[feature].negative.map(getProperty('grapheme')).join(' / ');\n return {[feature]: {plus: plusPhones, minus: minusPhones}}\n })\n }\n\n const getFeatureMapJSX = (featureMap) => {\n return featureMap.map((feature, index) => {\n const featureName = Object.keys(feature);\n const { plus, minus } = feature[featureName];\n return (\n
  • \n \n \n {`[+ ${featureName}]`}\n \n \n {plus}\n \n \n \n \n {`[- ${featureName}]`}\n \n \n {minus}\n \n \n
  • \n )\n })\n }\n\n const featureMap = getFeatureMap(featureObject);\n const featureMapJSX = getFeatureMapJSX(featureMap);\n return featureMapJSX;\n}\n\nconst parseNewPhones = somePhones => {\n if (somePhones === '') return [''];\n return somePhones.split('/').map(phone => phone.trim());\n}\n\nconst handleClickDispatch = e => dispatchFunction => actionBuilder => actionParameters => {\n e.preventDefault();\n return dispatchFunction(actionBuilder(actionParameters));\n}\n\nconst buildAddFeatureAction = ([newPositivePhones, newNegativePhones, feature]): featureAction => (\n {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: parseNewPhones(newPositivePhones),\n negativePhones: parseNewPhones(newNegativePhones),\n feature\n }\n }\n)\n\nconst Features = ({ phones, features, dispatch }) => {\n const [feature, setFeature] = useState('aspirated')\n const [ newPositivePhones, setNewPositivePhones ] = useState('tʰ / pʰ / kʰ');\n const [ newNegativePhones, setNewNegativePhones ] = useState('t / p / k');\n \n const newFeaturesSubmit = e => {\n e.preventDefault();\n setFeature('');\n setNewPositivePhones('');\n setNewNegativePhones('');\n }\n\n return (\n
    \n \n

    Phonetic Features

    \n \n
      \n {phones ? <>{parsePhonesFromFeatureObject(features)} : <>}\n
    \n\n
    \n setFeature(e.target.value)}\n >\n\n {/* ! Positive Phones */}\n \n \n {/* ! Negative Phones */}\n \n\n handleClickDispatch(e)(dispatch)(buildAddFeatureAction)([newPositivePhones, newNegativePhones, feature])} \n value=\"Add feature\"\n >\n
    \n\n
    \n );\n}\n\nexport default Features;","import React, { useState, useEffect } from 'react';\nimport './SoundChangeSuite.scss';\n\nconst SoundChangeSuite = props => {\n const { epochIndex, removeEpoch, epochs } = props;\n const [ epoch, setEpoch ] = useState(props.epoch ? props.epoch : {name:'', changes:[''], parent:'none'});\n \n const changeHandler = (e,cb) => {\n cb(e);\n props.updateEpoch(epoch, epochIndex);\n }\n \n useEffect(() => {\n props.updateEpoch(epoch, epochIndex);\n }, [epoch])\n\n const renderOptionFromEpoch = thisEpoch => (\n \n )\n\n const replaceCurrentEpoch = thisEpoch => {\n if (thisEpoch.name === epoch.name) return {name: 'none'}\n return thisEpoch;\n }\n\n const isViableParent = thisEpoch => {\n if (thisEpoch.parent && thisEpoch.parent === epoch.name) return false;\n return true;\n }\n\n const parentsOptions = () => {\n return epochs.map(replaceCurrentEpoch).filter(isViableParent).map(renderOptionFromEpoch)\n }\n\n const renderParentInput = () => {\n if (epochIndex) return (\n <>\n \n \n \n )\n return <>\n }\n\n return (\n <>\n

    {epoch.name}

    \n
    \n \n changeHandler(\n e, () => {\n setEpoch({...epoch, name:e.target.value})\n }\n )} \n >\n {renderParentInput()}\n \n \n
    \n
    removeEpoch(e, epoch.name)}>\n \n
    \n \n );\n}\n\nexport default SoundChangeSuite;","import React from 'react';\nimport './Epochs.scss';\n\nimport SoundChangeSuite from './SoundChangeSuite';\nimport { render } from 'react-dom';\n\n\n\nconst Epochs = ({epochs, dispatch}) => {\n \n const addEpoch = e => {\n e.preventDefault()\n let index = epochs.length + 1;\n dispatch({\n type: 'ADD_EPOCH',\n value: {name: `Epoch ${index}`}\n })\n }\n\n const removeEpoch = (e, epochName) => {\n e.preventDefault()\n dispatch({\n type: 'REMOVE_EPOCH',\n value: {name: epochName}\n });\n }\n\n const updateEpoch = (epoch, epochIndex) => {\n const dispatchValue = {\n name: epoch.name,\n index: epochIndex,\n changes: epoch.changes,\n parent: epoch.parent\n }\n dispatch({\n type: \"SET_EPOCH\",\n value: dispatchValue\n })\n }\n \n const renderAddEpochButton = index => {\n if (index === epochs.length - 1 ) return (\n
    addEpoch(e)}>\n \n
    \n )\n return <>\n }\n\n const renderEpochs = () => {\n if (epochs.length) return epochs.map((epoch, index) => (\n
    \n \n {renderAddEpochButton(index)}\n
    \n ));\n return renderAddEpochButton(-1)\n }\n\n return (\n <>\n { renderEpochs() }\n \n );\n}\n\nexport default Epochs;","import React, { useState } from 'react';\nimport './Options.scss';\nimport ls from 'local-storage';\n\nconst Options = ({ options, dispatch }) => {\n const [ load, setLoad ] = useState('');\n\n const handleRadioChange = e => {\n const { name, id } = e.target;\n dispatch({\n type: 'SET_OPTIONS',\n value: {\n option: name,\n setValue: id\n }\n });\n }\n \n const handleFormSubmit = (e, options) => {\n e.preventDefault();\n dispatch({\n type: 'RUN',\n value: options\n });\n }\n\n return (\n
    \n

    Modeling Options

    \n\n
    handleFormSubmit(e, options)} data-testid=\"Options-form\">\n \n {/*
    Output
    */}\n\n handleRadioChange(e)}\n />\n \n \n handleRadioChange(e)}\n />\n \n \n handleRadioChange(e)}\n />\n \n \n \n
    \n\n\n
    {}}>\n \n \n
    \n
    \n );\n}\n\nexport default Options;","import React from 'react';\nimport './Output.scss';\n\nconst Output = props => {\n const { results, options } = props;\n const renderResults = () => {\n switch(options.output) {\n case 'default':\n return renderDefault();\n default:\n return <>\n }\n }\n\n const renderDefault = () => {\n return results.map((epoch, i) => {\n const lexicon = epoch.lexicon.map((lexeme, i) => {lexeme});\n return (\n
    \n
    {epoch.pass}
    \n

    {lexicon}

    \n
    \n )\n })\n }\n return (\n
    \n

    Results of Run

    \n\n
    \n {results && results.length ? renderResults() : <>}\n
    \n
    \n );\n}\n\nexport default Output;","// @flow\nimport type { stateType } from './reducer';\n\ntype lexemeType = {\n lexeme: string,\n epoch?: string\n}\n\ntype addLexemeAction = {\n type: 'ADD_LEXEME',\n value: lexemeType\n}\n\ntype setLexiconAction = {\n type: 'SET_LEXICON',\n value: Array\n}\n\nconst makeLexeme = (lexeme: string, epochName: ?string, state: stateType) => {\n const newLexeme = {lexeme: lexeme, epoch: state.epochs[0]};\n if (epochName) {\n const epochIndex = state.epochs.findIndex(epoch => epoch.name === epochName);\n if (epochIndex > 0) {\n newLexeme.epoch = state.epochs[epochIndex];\n };\n }\n return newLexeme;\n}\n\nexport type lexiconAction = addLexemeAction | setLexiconAction\n\nexport const addLexeme = (state: stateType, action: addLexemeAction): stateType => {\n const newLexeme = makeLexeme(action.value.lexeme, action.value.epoch, state);\n return {...state, lexicon:[...state.lexicon, newLexeme]}\n}\n\nexport const setLexicon = (state: stateType, action: setLexiconAction): stateType => {\n let newLexicon = action.value;\n newLexicon = newLexicon.map(lexeme => makeLexeme(lexeme.lexeme, lexeme.epoch, state));\n return {...state, lexicon: newLexicon}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type featureAction = {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: Array,\n negativePhones: Array,\n feature: string\n }\n}\n\nconst addPhones = (phones: {}, phone: string): {} => {\n let node = {};\n\n phone.split('').forEach((graph, index) => {\n if (index) node[graph] = {}\n if (!index && !phones[graph]) phones[graph] = {} \n node = index === 0 ? phones[graph] : node[graph];\n if (index === phone.length - 1) node.grapheme = phone;\n })\n\n return phones;\n}\n\nconst findPhone = (phones: {}, phone: string): {} => {\n return phone\n .split('')\n .reduce((node, graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n return node;\n }, {});\n}\n\nconst addFeatureToPhone = (\n phones: {}, phone: string, featureKey: string, featureValue: boolean\n): {} => {\n let node = {}\n phone.split('').forEach((graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n \n if (index === phone.split('').length - 1) {\n node.features = {...node.features, [featureKey]: featureValue}\n }\n });\n return phones;\n}\n\nexport const addFeature = (state: stateType, action: featureAction): stateType => {\n let positivePhones = action.value.positivePhones || [];\n let negativePhones = action.value.negativePhones || [];\n let newFeatureName = action.value.feature;\n let newPhoneObject = [\n ...positivePhones, ...negativePhones\n ]\n .reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)\n \n if (positivePhones) {\n\n positivePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)\n , newPhoneObject\n );\n\n positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )\n }\n \n if (negativePhones) {\n \n negativePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)\n , newPhoneObject\n );\n \n negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )\n }\n \n let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};\n return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}\n}","// @flow\nimport type { stateType, epochType, phoneType } from './reducer';\n\nexport type resultsAction = {\n type: 'RUN'\n}\n\nexport type decomposedRulesType = [\n {\n environment: {\n pre: [{[key: string]: boolean}],\n position: [{[key: string]: boolean}],\n post: [{[key: string]: boolean}]\n },\n newFeatures: [{[key: string]: boolean}]\n }\n]\n\ntype ruleBundle = {\n environment: {\n pre: string,\n position: string,\n post: string\n },\n newFeatures: string\n}\n\nconst getProperty = property => object => object[property]\n\nconst findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index && !lastIndex) featureBundle.push(phones[graph].features)\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst errorMessage = ([prefix, separator], location, err) => `${prefix}${location}${separator}${err}`\n\nconst lintRule = (rule) => {\n if (!rule.match(/>/g)) throw `Insert '>' operator between target and result`\n if (!rule.match(/\\//g)) throw `Insert '/' operator between change and environment`\n if (!rule.match(/_/g)) throw `Insert '_' operator in environment`\n if (rule.match(/>/g).length > 1) throw `Too many '>' operators`\n if (rule.match(/\\//g).length > 1) throw `Too many '/' operators`\n if (rule.match(/_/g).length > 1) throw `Too many '_' operators`\n return rule.split(/>|\\/|_/g);\n}\n\nconst decomposeRule = (rule: string, index: number): ruleBundle => {\n try {\n // splits rule at '>' '/' and '_' substrings resulting in array of length 4\n const [position, newFeatures, pre, post] = lintRule(rule); \n return { environment: { pre, position, post }, newFeatures }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nconst isUnknownFeatureToken = token => token !== '-' && token !== '+' && token !== ']' && token !== '[' && token !== ' ';\n\nconst doesFeatureRuleContainUnknownToken = features => {\n const unknownTokens = features\n .match(/\\W/g)\n .filter(isUnknownFeatureToken)\n if (unknownTokens.length) throw `Unknown token '${unknownTokens[0]}'`;\n return true\n}\n\nconst reduceFeaturesToBoolean = bool => (map, feature) => ({...map, [feature]: bool})\n\nconst getFeatures = (phoneme: string, featureBoolean): {} => {\n try {\n const featureMatch = featureBoolean\n // regEx to pull positive features\n ? /(?=\\+.).*(?<=\\-)|(?=\\+.).*(?!\\-).*(?<=\\])/g \n // regEx to pull negative features\n : /(?=\\-.).*(?<=\\+)|(?=\\-.).*(?!\\+).*(?<=\\])/g\n const [ features ] = phoneme.match(featureMatch) || [ null ];\n if (features) {\n doesFeatureRuleContainUnknownToken(features)\n return features\n .trim()\n .match(/\\w+/g)\n .reduce(reduceFeaturesToBoolean(featureBoolean), {})\n }\n return {}\n } catch (err) {\n throw err;\n }\n}\n\nconst mapToPositiveAndNegativeFeatures = phoneme => (\n { ...getFeatures(phoneme, true), ...getFeatures(phoneme, false) } )\n\nconst mapStringToFeatures = (ruleString, phones) => {\n if (ruleString) {\n if (ruleString === '.') return [];\n if (ruleString === '#') return ['#']\n if (ruleString === '0') return [];\n const ruleBrackets = ruleString.match(/\\[.*\\]/)\n try {\n if (ruleBrackets) {\n return ruleString\n .split('[')\n // filter out empty strings\n .filter(v => v)\n .map(mapToPositiveAndNegativeFeatures)\n }\n return findFeaturesFromGrapheme(phones, ruleString);\n } catch (err) {\n throw err;\n }\n }\n return {};\n}\n\nconst mapRuleBundleToFeatureBundle = phones => ( ruleBundle, index ) => {\n // for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs\n try {\n const { newFeatures, environment:{ pre, position, post } } = ruleBundle;\n return {\n environment: {\n pre: mapStringToFeatures(pre, phones),\n position: mapStringToFeatures(position, phones),\n post: mapStringToFeatures(post, phones),\n },\n newFeatures: mapStringToFeatures(newFeatures, phones)\n }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nexport const decomposeRules = (epoch: epochType, phones: {[key: string]: phoneType}): decomposedRulesType => {\n const { changes } = epoch\n try {\n return changes\n .map(decomposeRule)\n .map(mapRuleBundleToFeatureBundle(phones));\n } catch (err) {\n return err;\n }\n}\n\nconst isPhonemeBoundByRule = phonemeFeatures => (ruleFeature, index) => {\n const phoneme = phonemeFeatures[index].features;\n return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {\n if (!bool) return false;\n if (!phoneme.hasOwnProperty(feature)) return false;\n if (!phoneme[feature] && !value) return true;\n if (phoneme[feature] !== value) return false;\n return true;\n }, true);\n} \n\nconst isEnvironmentBoundByRule = (phonemeFeatures, ruleFeatures) => {\n if (!ruleFeatures) return true;\n return ruleFeatures.filter(isPhonemeBoundByRule(phonemeFeatures)).length === ruleFeatures.length;\n}\n\nconst getEntries = object => Object.entries(object);\nconst isObjectWithPropertyInArray = (array, property) => candidate => array.map(getProperty(property)).includes(candidate[property]);\nconst transformFeatureValues = features => ([newFeature, newValue]) => features[newFeature][newValue ? 'positive': 'negative'];\nconst reduceFeatureValues = (newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })\n\nconst transformPhoneme = (phoneme, newFeatures, features) => {\n if (!newFeatures) return {}\n const newPhonemeFeatures = getEntries(newFeatures).reduce(reduceFeatureValues, {...phoneme.features});\n const newPhonemeCandidates = getEntries(newPhonemeFeatures).map(transformFeatureValues(features));\n return newPhonemeCandidates\n .reduce((candidates, candidatesSubset, index, array) => candidates.filter(isObjectWithPropertyInArray(candidatesSubset, 'grapheme'))\n , newPhonemeCandidates[newPhonemeCandidates.length - 1])[0];\n}\n\nconst transformLexemeInitial = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index !== pre.length - 1) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index + position.length, index + post.length + position.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nconst transformLexemeCoda = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index + post.length !== lexemeBundle.length) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nexport const transformLexeme = (lexemeBundle, rule, features) => {\n const {pre, post, position} = rule.environment;\n const newLexeme = lexemeBundle.reduce((newLexeme, phoneme, index) => {\n if (pre.find(val => val === '#')) return transformLexemeInitial(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if (post.find(val => val === '#')) return transformLexemeCoda(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if ( index < pre.length || index >= lexemeBundle.length - post.length ) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, rule.newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme || !newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n }, [])\n return newLexeme;\n}\n\nconst formBundleFromLexicon = lexicon => phones => lexicon.map(({lexeme}) => findFeaturesFromLexeme(phones, lexeme))\n\nconst transformLexicon = lexiconBundle => \n ruleBundle => \n features => \n lexiconBundle.map(lexemeBundle => ruleBundle.reduce(\n (lexeme, rule, i) => transformLexeme(lexeme, rule, features)\n , lexemeBundle\n ))\n\nconst getGraphemeFromEntry = ([_, phoneme]) => phoneme.grapheme\nconst stringifyLexeme = (lexeme) => lexeme.map(getProperty('grapheme')).join('')\nconst stringifyResults = ({lexicon, ...passResults}) => ({...passResults, lexicon: lexicon.map(stringifyLexeme)})\n\nexport const run = (state: stateType, action: resultsAction): stateType => {\n\n // TODO iterate through each epoch\n try {\n const passResults = state.epochs.reduce((results, epoch, _) => {\n const { phones, features, lexicon } = state;\n let lexiconBundle;\n if ( epoch.parent ) {\n lexiconBundle = results.find(result => result.pass === epoch.parent).lexicon\n }\n if (!epoch.parent) {\n lexiconBundle = formBundleFromLexicon(lexicon)(phones); \n }\n const ruleBundle = decomposeRules(epoch, phones);\n const passResults = transformLexicon(lexiconBundle)(ruleBundle)(features)\n const pass = { pass: epoch.name, lexicon: passResults }\n if ( epoch.parent ) pass.parent = epoch.parent;\n return [...results, pass];\n }, []);\n \n const results = passResults.map(stringifyResults);\n return {...state, results }\n } catch (err) {\n console.log(err)\n return {...state, errors: err };\n }\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type initAction = {\n type: \"INIT\"\n}\n\nexport const initState = (changesArgument: number): stateType => {\n const state = {\n epochs: [\n {\n name: 'epoch 1',\n changes: [\n '[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',\n 'a>ɯ/._#',\n '[+ sonorant - low rounded high back]>0/._.',\n '[+ obstruent]>[+ obstruent aspirated ]/#_.',\n '[+ sonorant - rounded]>[+ sonorant + rounded]/._#',\n // 'at>ta/._#'\n ]\n }\n ],\n phones: {\n a: {\n grapheme: 'a', features: {\n sonorant: true, back: true, low: true, high: false, rounded: false\n }\n },\n u: {\n grapheme: 'u', features: {\n sonorant: true, back: true, low: false, high: true, rounded: true, \n }\n },\n ɯ: {\n grapheme: 'ɯ', features: {\n sonorant: true, back: true, low: false, high: true, rounded: false,\n }\n },\n ə: {\n grapheme: 'ə', features: {\n sonorant: true, low: false, rounded: false, high: false, back: false\n }\n },\n t: {\n grapheme: 't', features: {\n occlusive: true, coronal: true, obstruent: true, nasal: false\n },\n ʰ: {\n grapheme: 'tʰ', features: {\n occlusive: true, coronal: true, obstruent: true, aspirated: true\n }\n }\n },\n n: {\n grapheme: 'n', features: {\n sonorant: true, nasal: true, occlusive: true, coronal: true\n }\n }\n },\n options: {\n output: 'default', save: false\n },\n results: [],\n errors: {},\n features: {},\n lexicon: []\n };\n state.features = {\n sonorant: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ, state.phones.ə, state.phones.n], negative: [] },\n back: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ ], negative: [ state.phones.ə ] },\n low: { positive:[ state.phones.a ], negative: [ state.phones.u, state.phones.ɯ, state.phones.ə ] },\n high: { positive:[ state.phones.u, state.phones.ɯ ], negative: [ state.phones.a, state.phones.ə ] },\n rounded: { positive:[ state.phones.u ], negative: [ state.phones.a, state.phones.ɯ, state.phones.ə ] },\n occlusive: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n coronal: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n obstruent: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n nasal: { positive:[ state.phones.n ], negative: [state.phones.t, state.phones.t.ʰ] },\n aspirated: { positive:[ state.phones.t.ʰ ], negative: [ state.phones.t ] },\n }\n state.lexicon = [\n {lexeme: 'anta', epoch: state.epochs[0]}, \n {lexeme: 'anat', epoch: state.epochs[0]},\n {lexeme: 'anət', epoch: state.epochs[0]},\n {lexeme: 'anna', epoch: state.epochs[0]}, \n {lexeme: 'tan', epoch: state.epochs[0]},\n {lexeme: 'ənta', epoch: state.epochs[0]}\n ]\n\n if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(0, changesArgument)\n\n return state;\n}","// @flow\nimport { addLexeme, setLexicon } from './reducer.lexicon';\nimport type { lexiconAction } from './reducer.lexicon';\nimport { addEpoch, setEpoch, removeEpoch } from './reducer.epochs';\nimport type { epochAction } from './reducer.epochs';\nimport { addFeature } from './reducer.features';\nimport type { featureAction } from './reducer.features';\nimport type { optionsAction } from './reducer.options';\nimport { setOptions } from './reducer.options';\nimport { run } from './reducer.results';\nimport type { resultsAction } from './reducer.results'\nimport { initState } from './reducer.init';\nimport type { initAction } from './reducer.init';\n\nexport type stateType = {\n lexicon: Array<{lexeme: string, epoch: epochType}>,\n epochs: Array,\n phones: {[key: string]: phoneType},\n options: {output: string, save: boolean},\n results: [],\n errors: {},\n features: featureType\n}\n\ntype epochType = {\n name: string, changes: Array\n}\n\ntype phoneType = {\n grapheme: string,\n features: {[key: string]: boolean}\n}\n\ntype featureType = {\n [key: string]: {[key: string]: Array}\n}\n\ntype actionType = featureAction | epochAction | initAction | resultsAction | lexiconAction\n\nexport const stateReducer = (state: stateType, action: actionType): stateType => {\n switch (action.type) {\n case 'INIT': {\n return initState();\n }\n \n case 'ADD_LEXEME': return addLexeme(state, action);\n \n case 'SET_LEXICON': return setLexicon(state, action);\n\n case 'ADD_EPOCH': return addEpoch(state, action);\n\n case 'SET_EPOCH': return setEpoch(state, action);\n\n case 'REMOVE_EPOCH': return removeEpoch(state, action);\n\n case 'ADD_FEATURE': return addFeature(state, action);\n\n case 'SET_OPTIONS': return setOptions(state, action);\n\n case 'RUN': return run(state, action);\n\n default: return state;\n }\n}\n","// @flow\nimport type { stateType } from './reducer';\n\nexport type epochAction = {\n type: \"ADD_EPOCH\" | \"SET_EPOCH\" | \"REMOVE_EPOCH\",\n value: {\n index?: number,\n name: string,\n changes?: Array,\n parent: string\n }\n}\n\nexport const addEpoch = (state: stateType, action: epochAction): stateType => {\n const newEpoch = { name: action.value.name, changes: action.value.changes || [''] };\n return {...state, epochs: [...state.epochs, newEpoch]}\n}\n\nexport const setEpoch = (state: stateType, action: epochAction): stateType => {\n const index = action.value.index;\n if (typeof index !== 'number') return state;\n \n const mutatedEpochs = state.epochs;\n mutatedEpochs[index].name = action.value.name \n ? action.value.name \n : mutatedEpochs[index].name;\n\n mutatedEpochs[index].changes = action.value.changes \n ? action.value.changes \n : mutatedEpochs[index].changes;\n\n mutatedEpochs[index].parent = action.value.parent && action.value.parent !== 'none'\n ? action.value.parent\n : null\n return {...state, epochs: [...mutatedEpochs]}\n}\n\nexport const removeEpoch = (state: stateType, action: epochAction): stateType => {\n const mutatedEpochs = state.epochs.filter(epoch => epoch.name !== action.value.name )\n return {...state, epochs: [...mutatedEpochs]}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type optionAction = {\n type: 'SET_OPTIONS',\n value: {\n option: string,\n setValue: string\n }\n};\n\nexport const setOptions = (state: stateType, action: optionAction): stateType => {\n const option = action.value.option;\n let value = action.value.setValue;\n if (value === 'true') value = true;\n if (value === 'false') value = false;\n const mutatedState = {...state};\n mutatedState.options[option] = value;\n return mutatedState;\n}","import React, { useState, useReducer } from 'react';\nimport './PhonoChangeApplier.scss';\n\nimport ProtoLang from './components/ProtoLang';\nimport Features from './components/Features';\nimport Epochs from './components/Epochs';\nimport Options from './components/Options';\nimport Output from './components/Output';\n\nimport { stateReducer } from './reducers/reducer';\nimport { initState } from './reducers/reducer.init';\n\nconst PhonoChangeApplier = () => {\n const [ state, dispatch ] = useReducer(\n stateReducer,\n {},\n initState\n )\n const { lexicon, phones, phonemes, epochs, options, features, results } = state;\n\n return (\n
    \n \n \n \n \n \n
    \n );\n}\n\nexport default PhonoChangeApplier;","import React from 'react';\nimport './App.css';\nimport PhonoChangeApplier from './PhonoChangeApplier';\n\nfunction App() {\n return (\n
    \n

    Phono Change Applier

    \n \n
    \n );\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.scss';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/stylesheets/_variables.scss b/stylesheets/_variables.scss index 14f3b60..47a3d48 100644 --- a/stylesheets/_variables.scss +++ b/stylesheets/_variables.scss @@ -3,4 +3,5 @@ $colors: ( "main": #d5bfbf, "text-input": #e8e22e, "text-input--bg": #1d191a, + "error": #ff0000 ); \ No newline at end of file