logo

Grimgrains

Unnamed repository; edit this file 'description' to name the repository.
commit: b7eb2654b39ffff27c31aae3093cc0b9683e0606
parent 0863f144a3311c9c16cd3b98c1aeabe1d33de101
Author: Rekka <rekkabell@gmail.com>
Date:   Wed,  9 Jan 2019 13:33:02 +1200

Merge branch 'master' of https://github.com/hundredrabbits/Grimgrains

Diffstat:

Mlinks/main.css89+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mlinks/riven.main.css2--
Amedia/recipes/seitan.2.jpg0
Amedia/recipes/seitan.3.jpg0
Amedia/recipes/seitan.jpg0
Mscripts/database/ingredients.js344+++++++++++--------------------------------------------------------------------
Mscripts/database/pages.js12++++--------
Mscripts/database/recipes.js33+++++++++++++++++++++++++++++++--
Mscripts/graph.js81++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mscripts/lib/riven.graph.js275+++++++++++++++++++++++++++++++++++++------------------------------------------
Mscripts/lib/riven.js234++++++++++++++++++++++++++++++++++++--------------------------------------------
Mscripts/lib/runic.js213+++++++++++++++++++++++++++++++++++++------------------------------------------
Mscripts/nodes/database.js15++++++---------
Mscripts/nodes/document.js13+++++--------
Mscripts/nodes/dom.js42++++++++++++++++++------------------------
Mscripts/nodes/indental.js83+++++++++++++++++++++++++++++++++++--------------------------------------------
Mscripts/nodes/query.js57++++++++++++++++++++++++++-------------------------------
Mscripts/nodes/router.js46+++++++++++++++++++++-------------------------
Mscripts/nodes/template.js21+++++++++------------
Mscripts/templates/home.js99++++++++++++++++++++++++++++++++++++-------------------------------------------
Mscripts/templates/ingredient.js154++++++++++++++++++++++++++++++++++++-------------------------------------------
Mscripts/templates/page.js34+++++++++++++++-------------------
Mscripts/templates/recipe.js130+++++++++++++++++++++++++++++++++++++------------------------------------------
Mscripts/templates/search.js17+++++++----------
24 files changed, 825 insertions(+), 1169 deletions(-)

diff --git a/links/main.css b/links/main.css @@ -1,13 +1,12 @@ -body { background:#fcfcfc; font-family: 'Helvetica Neue', Helvetica, Arial } -yu { display: block; } +body { background:#000; font-family: 'Helvetica Neue', Helvetica, Arial } hr { clear:both; } -list { display: block; } -list ln { display: block } +ul { display: block; } img { max-width: 100% } h1,h2,h3,h4 { font-weight: normal; font-family: 'alte_haas_grotesk_bold'; margin-bottom: 30px } -#view { max-width: 900px; margin:0px auto; padding:90px 30px; } +#view { margin: 5px auto 0px;padding: 45px 30px;background: white } +#view > * { max-width: 800px; margin:0px auto; } #view.loading { opacity: 0 } #view.loading #header #photo { opacity: 0 } @@ -18,72 +17,82 @@ h1,h2,h3,h4 { font-weight: normal; font-family: 'alte_haas_grotesk_bold'; margin #view #header #logo a { cursor: pointer; transition: all 250ms; } #view #header #logo a:hover { opacity: 0.7 } #view #header #logo a img { max-width: 240px; display: block; margin:0px auto; margin-bottom:30px; } -#view #header list { display: block;text-align: center;line-height: 30px; padding-bottom:15px; } -#view #header list a { display: inline-block; font-family: 'alte_haas_grotesk_bold'; font-size:14px; line-height: 30px; border-bottom:2px solid transparent } -#view #header list a:hover { border-bottom:2px solid black } +#view #header ul { display: block;line-height: 40px; border-bottom: 2px solid black; margin-bottom:30px } +#view #header ul li { display: inline-block;border-top-left-radius: 3px;border-top-right-radius: 3px; margin-right:10px; margin-bottom: -2px; line-height: 40px} +#view #header ul li:hover { } +#view #header ul li a { display: inline-block; font-family: 'alte_haas_grotesk_bold'; font-size:14px; line-height: 40px; border-bottom:2px solid transparent } +#view #header ul li a:hover { opacity: 1 !important; } #view #header #search { display: none } -#view.home #header list a.home { border-bottom-color: black} -#view.about #header list a.about { border-bottom-color: black} -#view.tools #header list a.tools { border-bottom-color: black} +#view.home #header ul a.home { color:#ccc;} +#view.about #header ul a.about { color:#ccc;} +#view.tools #header ul a.tools { color:#ccc;} #view #core { margin-bottom:30px; } #view #core #content { position: relative; z-index: 100; margin-bottom:45px; } #view #core #content h1 { text-transform: capitalize; font-size:36px; max-width:400px } #view #core #content h2 { text-transform: capitalize; font-size:28px; } +#view #core #content h1.name { float:left; font-size:32px; line-height: 40px } +#view #core #content h2.serving { float:right; font-size:32px; line-height: 40px } #view #core #content h3 { text-transform: capitalize; font-size:24px; border-bottom:2px solid black; line-height: 45px } #view #core #content hr.stroke { border-bottom:2px solid black; max-width: 600px; margin-bottom:30px; } #view #core #content p { font-size:18px; margin-bottom: 30px; max-width:600px; line-height: 26px } #view #core #content p.bref { font-size:28px; margin-bottom: 45px; line-height: 34px } -#view #core #content p a { font-weight: bold } -#view #core #content p a:hover { text-decoration: underline; } +#view #core #content p a { font-weight: bold; cursor: pointer; text-decoration: underline; } +#view #core #content p a:hover { text-decoration: none; } +#view #core #content p a.external:after { content:"*"; color:#999; } #view #core #content p b { font-weight: bold; } #view #core #content img { margin-bottom: 30px; border-radius: 2px } #view #core #content img.photo { width:100%; } #view #core #content columns { columns:2; display: block; margin-bottom:30px; column-gap: 30px } -#view #core #content columns list { line-height: 24px } -#view #core #content columns list ln { padding-left:25px; position: relative; } -#view #core #content columns list ln:before { content:"●"; position: absolute; top:0px; left:0px; font-size:12px;} -#view #core #content columns list ln a { font-weight: bold } +#view #core #content columns ul { line-height: 24px } +#view #core #content columns ul li { padding-left:25px; position: relative; } +#view #core #content columns ul li:before { content:"●"; position: absolute; top:0px; left:0px; font-size:12px;} +#view #core #content columns ul li a { font-weight: bold } +#view #core #content ul.bullet li { font-weight: bold;position: relative;padding-left:30px;line-height: 25px; } +#view #core #content ul.bullet li:before { content:"•"; position: absolute;left:15px; } +#view #core #content ul.bullet li a { text-decoration: underline; } #view #core #content #instructions { margin-bottom:30px; } -#view #core #content #instructions list { margin-bottom:30px; } -#view #core #content #instructions list ln { max-width:700px; margin-bottom:15px; font-size:18px; padding-left:30px; line-height: 24px} -#view #core #content #instructions list ln:before { content:"•"; position: absolute; left:0px; } -#view #core #content #instructions list ln a { font-weight: bold } +#view #core #content #instructions ul { margin-bottom:30px; } +#view #core #content #instructions ul li { max-width:700px; margin-bottom:15px; font-size:18px; padding-left:30px; line-height: 24px} +#view #core #content #instructions ul li:before { content:"•"; position: absolute; left:0px; } +#view #core #content #instructions ul li a { font-weight: bold } #view #core #content #instructions note { max-width:700px; margin-bottom:15px; font-size:18px; padding-left:30px; display: block; font-style: italic; font-size:14px; margin-bottom:30px; } #view #core #content #instructions a { font-weight: bold; } #view #core #content #instructions a:hover { text-decoration: underline; cursor: pointer } #view #core #content #instructions i { background: #eee;font-size: 12px;text-transform: uppercase;padding: 5px 7.5px;display: inline;font-weight: bold;border-radius: 3px;color:#333 } #view #core #content #instructions code { font-size: 12px;text-transform: uppercase;padding: 3px 5.5px;display: inline;font-weight: bold;border-radius: 3px;border:2px solid black;} -#view #core #content list.ingredients { display: inline-block; margin-right:15px; font-size:0; padding-left:20px; margin-bottom:30px; } -#view #core #content list.ingredients h3 { margin-left:-20px; } -#view #core #content list.ingredients ln.ingredient { width: 100px;margin-left:-20px;min-height: 210px;display: inline-block;text-align: center;vertical-align: top;border: 2px dashed transparent;border-radius: 10px; } -#view #core #content list.ingredients ln.ingredient:hover t.name { text-decoration: underline; } -#view #core #content list.ingredients ln.ingredient.missing t.name { font-style: italic } -#view #core #content list.ingredients ln.ingredient img { max-width: 100% } -#view #core #content list.ingredients ln.ingredient t.name { display: block; font-family: 'alte_haas_grotesk_bold'; font-size:14px; margin-bottom: 5px;padding:0px 10px } -#view #core #content list.ingredients ln.ingredient t.quantity { display: block; font-size:12px; } +#view #core #content ul.ingredients { display: inline-block; margin-right:15px; font-size:0; padding-left:20px; margin-bottom:30px; } +#view #core #content ul.ingredients h3 { margin-left:-20px; } +#view #core #content ul.ingredients li.ingredient { width: 100px;margin-left:-20px;min-height: 210px;display: inline-block;text-align: center;vertical-align: top;border: 2px dashed transparent;border-radius: 10px; } +#view #core #content ul.ingredients li.ingredient:hover t.name { text-decoration: underline; } +#view #core #content ul.ingredients li.ingredient.missing t.name { font-style: italic } +#view #core #content ul.ingredients li.ingredient img { max-width: 100% } +#view #core #content ul.ingredients li.ingredient t.name { display: block; font-family: 'alte_haas_grotesk_bold'; font-size:14px; margin-bottom: 5px;padding:0px 10px } +#view #core #content ul.ingredients li.ingredient t.quantity { display: block; font-size:12px; } #view #core #related { width:100%;} -#view #core #related ln { width: calc((100% / 3) - 10px); float:left; overflow: hidden;} -#view #core #related ln:nth-child(1), #view #core #related ln:nth-child(2) { margin-right:15px;} -#view #core #related ln a.photo { border-radius: 2px; display: block; height:160px; background-size:cover; margin-bottom:15px; background-position: center } -#view #core #related ln t.name { display: block; font-family: 'alte_haas_grotesk_bold'; font-size:16px; margin-bottom: 5px; text-transform: capitalize; line-height: 30px } -#view #core #related ln t.details { display: block; font-family: 'alte_haas_grotesk_regular'; font-size:14px; text-transform: capitalize; line-height: 30px; line-height: 18px } +#view #core #related li { width: calc((100% / 3) - 10px); float:left; overflow: hidden;} +#view #core #related li:nth-child(1), #view #core #related li:nth-child(2) { margin-right:15px;} +#view #core #related li a.photo { border-radius: 2px; display: block; height:160px; background-size:cover; margin-bottom:15px; background-position: center } +#view #core #related li t.name { display: block; font-family: 'alte_haas_grotesk_bold'; font-size:16px; margin-bottom: 5px; text-transform: capitalize; line-height: 30px } +#view #core #related li t.details { display: block; font-family: 'alte_haas_grotesk_regular'; font-size:14px; text-transform: capitalize; line-height: 30px; line-height: 18px } #view #core #content #recipes { columns:3; font-size:14px; font-weight: bold} -#view #core #content #recipes ln { display: block } -#view #core #content #recipes ln a:hover { text-decoration: underline; cursor: pointer; } +#view #core #content #recipes li { display: block } +#view #core #content #recipes li a:hover { text-decoration: underline; cursor: pointer; } #view #core #content #recipes h3 { margin-bottom:10px; } -#view #footer { display: block; padding:15px 0px;font-family: 'alte_haas_grotesk_bold'; font-size:12px; margin-top:60px; } +#view #footer { display: block; padding:15px 0px;font-family: 'alte_haas_grotesk_bold'; font-size:14px; margin-top:60px; } #view #footer a:hover { text-decoration: underline; cursor: pointer } -@media (max-width: 950px) { +@media (max-width: 850px) { #view #core #content #recipes { columns:1; } #view #core #content columns { columns:1; } - #view #core #related ln { width:100%; clear:both; float:none; height:330px; } - #view #core #related ln a.photo { height:200px; } + #view #core #content h1.name { float:none; } + #view #core #content h2.serving { float:none; font-size:18px; line-height: 12px } + #view #core #related li { width:100%; clear:both; float:none; height:330px; } + #view #core #related li a.photo { height:200px; } } diff --git a/links/riven.main.css b/links/riven.main.css @@ -17,8 +17,6 @@ svg path.route.request { stroke-dasharray: 5,5; } svg path.route.bidirectional { stroke:#33; stroke-dasharray: 0,4; } svg g:hover text { fill:#72dec2; cursor: pointer; } -yu { display: none } - path.route { stroke-dashoffset: 100; animation: dash 5s linear infinite; } path.route.request { stroke-dashoffset: -50; animation: dash 5s linear infinite; } @keyframes dash { to { stroke-dashoffset: 0;} } \ No newline at end of file diff --git a/media/recipes/seitan.2.jpg b/media/recipes/seitan.2.jpg Binary files differ. diff --git a/media/recipes/seitan.3.jpg b/media/recipes/seitan.3.jpg Binary files differ. diff --git a/media/recipes/seitan.jpg b/media/recipes/seitan.jpg Binary files differ. diff --git a/scripts/database/ingredients.js b/scripts/database/ingredients.js @@ -1,61 +1,47 @@ DATABASE.ingredients = ` Coffee - BREF : {{Coffee}} is a brewed drink prepared from roasted coffee beans, which are the seeds of berries from the Coffea plant. + BREF : {{Coffee}} is a brewed drink prepared from roasted coffee beans, which are the seeds of berries from the {{Coffea plant|https://en.wikipedia.org/wiki/Coffea}}. LONG - % blog/coffee.jpg - > <columns> - * Coffee on Pino - & Devine & I are coffee drinkers, we have a one per day. We have a second cup on occasion - or, second wind, as we like to call it. We drink it black, but enjoy having a flat white (has less milk than a latte) with a {{non-dairy milk|Soy Milk}} as a treat. - & Most times, we have a cup at home on {{Pino|http://100r.co}}, and so having good coffee gear is essential. We had two requirements: {{portability and durability|http://100r.co/resources.html#habitat}}. (Two of my glass presses have made friends with the floor in the past.) - & Our first buy, was a {{GSI outdoors french press|http://www.amzn.to/2FrWg8a}}. It's BPA-free (made from co-polyester), and shatter resistant - perfect for those of us prone to recurrent bouts of clumsiness. - & We like to grind our own beans, so we got a {{GSI outdoors coffee grinder|http://www.amzn.to/2p0pO2p}}. Non-electric, and portable. - & Sometimes, we use a stainless steel moka pot for espresso. The model is an {{ikea RADIG espresso pot|http://www.ikea.com/us/en/catalog/products/30149839/}}, we found it in a bin at the marina. I didn't know ikea made moka pots. I can't say this would be my first choice, but it was free and it works so... ¯&#92;_(ツ)_/¯. % blog/coffee.2.jpg - & I'm not saying that these brands are the very best, but they suit our needs. We bought these while in Victoria BC from MEC. GSI is the in-store brand for camping goods, their products have not failed us yet, and so we like to recommend them. + & Devine & I are daily coffee drinkers, we sometimes have a second cup in the afternoon, but typically we limit ourselves to a single cup in the morning. We drink it {*black*}, but enjoy the occasional flat white as a treat. + & We grind new beans each morning with a portable manual {{coffee grinder|http://www.amzn.to/2p0pO2p}}. We mainly use a {{stainless steel moka pot|http://www.ikea.com/us/en/catalog/products/30149839/}} for espresso. + & To make a perfect espresso with the moka pot, here are a few things to remember: + • The grind should be only slightly smaller than filter coffee. + • Warm up the water in the bottom part before screwing the top section. + • Take apart and clean the moka pot after each use. + & &nbsp; + % blog/coffee.jpg & To finish, here is a list of the coffee places we've tried (and loved) in our travels: - - {{Prado|https://pradocafe.co}} - Vancouver, CA - - {{Cafe Neve|http://www.cafeneve.com}} - Montreal, CA - - {{Sextant Coffee Roasters|https://sextantcoffee.com}} - San Francisco, CA, US - - {{Big Sur|https://www.facebook.com/BigSurCafeOrganico/}} - La Paz, Mexico - - {{Fat Camel|https://www.facebook.com/Fat-Camel-Israeli-Cafe-111529865551331/}} - Whangarei, NZ - > </columns> + • {{Prado|https://pradocafe.co}} — Vancouver, CA + • {{Cafe Neve|http://www.cafeneve.com}} — Montreal, CA + • {{Sextant Coffee Roasters|https://sextantcoffee.com}} — San Francisco, CA, US + • {{Big Sur|https://www.facebook.com/BigSurCafeOrganico/}} — La Paz, Mexico + • {{Fat Camel|https://www.facebook.com/Fat-Camel-Israeli-Cafe-111529865551331/}} — Whangarei, NZ ~ LEGUMES Lentils - BREF : [red#FF6600 beluga#000000 green] Lentils are considered to be one of the best foods because their chemical structures are not altered by cooking. Lens is the latin name for lentil. + BREF : Lentils are considered to be one of the best foods because their chemical structures are not altered by cooking. Lens is the latin name for lentil. Beluga Lentils Color : #000000 - Tempeh - BREF : [#875A2C] Missing. + Color : #875A2C Peanut - BREF : [butter] Missing. Peanut Butter - BREF : Missing. - - - Peanuts - BREF : Missing. Soy beans BREF : [#EFEFEF milk flour] If you produce your own soy milk, know that there wont be any waste. The pulp can be used to make okara, which you can use to make baked goods. Beans BREF : [black green kidney] There are over 130 varieties of green beans. Edamame - BREF : Missing. Chickpeas - BREF : [#FFD800] Missing. Chickpea - BREF : [#FFD800 flour hummus] Missing. Chickpea Flour Peas - BREF : [#006633 split green] Missing. Green Peas Mungbeans - BREF : [noodles sprouts] Missing. ~ CRUCIFEROUS @@ -81,20 +67,15 @@ Cauliflower White Cauliflower Purple Cauliflower Brussel sprouts - BREF : Missing. Daikon - BREF : [#EFEFEF] Bok choy - BREF : Missing. Radish - BREF : Missing. ~ ALGEA FUNGI Wakame BREF : [#006633] Wakame is a very invasive plant, its even banned in australia. Dried Hijiki - BREF : [#000000 dried] Missing. Bull kelp powder BREF : No description. Nori @@ -107,55 +88,44 @@ Crimini Portobello BREF : [#875A2C] Portobello are mature 'common mushroom'. They can be used in plantbased recipes as hamburger steaks, you can even use them as buns. Shimeji - BREF : Missing. Button Mushrooms - BREF : Missing. -Dehydrated mushrooms - BREF : Missing. +Dehydrated mushro Black mushrooms - BREF : Missing. Straw mushrooms - BREF : Missing. ~ SEEDS Flax seeds - BREF : [#875A2C] Flax is the national flower of Belarus. + BREF : Flax is the national flower of Belarus. Sunflower seeds - BREF : [#875A2C] Missing. Pumpkin seeds - BREF : [#006633] Missing. Sesame seeds - BREF : [white#EFEFEF black#000000 butter] Tahini is made by grinding toasted hulled sesame seeds. It is used in baba ghanoush, halva, hummus and in many other recipes. Because of its high oil content, it needs to be refrigerated to prevent spoilage. Tahini has high levels of calcium and protein, making it a must ingredient in any plantbased pantry. + BREF : Tahini is made by grinding toasted hulled sesame seeds. It is used in baba ghanoush, halva, hummus and in many other recipes. Because of its high oil content, it needs to be refrigerated to prevent spoilage. Tahini has high levels of calcium and protein, making it a must ingredient in any plantbased pantry. White Sesame seeds Black Sesame seeds Tahini - BREF : Missing. pomegranate seeds - BREF : [#94191C] Missing. Chia seeds - BREF : Missing. ~ ROOT VEGETABLES Carrots - BREF : [#FF6600 heirloom] Overconsumming carrots can cause what is reffered to as "Carotenosis", a condition in which the skin turns orange. + BREF : Overconsumming carrots can cause what is reffered to as "Carotenosis", a condition in which the skin turns orange. Heirloom Carrots Ginger - BREF : [#FFD800 root powder jam cookies beer] Ginger Root Potatoes - BREF : [#EFEFEF russet sweet#FF6600 powder] Since vitamin A deficiency is a common problem in africa, people are encouraged to eat sweet potatoes. + BREF : Since vitamin A deficiency is a common problem in africa, people are encouraged to eat sweet potatoes. Russet Potatoes Sweet Potatoes Beets - BREF : [#94191C red golden#FFD800 juice#C820B3] Golden beets are rich in b-xanthin pigment, making it not a replacement to red beets (which contain betalain pigment). Both pigments offer different health benefits! Don't be alarmed, beet root juice will make your urine red for a day. + BREF : Golden beets are rich in b-xanthin pigment, making it not a replacement to red beets (which contain betalain pigment). Both pigments offer different health benefits! Don't be alarmed, beet root juice will make your urine red for a day. Golden Beets Red Beets Yuka - BREF : [#EFEFEF] Tapioca is actually a starch extracted from Yuca roots. + BREF : Tapioca is actually a starch extracted from Yuca roots. Garlic - BREF : [#EFEFEF powder] Garlic has been used in many cultures around the world for thousands of years. Dating all the way back to the time the pyramids were built! + BREF : Garlic has been used in many cultures around the world for thousands of years. Dating all the way back to the time the pyramids were built! Garlic Powder Red Onion Color : #C820B3 @@ -166,290 +136,122 @@ Yellow Onion ~ OTHER VEGETABLES Cucumber - BREF : [#006633 pickled] Cucumbers are usually more than 90% water. - Tags - other vegetables + BREF : Cucumbers are usually more than 90% water. Eggplant - BREF : [#6620B3] - Tags - other vegetables Zucchini - BREF : [#006633] - Tags - other vegetables Chile - BREF : [#006633 green] - Tags - other vegetables Green Chile Peppers - BREF : [red#94191C yellow#FFD800 green#006633] The misleading name 'pepper' was given by Christopher Columbus when he brought back a plant to europe. The word pepper was given to all spices in europe that had a hot and pungent taste. + BREF : The misleading name 'pepper' was given by Christopher Columbus when he brought back a plant to europe. The word pepper was given to all spices in europe that had a hot and pungent taste. Green Peppers Red Peppers Yellow Peppers - Tomato - BREF : [paste#94191C dried heirloom#94191C] The tomatoes can also be dried with an oven. - Tags - other vegetables - + BREF : The tomatoes can also be dried with an oven. Tomato Paste BREF : The tomatoes can also be dried with an oven. - Tags - other vegetables - Avocado - Color : #006633 BREF : Avocados are botanically 'berries', they may be pear-shaped, round or egg-shaped. It is a good source of fat. Fun fact: Avocado trees dont self-pollinate, they need another avocado tree nearby to bear fruit. - Tags - other vegetables - Pumpkin - BREF : [#FF6600] The darker the skin of the pumpkin, the higher the beta carotene content. - Tags - other vegetables + BREF : The darker the skin of the pumpkin, the higher the beta carotene content. Olives - BREF : [green black] - Tags - other vegetables Green Olives Black Olives Palm - BREF : [#EFEFEF heart] Heart of palm is a vegetable that is harvested from the inner core of certain palm trees. They can be eaten as is, but they're especially delicious when tossed into a salad. + BREF : Heart of palm is a vegetable that is harvested from the inner core of certain palm trees. They can be eaten as is, but they're especially delicious when tossed into a salad. Squash - BREF : [#FF6600 acorn] The seeds of the acorn squash can be eaten, they're delicious when roasted! - Tags - other vegetables + BREF : The seeds of the acorn squash can be eaten, they're delicious when roasted! Artichokes - BREF : Missing. - Tags - other vegetables Asparagus - BREF : Missing. - Tags - other vegetables Bamboo shoots - BREF : Missing. - Tags - other vegetables Breadfruit - BREF : Missing - Tags - other vegetables Scallions - BREF : [#006633] In some countries scallions are mistakenly referred to as 'shallots'. - Tags - other vegetables + BREF : In some countries scallions are mistakenly referred to as 'shallots'. Spinach - Color : #006633 Desc : During the cold war, wine with added spinach juice was given to weakened soldiers. - Tags - other vegetables Alfaalfa sprouts - BREF : Missing - Tags - other vegetables ~ BERRIES Raisins - BREF : [#875A2C, dried] Missing. Dried Raisins Blackberries - BREF : No description. Cherries - BREF : No description. Mulberries - BREF : No description. Raspberries - BREF : No description. Strawberries - BREF : No description. Cranberries - BREF : [#94191C dried] Dried cranberries are often coated with a bit of vegetable oil to keep them from sticking to each other, look in natural food stores to find brands that don't do this + BREF : Dried cranberries are often coated with a bit of vegetable oil to keep them from sticking to each other, look in natural food stores to find brands that don't do this Goji - BREF : [#94191C] Mixed Berries - BREF : Missing. ~ OTHER FRUITS Pandanus fruit BREF : The fruit of the pandanus tectorius tree is widely consumed in the pacific islands, but it goes under other names, like "hala", "screwpine" or "pu hala". The phalanges covering the inner core are buoyant, so like coconuts they be transported for many months by ocean currents while remaining viable. - Tags - Other Fruits Banana BREF : A fruit (actually a berry) consummed the world over, and come from two wild species. It varies in size and color, and always grows in clusters at the top of the plant. They're 75% water. They can be used in a variety of ways in recipes, for both desserts and savoury meals. A low source of fat, it can be used to make non-dairy ice cream. - Color : #FFD800 - Tags - Other Fruits - Kiwi - BREF : Missing. - Color : 006633 - Tags - Other Fruits - Apple - BREF : [sauce juice] Missing. - Tags - Other Fruits - Apples - BREF : Missing. - Tags - Other Fruits - Lemon - BREF : [juice zest] Lemon juice can be used as an invisible ink, revealed with heat. - Color : #FFD800 - Tags - Other Fruits - + BREF : Lemon juice can be used as an invisible ink, revealed with heat. Lemon Zest Lemon Juice - Orange - BREF : [juice jam] In the early 16th century, the orange was considered a luxury item and rich people would grow it in private conservatories called "orangeries". - Color : #FF6600 - Tags - Other Fruits - + BREF : In the early 16th century, the orange was considered a luxury item and rich people would grow it in private conservatories called "orangeries". Pear - BREF : [Bartlett Bosc] - Color : #875A2C - Tags - Other Fruits - Bartlett Pear - Papaya - BREF : [] - Color : #FF6600 - Tags - Other Fruits - Pomegranate - BREF : [ juice] - Color : #94191C - Tags - Other Fruits - Pomegranate Juice - Mango - BREF : [] - Color : #FFD800 - Tags - Other Fruits - Lime - BREF : [ juice] - Color : #006633 - Tags - Other Fruits - Hachiya Persimmon Persimmon - BREF : [ hachiya] Unripe persimmon can be frozen outside during winter to help speed up the ripening process. - Color : #FF6600 - Tags - Other Fruits - Dates - BREF : [ deglet_noor caramel] Date palms have been around for at least 50 million years - Color : #875A2C - Tags - Other Fruits + BREF : Date palms have been around for at least 50 million years Deglet Noor Dates - - Pamplemousse - BREF : [juice] Missing. - Tags - Other Fruits - Rhubarb - BREF : [jam] Missing. - Tags - Other Fruits - Apricot Jam - BREF : [jam]Missing. - Tags - Other Fruits - Starfruit - BREF : Missing. - Tags - Other Fruits - Mixed fruits - BREF : Missing. - Tags - Other Fruits - Coconut - BREF : Missing. - Tags - Other Fruits - Date - BREF : Missing. - Tags - Other Fruits - Plums - BREF : Missing. - Tags - Other Fruits - Pineapple -Tags - Other Fruits - - BREF : Missing. - Tags - Other Fruits - ~ SPICES Turmeric - BREF : [#FFD800 ground fresh] Its sometimes used as a fabric dye, namely for Buddhist Monk's robes. + BREF : Its sometimes used as a fabric dye, namely for Buddhist Monk's robes. Ground Turmeric Cinnamon - BREF : [#875A2C] Cinnamon and garlic and be used to preserve fried foods + Color : 875A2C + BREF : Cinnamon and {{garlic}} and be used to preserve fried foods Rosemary - BREF : [#006633] Missing. Basil Dried Basil - BREF : [#006633 dried] When soaked in water, the seeds of some basil varieties become gelatinous. They are in turn used in drinks and desserts. + BREF : When soaked in water, the seeds of some basil varieties become gelatinous. They are in turn used in drinks and desserts. Wasabi - BREF : [#006633 powder] Missing. Wasabi Powder Sichuan peppercorns - BREF : [#875A2C] Missing. Coriander - BREF : [#006633] Missing Mint BREF : [#006633 fresh] Oil derived from fresh mint can be used as a friendly insecticide. Fresh Mint Cocoa - BREF : [#6620B3 powder] Missing. Cocoa Powder Cayenne - BREF : [#94191C pepper] Missing. Cayenne Pepper Anise - BREF : [seeds] Missing Anise Seeds Nutritional yeast BREF : [#FFD800] In the US it's sometimes referred to as "nooch". Vanilla - BREF : [extract] Missing. Vanilla Extract Nutmeg BREF : [#875A2C] If consumed in high doses, raw nutmeg has psychoactive effects. @@ -496,35 +298,25 @@ Chili Pepper Flakes Hops BREF : [#006633] There are many different varieties of hops around, from all corners of the globe. Dried orange peel - BREF : Missing. Oregano - BREF : Missing. Cardamom - BREF : Missing. Ajwain - BREF : Missing. Fenugreek - BREF : [seeds] Missing. ~ WHOLEGRAINS Whole wheat flour Buckwheat - BREF : [#875A2C noodles flour cookies pancakes] Missing. Buckwheat noodles Buckwheat flour Quinoa BREF : No description. Whole wheat - BREF : [pitas flour#875A2C crackers bread] Missing. Einkorn - BREF : [flour] Missing. Einkorn Flour Spelt - BREF : [flour] Missing. Spelt Flour Corn - BREF : [#FFD800 pop semolina cornmeal hominy] Missing. Cornmeal Corn Semolina @@ -550,11 +342,8 @@ All Purpose Flour Breadfruit Flour BREF : The product of dried and ground breadfruit. Can be used to make cakes, pasta and a number of other meals. Wheat Semolina - BREF : Missing. Oatmeal - BREF : Missing. Cornmeal - BREF : Missing. ~ SPECIAL @@ -569,9 +358,7 @@ Tofu Silken Tofu Burmese Tofu Nutolene - BREF : Missing. Soy protein - BREF : Missing. ~ SAUCES @@ -585,19 +372,15 @@ Mirin ~ POWDERS Baking powder - BREF : [#EFEFEF] Missing. Bamboo charcoal powder BREF : [#000000] Bamboo charcoal comes from pieces of bamboo plants, harvested after at least five years, and burned in ovens at temperatures ranging from 800 to 1200 °C. It benefits environmental protection by reducing pollutant residue. It is an environmentally functional material featuring excellent absorption properties. It can be added to foods to give it a black tint, it's very popular in Japan. You can get some through Taketora, a japanese company. (wikipedia description). & NOTE: {*Bamboo charcoal*} binds on the nutrients in food that you're meant to be digesting, so it's preferable to not add bamboo charcoal to every food you make. Use it sparingly, as an occasional treat. Cornstarch - BREF : [#EFEFEF] Missing. Active dry yeast - BREF : [#FFD800] Missing. Baking soda BREF : Since sodium bicarbonate can cause alkalosis, it's sometimes used to treat aspirin overdoses. Agar agar BREF : Agar is used to make impression material in dentistry. Arrowroot starch - BREF : Missing ~ SYRUPS @@ -618,7 +401,6 @@ Apple cider vinegar ~ SUPPLEMENTS B12 supplement - BREF : Missing. ~ TEA @@ -631,17 +413,9 @@ Matcha Powder Houjicha BREF : KitKat in japan has a houjicha flavour. color : #875A2C - Tags - Tea Hibiscus - BREF : [tea] Missing. - Tags - Tea Mint tea - BREF : Missing. - Tags - Tea Lapsang souchong BREF : Missing. @@ -652,19 +426,13 @@ Lapsang souchong ~ ALCOHOL Wine - BREF : [#6620B3] Wine has long been used as an antiseptic to treat wounds, it was even used to treat pain from child birth. + BREF : Wine has long been used as an antiseptic to treat wounds, it was even used to treat pain from child birth. Beer - BREF : No description. Sake - BREF : No description. Whisky - BREF : No description. Cider - BREF : Missing. Rhum - BREF : Missing. Porto - BREF : Missing. ~ OILS @@ -677,67 +445,46 @@ Olive oil Sesame oil BREF : [#875A2C] Sesame oil is sometimes mixed into very hot and spicy food to help neutralize the heat. Peppermint oil - BREF : Missing ~ MISC Coconut milk - BREF : [#EFEFEF] Missing. Soy milk - BREF : [#EFEFEF] Missing. Purple potato powder BREF : [#6620B3] Baguette BREF : [#875A2C] A law in the 1920's was put in place to keep bakers from working before 4 am, this didn't give them time to make proper rounded loaves. Making slender baguettes was a simple solution to this problem since they bake more rapidly. Bread crusts - BREF : [#875A2C] Missing. Vegan butter BREF : No description. Royal blue colouring - BREF : [#145BAC] Missing. Violet colouring - BREF : [#6620B3] Missing. Wholegrain macaroni - BREF : [#875A2C] Missing. Scoobi do - BREF : No description. Fusilli - BREF : No description. Soy yogurt - BREF : [#EFEFEF] Missing. Kinako - BREF : No description. -Blue corn tortillas - BREF : Missing. +Blue corn tortilla Tofurky sausages - BREF : Missing. Corn tortillas - BREF : Missing. Sugar apple BREF : Sugar apples are covered with scale-like protuberances that you can pry off easily when the fruit is ripe. The skin is soft and sweet and can be eaten with a spoon, once the seeds have been removed. Sugar apples are high energy, and str very rich in minerals. They are a good source of calcium, manganese, phosphorus and vitamins B and C. Fleur de sel - BREF : [#efefef] Vegetable bouillon - BREF : [#875A2C] Dehydrated vegetable bouillon has many names depending on where you live. In Canada and the US it is known as 'bouillon cube', it's known as 'stock cube' in Australia, Ireland, New Zealand, South Africa and in the UK. And as 'dehydrated bouillon' in France. + BREF : Dehydrated vegetable bouillon has many names depending on where you live. In Canada and the US it is known as 'bouillon cube', it's known as 'stock cube' in Australia, Ireland, New Zealand, South Africa and in the UK. And as 'dehydrated bouillon' in France. macaroni - BREF : [wholegrain] Missing. Tajin - BREF : Missing. Instant noodles - BREF : Missing. Water BREF : 70% of the fresh water used by people goes to agriculture. Sugar - BREF : [#EFEFEF brown#875A2C powdered whole_cane#875A2C coconut#875A2C] The average person consumes about 24kg of sugar per year, which is about 260 calories per day. Natural brown sugars that have been highly centrifuged go by the names of turbinado, demeara or raw sugar. Others that have been midly centrifuged and that have a higher molasses content go by Panela, rapadura, jaggery, muscovado etc. Powdered sugar is available in different degrees of fineness, the more X's the finer the grain. + BREF : The average person consumes about 24kg of sugar per year, which is about 260 calories per day. Natural brown sugars that have been highly centrifuged go by the names of turbinado, demeara or raw sugar. Others that have been midly centrifuged and that have a higher molasses content go by Panela, rapadura, jaggery, muscovado etc. Powdered sugar is available in different degrees of fineness, the more X's the finer the grain. Powdered Sugar Whole Cane Sugar Coconut Sugar Brown Sugar - - Salt - BREF : [#EFEFEF sea] Some boutiques in hawaii sell black salt with powdered black lava added in. Fleur de sel is considered more of a garnish or a condiment, it creates contrast in sweet deserts. + BREF : Some boutiques in hawaii sell black salt with powdered black lava added in. Fleur de sel is considered more of a garnish or a condiment, it creates contrast in sweet deserts. Sea Salt Chocolate - BREF : [dark]Missing -`- \ No newline at end of file +` diff --git a/scripts/database/pages.js b/scripts/database/pages.js @@ -2,27 +2,24 @@ DATABASE.pages = ` ABOUT BREF : We started {*Grim Grains*} to teach ourselves how to cook. This blog, which now doubles as a travel diary, helps measure our progress, while giving us another creative output. We cook and travel, and adapt to the local produce whenever possible. All of the recipes we make are plant-based, and tree-nut free. LONG - * HundredRabbits - & This website showcases our favourite creations, along with handdraw illustrations for {{each ingredient|ingredients-list}}. & We are {{Rekka Bellum|http://kokorobot.ca/}}, an illustrator, and {{Devine Lu Linvega|http://xxiivv.com}}, an artist/musician, living on a small sailboat somewhere on the shores of the Pacific Ocean. Hundredrabbits is the name of our {{floating studio|http://100r.co}}, we make {{games|https://100r.co/pages/games.html}}, {{tools|https://100r.co/pages/tools.html}} and delicious recipes as we travel. - & You can contact us on our twitter {{@grimgrains|http://twitter.com/grimgrains}}, or by email at rekkabell at gmail dot com. + & This website showcases our favourite creations, along with hand-draw illustrations for {{each ingredient|ingredients-list}}. You can contact us on our twitter {{@grimgrains|http://twitter.com/grimgrains}}, or by email at rekkabell at gmail dot com. * Copyright policy & You may adapt our recipes, but a link back or mention would be nice :). * Disclaimer & The content of grimgrains.com, unless stated otherwise, is © hundredrabbits. All rights reserved. Photographs, drawings or text should not be used, published, reprinted or modified without our permission. & All recipes featured on grimgrains.com are our own, unless stated otherwise. The information is for food enthusiasts like ourselves, we do not claim to be all-knowing. Nor are we health professionals. Our views are our own, we encourage openness and curiosity whenever possible. * Privacy statement - & We reserve the right to alter the blog at our own discretion. - & Words addressed to us in private will not be shared, nor will we use any of it in future publications. + & We reserve the right to alter the blog at our own discretion. Words addressed to us in private will not be shared, nor will we use any of it in future publications. TOOLS BREF : Entering a store, with the goal of purchasing kitchenware can be a dizzying experience. There are many choices, but few are worth your money and attention. An ideal kitchen will have as few items as possible, be composed of things that make you happy and that you chose with purpose. With this in mind, for a tool to be awarded a place in your home, it needs to be effective and versatile. I made this list of notes on what to look for in a tool, based on experience and research: LONG + % pages/tools.jpg & {*Durability*}: Choose a material that will last, of finer grade, or that can be composted. & {*Simplicity*}: Prioritize unibody tools, the fewer parts the better. Opting for non-electric is important for that same reason. Less prone to breakage. & {*Multi-functional*}: Having too many tools that have a single function, adds clutter to our home and in our minds. & Note: If you look at the photo, you can see that my kitchenware doesn't have all the features listed below. That's because this list is an ideal, a study of what an optimal toolset would be. It may not be realistic to you, and that's okay. In the end, you've got to work with what you have. The resulting food matters {*more*} than the tools you use. - % pages/tools.jpg * Cutting boards & {*Material*}: Opt for a maple or bamboo hardwood cutting board. Avoid plastic. Contrary to popular belief, it is not more sanitary and can harbour a lot of bacteria. A knife-scarred plastic surface is difficult to disinfect, and studies have shown that washing the board – whether by hand or with a dishwasher – was not enough to kill lingering bacteria. & Wood doesn't scar as easily, and is the preferred material. After cleaning, it must be allowed to dry thoroughly. @@ -71,4 +68,4 @@ INGREDIENTS LONG & Select any item below to view recipes in which they were used and to find more information on them! -`- \ No newline at end of file +` diff --git a/scripts/database/recipes.js b/scripts/database/recipes.js @@ -1,5 +1,35 @@ DATABASE.recipes = ` +SEITAN + DATE : 2019-01-08 + TAGS + basic + TIME : 60 + SERV : 1 paddies + DESC + & A good supplement to other meals. + INST + Pancake + - Blend {#1/2 cup#} of {{spinach}} with {#1/2 cup#} of {{water}} until smooth. Set aside. + - In a bowl, whisk together {#1/2 cup#} of {{spelt flour}}, {#1 tsp#} {{sesame oil}} and the blended spinach. + - Heat a large pan with {#1 tsp#} of {{sesame oil}} over {_medium heat_}. + - Put the chopped {{scallions}} in the pan and pour the batter onto it. With a spatula, press down on the pancake to flatten it out. + - Cook for {#3-4 minutes#} until the sides come off the pan and the bottom is cooked. Flip, cook for a a few extra minutes and transfer to a plate. + - Cut it into pieces to make it easier to dip into the sauce! + Sauce + - Put the sauce ingredients together in a bowl and mix! + INGR + Main + Glutinous flour : 1/2 cup + chickpea flour : 1/4 cup + soy sauce : 1 tbsp + Water : 1/3 cup + Broth + garlic : 1 clove + ginger root : 1 clove + vegetable bouillon : 1 cube + yellow onion : half + SPINACH PAJEON DATE : 2014-08-19 TAGS @@ -2220,4 +2250,4 @@ CRACKERS Black sesame seeds : 1 tbsp Flax seeds : 1 tbsp -`- \ No newline at end of file +` diff --git a/scripts/graph.js b/scripts/graph.js @@ -1,52 +1,57 @@ -function graph() -{ - Ø("query").create({x:2,y:4},QueryNode) - - Ø("model").mesh({x:6,y:0},[ - Ø("router").create({x:5,y:2},RouterNode), - Ø("database").create({x:5,y:8},DatabaseNode), - Ø("recipes").create({x:2,y:14},IndentalNode), - Ø("ingredients").create({x:5,y:14},IndentalNode), - Ø("pages").create({x:8,y:14},IndentalNode), +function graph () { + Ø('query').create({ x: 2, y: 4 }, QueryNode) + + Ø('model').mesh({ x: 6, y: 0 }, [ + Ø('router').create({ x: 5, y: 2 }, RouterNode), + Ø('database').create({ x: 5, y: 8 }, DatabaseNode), + Ø('recipes').create({ x: 2, y: 14 }, IndentalNode), + Ø('ingredients').create({ x: 5, y: 14 }, IndentalNode), + Ø('pages').create({ x: 8, y: 14 }, IndentalNode) ]) - Ø("assoc").mesh({x:19,y:0},[ - Ø("template").create({x:5,y:2},TemplateNode), - Ø("page").create({x:2,y:8},PageTemplate), - Ø("search").create({x:5,y:14},SearchTemplate), - Ø("home").create({x:2,y:14},HomeTemplate), - Ø("recipe").create({x:5,y:8},RecipeTemplate), - Ø("ingredient").create({x:8,y:8},IngredientTemplate), + Ø('assoc').mesh({ x: 19, y: 0 }, [ + Ø('template').create({ x: 5, y: 2 }, TemplateNode), + Ø('page').create({ x: 2, y: 8 }, PageTemplate), + Ø('search').create({ x: 5, y: 14 }, SearchTemplate), + Ø('home').create({ x: 2, y: 14 }, HomeTemplate), + Ø('recipe').create({ x: 5, y: 8 }, RecipeTemplate), + Ø('ingredient').create({ x: 8, y: 8 }, IngredientTemplate) ]) - Ø("client").mesh({x:32,y:0},[ - Ø("document").create({x:2,y:2},DocumentNode), - Ø("view").create({x:2,y:6},DomNode), - Ø("header").create({x:2,y:11},DomNode), - Ø("logo").create({x:2,y:16},DomNode,"wr",`{{<img src='media/interface/logo.png'/>|Home}}<list><a class="local home" onclick="Ø('query').bang('Home')">Home</a> • <a class="local about" onclick="Ø('query').bang('About')">About</a> • <a class="local tools" onclick="Ø('query').bang('Tools')">Tools</a> • <a href='http://twitter.com/grimgrains' target='_blank'>Twitter</a></list>`.to_markup()), - Ø("menu").create({x:6,y:16},DomNode,"list"), - Ø("core").create({x:10,y:11},DomNode), - Ø("content").create({x:10,y:16},DomNode), - Ø("related").create({x:14,y:16},DomNode,"list"), - Ø("footer").create({x:6,y:11},DomNode,"wr",`<a onclick="Ø('query').bang('about')">Grimgrains</a> © 2014—2018<br/><a href='http://100r.co/' target='_blank'>Hundred Rabbits</a>`), + Ø('client').mesh({ x: 32, y: 0 }, [ + Ø('document').create({ x: 2, y: 2 }, DocumentNode), + Ø('view').create({ x: 2, y: 6 }, DomNode), + Ø('header').create({ x: 2, y: 11 }, DomNode), + Ø('logo').create({ x: 2, y: 16 }, DomNode, 'wr', ` + <a href='index.html'><img src='media/interface/logo.png'/></a> + <ul> + <li><a class="local home" onclick="Ø('query').bang('Home')">Home</a></li> + <li><a class="local about" onclick="Ø('query').bang('About')">About</a></li> + <li><a class="local tools" onclick="Ø('query').bang('Tools')">Tools</a></li> + <li><a href='http://twitter.com/grimgrains' target='_blank'>Twitter</a></li> + </ul>`.to_markup()), + Ø('core').create({ x: 10, y: 11 }, DomNode), + Ø('content').create({ x: 10, y: 16 }, DomNode), + Ø('related').create({ x: 14, y: 16 }, DomNode, 'ul'), + Ø('footer').create({ x: 6, y: 11 }, DomNode, 'wr', `<a onclick="Ø('query').bang('about')">Grimgrains</a> © 2014—2018<br/><a href='http://100r.co/' target='_blank'>Hundred Rabbits</a>`) ]) // Model - Ø("router").syphon("database") - Ø("database").syphon(["recipes","ingredients","pages"]) + Ø('router').syphon('database') + Ø('database').syphon(['recipes', 'ingredients', 'pages']) // Assoc - Ø("template").syphon(["recipe","ingredient","page"]) - Ø("page").syphon(["home","search"]) + Ø('template').syphon(['recipe', 'ingredient', 'page']) + Ø('page').syphon(['home', 'search']) - Ø("template").connect(["view","document"]) - Ø("view").bind(["header","core","footer"]) - Ø("core").bind(["content","related"]) - Ø("header").bind(["logo","menu"]) + Ø('template').connect(['view', 'document']) + Ø('view').bind(['header', 'core', 'footer']) + Ø('core').bind(['content', 'related']) + Ø('header').bind(['logo']) - Ø("query").connect("router") - Ø("router").connect("template") + Ø('query').connect('router') + Ø('router').connect('template') - Ø("query").bang() + Ø('query').bang() } diff --git a/scripts/lib/riven.graph.js b/scripts/lib/riven.graph.js @@ -1,250 +1,229 @@ -function Riven_Graph() -{ - Riven.call(this); +function Riven_Graph () { + Riven.call(this) var GRID_SIZE = 20 - this.el = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this.el = document.createElementNS('http://www.w3.org/2000/svg', 'svg') document.body.appendChild(this.el) - - this.graph = function() - { - var html = ""; - for(id in this.network){ - var node = this.network[id]; - html += draw_routes(node); + + this.graph = function () { + var html = '' + for (id in this.network) { + var node = this.network[id] + html += draw_routes(node) } - for(id in this.network){ - var node = this.network[id]; - html += draw_node(node); + for (id in this.network) { + var node = this.network[id] + html += draw_node(node) } - this.el.innerHTML = html; + this.el.innerHTML = html } - function draw_routes(node) - { - var html = ""; - for(id in node.ports){ + function draw_routes (node) { + var html = '' + for (id in node.ports) { var port = node.ports[id] - var pos = port ? get_port_position(port) : {x:0,y:0} - for(route_id in port.routes){ - var route = port.routes[route_id]; - if(!route){ continue; } - html += route ? draw_connection(port,route) : "" + var pos = port ? get_port_position(port) : { x: 0, y: 0 } + for (route_id in port.routes) { + var route = port.routes[route_id] + if (!route) { continue } + html += route ? draw_connection(port, route) : '' } } return `<g id='routes'>${html}</g>` } - function draw_node(node) - { - var rect = get_rect(node); + function draw_node (node) { + var rect = get_rect(node) return ` <g class='node ${node.is_mesh ? 'mesh' : ''}' id='node_${node.id}'> - <rect rx='2' ry='2' x=${rect.x} y=${rect.y-(GRID_SIZE/2)} width="${rect.w}" height="${rect.h}" class='${node.children.length == 0 ? "fill" : ""}'/> - <text x="${rect.x+(rect.w/2)}" y="${rect.y+rect.h+(GRID_SIZE/2)}">${node.label}</text> + <rect rx='2' ry='2' x=${rect.x} y=${rect.y - (GRID_SIZE / 2)} width="${rect.w}" height="${rect.h}" class='${node.children.length == 0 ? 'fill' : ''}'/> + <text x="${rect.x + (rect.w / 2)}" y="${rect.y + rect.h + (GRID_SIZE / 2)}">${node.label}</text> ${draw_ports(node)} ${draw_glyph(node)} </g>` } - function draw_ports(node) - { - var html = ""; - for(id in node.ports){ - html += draw_port(node.ports[id]); + function draw_ports (node) { + var html = '' + for (id in node.ports) { + html += draw_port(node.ports[id]) } return html } - function draw_glyph(node) - { - var rect = get_rect(node); - return !node.is_mesh && node.glyph ? `<path class='glyph' transform="translate(${rect.x+(GRID_SIZE/4)},${rect.y-(GRID_SIZE/4)}) scale(0.1)" d='${node.glyph}'/>` : "" + function draw_glyph (node) { + var rect = get_rect(node) + return !node.is_mesh && node.glyph ? `<path class='glyph' transform="translate(${rect.x + (GRID_SIZE / 4)},${rect.y - (GRID_SIZE / 4)}) scale(0.1)" d='${node.glyph}'/>` : '' } - function draw_port(port) - { - var pos = port ? get_port_position(port) : {x:0,y:0} - return `<g id='${port.host.id}_port_${port.id}'>${(port.type == PORT_TYPES.request || port.type == PORT_TYPES.answer)? `<path d='${draw_diamond(pos)}' class='port ${port.type} ${port.host.ports[id] && port.host.ports[id].route ? "route" : ""}' />` : `<circle cx='${pos.x}' cy="${pos.y}" r="${parseInt(GRID_SIZE/6)}" class='port ${port.type} ${port.host.ports[id] && port.host.ports[id].route ? "route" : ""}'/>`}</g>` + function draw_port (port) { + var pos = port ? get_port_position(port) : { x: 0, y: 0 } + return `<g id='${port.host.id}_port_${port.id}'>${(port.type == PORT_TYPES.request || port.type == PORT_TYPES.answer) ? `<path d='${draw_diamond(pos)}' class='port ${port.type} ${port.host.ports[id] && port.host.ports[id].route ? 'route' : ''}' />` : `<circle cx='${pos.x}' cy="${pos.y}" r="${parseInt(GRID_SIZE / 6)}" class='port ${port.type} ${port.host.ports[id] && port.host.ports[id].route ? 'route' : ''}'/>`}</g>` } - function draw_connection(a,b,type) - { - if(is_bidirectional(a.host,b.host)){ - return a.type != PORT_TYPES.output ? draw_connection_bidirectional(a,b) : "" + function draw_connection (a, b, type) { + if (is_bidirectional(a.host, b.host)) { + return a.type != PORT_TYPES.output ? draw_connection_bidirectional(a, b) : '' } - - return a.type == PORT_TYPES.output ? draw_connection_output(a,b) : draw_connection_request(a,b) + + return a.type == PORT_TYPES.output ? draw_connection_output(a, b) : draw_connection_request(a, b) } - function is_bidirectional(a,b) - { - for(id in a.ports.output.routes){ + function is_bidirectional (a, b) { + for (id in a.ports.output.routes) { var route_a = a.ports.output.routes[id] - for(id in a.ports.request.routes){ + for (id in a.ports.request.routes) { var route_b = a.ports.request.routes[id] - if(route_a.host.id == route_b.host.id){ - return true; + if (route_a.host.id == route_b.host.id) { + return true } } } return false } - function draw_connection_output(a,b) - { + function draw_connection_output (a, b) { var pos_a = get_port_position(a) var pos_b = get_port_position(b) - var pos_m = middle(pos_a,pos_b) - var pos_c1 = {x:(pos_m.x+(pos_a.x+GRID_SIZE))/2,y:pos_a.y} - var pos_c2 = {x:(pos_m.x+(pos_b.x-GRID_SIZE))/2,y:pos_b.y} + var pos_m = middle(pos_a, pos_b) + var pos_c1 = { x: (pos_m.x + (pos_a.x + GRID_SIZE)) / 2, y: pos_a.y } + var pos_c2 = { x: (pos_m.x + (pos_b.x - GRID_SIZE)) / 2, y: pos_b.y } - var path = "" + var path = '' - path += `M${pos_a.x},${pos_a.y} L${pos_a.x+GRID_SIZE},${pos_a.y} ` + path += `M${pos_a.x},${pos_a.y} L${pos_a.x + GRID_SIZE},${pos_a.y} ` path += `Q${pos_c1.x},${pos_c1.y} ${pos_m.x},${pos_m.y} ` - path += `Q ${pos_c2.x},${pos_c2.y} ${pos_b.x-GRID_SIZE},${pos_b.y}` + path += `Q ${pos_c2.x},${pos_c2.y} ${pos_b.x - GRID_SIZE},${pos_b.y}` path += `L${pos_b.x},${pos_b.y}` return `<path d="${path}" class='route output'/> <circle cx='${pos_m.x}' cy='${pos_m.y}' r='2' fill='white'></circle>` } - function draw_connection_request(a,b) - { + function draw_connection_request (a, b) { var pos_a = get_port_position(a) var pos_b = get_port_position(b) - var pos_m = middle(pos_a,pos_b) - var pos_c1 = {x:pos_a.x,y:(pos_m.y+(pos_a.y+GRID_SIZE))/2} - var pos_c2 = {x:pos_b.x,y:(pos_m.y+(pos_b.y-GRID_SIZE))/2} + var pos_m = middle(pos_a, pos_b) + var pos_c1 = { x: pos_a.x, y: (pos_m.y + (pos_a.y + GRID_SIZE)) / 2 } + var pos_c2 = { x: pos_b.x, y: (pos_m.y + (pos_b.y - GRID_SIZE)) / 2 } - var path = "" + var path = '' - path += `M${pos_a.x},${pos_a.y} L${pos_a.x},${pos_a.y+GRID_SIZE} ` + path += `M${pos_a.x},${pos_a.y} L${pos_a.x},${pos_a.y + GRID_SIZE} ` path += `Q${pos_c1.x},${pos_c1.y} ${pos_m.x},${pos_m.y} ` - path += `Q ${pos_c2.x},${pos_c2.y} ${pos_b.x},${pos_b.y-GRID_SIZE}` + path += `Q ${pos_c2.x},${pos_c2.y} ${pos_b.x},${pos_b.y - GRID_SIZE}` path += `L${pos_b.x},${pos_b.y}` return `<path d="${path}" class='route request'/> <circle cx='${pos_m.x}' cy='${pos_m.y}' r='2' fill='white'></circle>` } - function draw_connection_bidirectional(a,b) - { + function draw_connection_bidirectional (a, b) { var pos_a = get_port_position(a) var pos_b = get_port_position(b) - var pos_m = middle(pos_a,pos_b) - var pos_c1 = {x:pos_a.x,y:(pos_m.y+(pos_a.y+GRID_SIZE))/2} - var pos_c2 = {x:pos_b.x,y:(pos_m.y+(pos_b.y-GRID_SIZE))/2} + var pos_m = middle(pos_a, pos_b) + var pos_c1 = { x: pos_a.x, y: (pos_m.y + (pos_a.y + GRID_SIZE)) / 2 } + var pos_c2 = { x: pos_b.x, y: (pos_m.y + (pos_b.y - GRID_SIZE)) / 2 } - var path = "" + var path = '' - path += `M${pos_a.x},${pos_a.y} L${pos_a.x},${pos_a.y+GRID_SIZE} ` + path += `M${pos_a.x},${pos_a.y} L${pos_a.x},${pos_a.y + GRID_SIZE} ` path += `L${pos_a.x},${pos_m.y} L${pos_b.x},${pos_m.y}` - path += `L${pos_b.x},${pos_b.y-GRID_SIZE} L${pos_b.x},${pos_b.y}` + path += `L${pos_b.x},${pos_b.y - GRID_SIZE} L${pos_b.x},${pos_b.y}` return `<path d="${path}" class='route bidirectional'/>` } - - function draw_diamond(pos) - { - var r = GRID_SIZE/6 - return `M${pos.x-(r)},${pos.y} L${pos.x},${pos.y-(r)} L${pos.x+(r)},${pos.y} L${pos.x},${pos.y+(r)} Z` + + function draw_diamond (pos) { + var r = GRID_SIZE / 6 + return `M${pos.x - (r)},${pos.y} L${pos.x},${pos.y - (r)} L${pos.x + (r)},${pos.y} L${pos.x},${pos.y + (r)} Z` } - function get_port_position(port) - { + function get_port_position (port) { var rect = get_rect(port.host) - var offset = {x:0,y:0} - if(port.type == PORT_TYPES.output){ - offset = {x:GRID_SIZE*2,y:GRID_SIZE/2} - } - else if(port.type == PORT_TYPES.input){ - offset = {x:0,y:GRID_SIZE/2} - } - else if(port.type == PORT_TYPES.answer){ - offset = {x:GRID_SIZE,y:-GRID_SIZE*0.5} - } - else if(port.type == PORT_TYPES.request){ - offset = {x:GRID_SIZE,y:GRID_SIZE*1.5} + var offset = { x: 0, y: 0 } + if (port.type == PORT_TYPES.output) { + offset = { x: GRID_SIZE * 2, y: GRID_SIZE / 2 } + } else if (port.type == PORT_TYPES.input) { + offset = { x: 0, y: GRID_SIZE / 2 } + } else if (port.type == PORT_TYPES.answer) { + offset = { x: GRID_SIZE, y: -GRID_SIZE * 0.5 } + } else if (port.type == PORT_TYPES.request) { + offset = { x: GRID_SIZE, y: GRID_SIZE * 1.5 } } - return {x:rect.x+offset.x,y:rect.y+offset.y} + return { x: rect.x + offset.x, y: rect.y + offset.y } } - function get_rect(node) - { + function get_rect (node) { var rect = node.rect - var x = node.rect.x * GRID_SIZE; - var y = node.rect.y * GRID_SIZE; - var w = node.rect.w * GRID_SIZE; - var h = node.rect.h * GRID_SIZE; - - if(node.parent){ - var offset = get_rect(node.parent); - x += offset.x; - y += offset.y; + var x = node.rect.x * GRID_SIZE + var y = node.rect.y * GRID_SIZE + var w = node.rect.w * GRID_SIZE + var h = node.rect.h * GRID_SIZE + + if (node.parent) { + var offset = get_rect(node.parent) + x += offset.x + y += offset.y } - return {x:x,y:y,w:w,h:h} + return { x: x, y: y, w: w, h: h } } - function distance(a,b) - { - return Math.sqrt( (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) ); + function distance (a, b) { + return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) } - function diagonal(a,b) - { + function diagonal (a, b) { return a.x == b.x || a.y == b.y || a.y - a.x == b.y - b.x || b.y - a.x == a.y - b.x } - function middle(a,b) - { - return {x:(a.x+b.x)/2,y:(a.y+b.y)/2} + function middle (a, b) { + return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 } } // Cursor this.cursor = { - host:null, - el:document.createElement("cursor"), - pos:{x:0,y:0}, - offset:{x:0,y:0}, - origin:null, - install: function(host){ - this.host = host; + host: null, + el: document.createElement('cursor'), + pos: { x: 0, y: 0 }, + offset: { x: 0, y: 0 }, + origin: null, + install: function (host) { + this.host = host document.body.appendChild(this.el) - document.addEventListener('mousedown',(e)=>{ this.touch({x:e.clientX,y:e.clientY},true); e.preventDefault(); }); - document.addEventListener('mousemove',(e)=>{ this.touch({x:e.clientX,y:e.clientY},false); e.preventDefault(); }); - document.addEventListener('mouseup', (e)=>{ this.touch({x:e.clientX,y:e.clientY}); e.preventDefault(); }); + document.addEventListener('mousedown', (e) => { this.touch({ x: e.clientX, y: e.clientY }, true); e.preventDefault() }) + document.addEventListener('mousemove', (e) => { this.touch({ x: e.clientX, y: e.clientY }, false); e.preventDefault() }) + document.addEventListener('mouseup', (e) => { this.touch({ x: e.clientX, y: e.clientY }); e.preventDefault() }) }, - update: function(){ - this.host.el.style.left = `${parseInt(this.offset.x)}px`; - this.host.el.style.top = `${parseInt(this.offset.y)}px`; - document.body.style.backgroundPosition = `${parseInt(this.offset.x/2)}px ${parseInt(this.offset.y/2)}px`; + update: function () { + this.host.el.style.left = `${parseInt(this.offset.x)}px` + this.host.el.style.top = `${parseInt(this.offset.y)}px` + document.body.style.backgroundPosition = `${parseInt(this.offset.x / 2)}px ${parseInt(this.offset.y / 2)}px` }, - touch: function(pos,click = null){ - if(click == true){ - this.origin = pos; - return; + touch: function (pos, click = null) { + if (click == true) { + this.origin = pos + return } - if(this.origin){ - this.offset.x += (pos.x - this.origin.x)/2; - this.offset.y += (pos.y - this.origin.y)/2; - this.update(); - this.origin = pos; + if (this.origin) { + this.offset.x += (pos.x - this.origin.x) / 2 + this.offset.y += (pos.y - this.origin.y) / 2 + this.update() + this.origin = pos } - if(click == null){ - this.origin = null; - return; + if (click == null) { + this.origin = null + return } - this.pos = pos; + this.pos = pos }, - magnet: function(val){ - return (parseInt(val/GRID_SIZE)*GRID_SIZE)+(GRID_SIZE/2); + magnet: function (val) { + return (parseInt(val / GRID_SIZE) * GRID_SIZE) + (GRID_SIZE / 2) } } - this.cursor.install(this); + this.cursor.install(this) } diff --git a/scripts/lib/riven.js b/scripts/lib/riven.js @@ -1,163 +1,144 @@ // "Don't forget, the portal combination's in my journal."" — Catherine -function Riven() -{ +function Riven () { this.network = {} } // QUERY -function Ø(s,network = RIVEN.network) -{ - var id = s.toLowerCase(); - if(id.indexOf(" ") > -1){ - var node_id = id.split(" ")[0]; - var port_id = id.split(" ")[1]; - return network[node_id] && network[node_id].ports[port_id] ? network[node_id].ports[port_id] : null; - } - else if(network[id]){ - return network[id]; - } - else{ - return new Node(id); +function Ø (s, network = RIVEN.network) { + var id = s.toLowerCase() + if (id.indexOf(' ') > -1) { + var node_id = id.split(' ')[0] + var port_id = id.split(' ')[1] + return network[node_id] && network[node_id].ports[port_id] ? network[node_id].ports[port_id] : null + } else if (network[id]) { + return network[id] + } else { + return new Node(id) } } // NODE -function Node(id,rect={x:0,y:0,w:2,h:2}) -{ - this.id = id; +function Node (id, rect = { x: 0, y: 0, w: 2, h: 2 }) { + this.id = id this.ports = {} - this.rect = rect; - this.parent = null; - this.children = []; - this.label = id; - - this.setup = function() - { - this.ports.input = new Port(this,"in",PORT_TYPES.input) - this.ports.output = new Port(this,"out",PORT_TYPES.output) - this.ports.answer = new Port(this,"answer",PORT_TYPES.answer) - this.ports.request = new Port(this,"request",PORT_TYPES.request) + this.rect = rect + this.parent = null + this.children = [] + this.label = id + + this.setup = function () { + this.ports.input = new Port(this, 'in', PORT_TYPES.input) + this.ports.output = new Port(this, 'out', PORT_TYPES.output) + this.ports.answer = new Port(this, 'answer', PORT_TYPES.answer) + this.ports.request = new Port(this, 'request', PORT_TYPES.request) } - this.create = function(pos = {x:0,y:0},type = Node,...params) - { - var node = new type(this.id,rect,...params) + this.create = function (pos = { x: 0, y: 0 }, type = Node, ...params) { + var node = new type(this.id, rect, ...params) this.rect.x = pos.x this.rect.y = pos.y - node.setup(); + node.setup() RIVEN.network[node.id] = node return node } - this.mesh = function(pos,n) - { - var node = new Mesh(this.id,pos) + this.mesh = function (pos, n) { + var node = new Mesh(this.id, pos) node.rect.x = pos.x node.rect.y = pos.y - node.setup(); + node.setup() RIVEN.network[node.id] = node - if(n instanceof Array){ - for(id in n){ - n[id].parent = node; - node.children.push(n[id]); - node.update(); + if (n instanceof Array) { + for (id in n) { + n[id].parent = node + node.children.push(n[id]) + node.update() } + } else { + n.parent = node + node.children.push(n) + node.update() } - else{ - n.parent = node; - node.children.push(n); - node.update(); - } - return node; + return node } // Connect - this.connect = function(q,type = ROUTE_TYPES.output) - { - if(q instanceof Array){ - for(id in q){ - this.connect(q[id],type) + this.connect = function (q, type = ROUTE_TYPES.output) { + if (q instanceof Array) { + for (id in q) { + this.connect(q[id], type) } - } - else{ - this.ports[type == ROUTE_TYPES.request ? "request" : "output"].connect(`${q} ${type == ROUTE_TYPES.request ? "answer" : "input"}`,type); + } else { + this.ports[type == ROUTE_TYPES.request ? 'request' : 'output'].connect(`${q} ${type == ROUTE_TYPES.request ? 'answer' : 'input'}`, type) } } - this.syphon = function(q) - { - this.connect(q,ROUTE_TYPES.request) + this.syphon = function (q) { + this.connect(q, ROUTE_TYPES.request) } - this.bind = function(q) - { + this.bind = function (q) { this.connect(q) this.syphon(q) } // Target - this.signal = function(target) - { - for(port_id in this.ports){ + this.signal = function (target) { + for (port_id in this.ports) { var port = this.ports[port_id] - for(route_id in port.routes){ - var route = port.routes[route_id]; - if(!route || !route.host || route.host.id != target.toLowerCase()){ continue; } + for (route_id in port.routes) { + var route = port.routes[route_id] + if (!route || !route.host || route.host.id != target.toLowerCase()) { continue } return route.host } } - return null; + return null } // SEND/RECEIVE - this.send = function(payload) - { - for(route_id in this.ports.output.routes){ - var route = this.ports.output.routes[route_id]; - if(!route){ continue; } + this.send = function (payload) { + for (route_id in this.ports.output.routes) { + var route = this.ports.output.routes[route_id] + if (!route) { continue } route.host.receive(payload) } } - - this.receive = function(q) - { + + this.receive = function (q) { var port = this.ports.output - for(route_id in port.routes){ - var route = port.routes[route_id]; - if(route){ - route.host.receive(q) + for (route_id in port.routes) { + var route = port.routes[route_id] + if (route) { + route.host.receive(q) } } } - this.bang = function() - { + this.bang = function () { this.send(true) } // REQUEST/ANSWER - this.answer = function(q) - { + this.answer = function (q) { return this.request(q) } - this.request = function(q) - { - var payload = {}; - for(route_id in this.ports.request.routes){ - var route = this.ports.request.routes[route_id]; - if(!route){ continue; } + this.request = function (q) { + var payload = {} + for (route_id in this.ports.request.routes) { + var route = this.ports.request.routes[route_id] + if (!route) { continue } var answer = route.host.answer(q) - if(!answer){ continue; } + if (!answer) { continue } payload[route.host.id] = answer } return payload @@ -165,58 +146,54 @@ function Node(id,rect={x:0,y:0,w:2,h:2}) // PORT - function Port(host,id,type = PORT_TYPES.default) - { - this.host = host; - this.id = id; - this.type = type; - this.routes = []; + function Port (host, id, type = PORT_TYPES.default) { + this.host = host + this.id = id + this.type = type + this.routes = [] - this.connect = function(b,type = "transit") - { + this.connect = function (b, type = 'transit') { this.routes.push(Ø(b)) } } // MESH - function Mesh(id,rect) - { - Node.call(this,id,rect); + function Mesh (id, rect) { + Node.call(this, id, rect) - this.is_mesh = true; + this.is_mesh = true - this.setup = function(){} + this.setup = function () {} - this.update = function() - { - var bounds = {x:0,y:0}; - for(id in this.children){ - var node = this.children[id]; + this.update = function () { + var bounds = { x: 0, y: 0 } + for (id in this.children) { + var node = this.children[id] bounds.x = node.rect.x > bounds.x ? node.rect.x : bounds.x bounds.y = node.rect.y > bounds.y ? node.rect.y : bounds.y } - this.rect.w = bounds.x+4; - this.rect.h = bounds.y+5; + this.rect.w = bounds.x + 4 + this.rect.h = bounds.y + 5 } } } -var PORT_TYPES = {default:"default",input:"input",output:"output",request:"request",answer:"answer"} -var ROUTE_TYPES = {default:"default",request:"request"} +var PORT_TYPES = { default: 'default', input: 'input', output: 'output', request: 'request', answer: 'answer' } +var ROUTE_TYPES = { default: 'default', request: 'request' } var NODE_GLYPHS = { - default: "M150,60 L150,60 L60,150 L150,240 L240,150 Z", - router:"M60,120 L60,120 L150,120 L240,60 M60,150 L60,150 L240,150 M60,180 L60,180 L150,180 L240,240", - parser:"M60,60 L60,60 L240,60 M120,120 A30,30 0 0,1 150,150 M150,150 A30,30 0 0,0 180,180 M180,180 L180,180 L240,180 M120,120 L120,120 L60,120 M60,240 L60,240 L240,240 M240,120 L240,120 L180,120 M60,180 L60,180 L120,180", - entry:"M60,150 L60,150 L240,150 L240,150 L150,240 M150,60 L150,60 L240,150", - bang:"M150,60 L150,60 L150,180 M150,240 L150,240 L150,240", - value:"M60,60 L60,60 L240,60 L240,240 L60,240 Z M60,150 L60,150 L240,150", - equal:"M60,60 L60,60 L240,60 M60,120 L60,120 L240,120 M60,180 L60,180 L240,180 M60,240 L60,240 L240,240", - render:"M60,60 L60,60 L240,60 L240,240 L60,240 Z M240,150 L240,150 L150,150 L150,240", - database:"M60,60 L60,60 L240,60 L240,240 L60,240 Z M120,120 L120,120 L180,120 M120,180 L120,180 L180,180 M120,150 L120,150 L180,150", - cache:"M60,60 L60,60 L240,60 L240,240 L60,240 Z", - builder:"M60,60 L60,60 L150,120 L240,120 M60,150 L60,150 L240,150 M60,240 L60,240 L150,180 L240,180", - selector:"M90,60 L90,60 L60,60 L60,90 M60,210 L60,210 L60,240 L90,240 M210,240 L210,240 L240,240 L240,210 M240,90 L240,90 L240,60 L210,60", - dom: "M150,60 L150,60 L60,150 L150,240 L240,150 Z", - template: "M150,60 L150,60 L240,150 L150,240 L60,150 Z M120,150 L120,150 L180,150 M150,120 L150,120 L150,180", -}- \ No newline at end of file + default: 'M150,60 L150,60 L60,150 L150,240 L240,150 Z', + router: 'M60,120 L60,120 L150,120 L240,60 M60,150 L60,150 L240,150 M60,180 L60,180 L150,180 L240,240', + parser: 'M60,60 L60,60 L240,60 M120,120 A30,30 0 0,1 150,150 M150,150 A30,30 0 0,0 180,180 M180,180 L180,180 L240,180 M120,120 L120,120 L60,120 M60,240 L60,240 L240,240 M240,120 L240,120 L180,120 M60,180 L60,180 L120,180', + entry: 'M60,150 L60,150 L240,150 L240,150 L150,240 M150,60 L150,60 L240,150', + bang: 'M150,60 L150,60 L150,180 M150,240 L150,240 L150,240', + value: 'M60,60 L60,60 L240,60 L240,240 L60,240 Z M60,150 L60,150 L240,150', + equal: 'M60,60 L60,60 L240,60 M60,120 L60,120 L240,120 M60,180 L60,180 L240,180 M60,240 L60,240 L240,240', + render: 'M60,60 L60,60 L240,60 L240,240 L60,240 Z M240,150 L240,150 L150,150 L150,240', + database: 'M60,60 L60,60 L240,60 L240,240 L60,240 Z M120,120 L120,120 L180,120 M120,180 L120,180 L180,180 M120,150 L120,150 L180,150', + cache: 'M60,60 L60,60 L240,60 L240,240 L60,240 Z', + builder: 'M60,60 L60,60 L150,120 L240,120 M60,150 L60,150 L240,150 M60,240 L60,240 L150,180 L240,180', + selector: 'M90,60 L90,60 L60,60 L60,90 M60,210 L60,210 L60,240 L90,240 M210,240 L210,240 L240,240 L240,210 M240,90 L240,90 L240,60 L210,60', + dom: 'M150,60 L150,60 L60,150 L150,240 L240,150 Z', + template: 'M150,60 L150,60 L240,150 L150,240 L60,150 Z M120,150 L120,150 L180,150 M150,120 L150,120 L150,180' +} diff --git a/scripts/lib/runic.js b/scripts/lib/runic.js @@ -1,157 +1,144 @@ -function Runic(raw) -{ - this.raw = raw; +function Runic (raw) { + this.raw = raw this.runes = { - "&":{glyph:"&",tag:"p",class:""}, - "~":{glyph:"~",tag:"list",sub:"ln",class:"parent",stash:true}, - "-":{glyph:"-",tag:"list",sub:"ln",class:"",stash:true}, - "!":{glyph:"!",tag:"table",sub:"tr",wrap:"th",class:"outline",stash:true}, - "|":{glyph:"|",tag:"table",sub:"tr",wrap:"td",class:"outline",stash:true}, - "#":{glyph:"#",tag:"code",sub:"ln",class:"",stash:true}, - "%":{glyph:"%"}, - "?":{glyph:"?",tag:"note",class:""}, - ":":{glyph:":",tag:"info",class:""}, - "*":{glyph:"*",tag:"h2",class:""}, - "=":{glyph:"=",tag:"h3",class:""}, - "+":{glyph:"+",tag:"hs",class:""}, - ">":{glyph:">",tag:"",class:""}, - "$":{glyph:">",tag:"",class:""} + '&': { glyph: '&', tag: 'p', class: '' }, + '~': { glyph: '~', tag: 'ul', sub: 'li', class: 'parent', stash: true }, + '-': { glyph: '-', tag: 'ul', sub: 'li', class: '', stash: true }, + '!': { glyph: '!', tag: 'table', sub: 'tr', wrap: 'th', class: 'outline', stash: true }, + '|': { glyph: '|', tag: 'table', sub: 'tr', wrap: 'td', class: 'outline', stash: true }, + '•': { glyph: '•', tag: 'ul', sub: 'li', class: 'bullet', stash: true }, + '#': { glyph: '#', tag: 'code', sub: 'ln', class: '', stash: true }, + '%': { glyph: '%' }, + '?': { glyph: '?', tag: 'note', class: '' }, + ':': { glyph: ':', tag: 'info', class: '' }, + '*': { glyph: '*', tag: 'h2', class: '' }, + '=': { glyph: '=', tag: 'h3', class: '' }, + '+': { glyph: '+', tag: 'hs', class: '' }, + '>': { glyph: '>', tag: '', class: '' }, + '$': { glyph: '>', tag: '', class: '' } } this.stash = { - rune : "", - all : [], - add : function(rune,item){ + rune: '', + all: [], + add: function (rune, item) { this.rune = this.copy(rune) - this.all.push({rune:rune,item:item}); + this.all.push({ rune: rune, item: item }) }, - pop : function(){ - var copy = this.copy(this.all); - this.all = []; - return copy; + pop: function () { + var copy = this.copy(this.all) + this.all = [] + return copy }, - is_pop : function(rune){ - return this.all.length > 0 && rune.tag != this.rune.tag; + is_pop: function (rune) { + return this.all.length > 0 && rune.tag != this.rune.tag }, - length: function() - { - return this.all.length; + length: function () { + return this.all.length }, - copy : function(data){ - return JSON.parse(JSON.stringify(data)); + copy: function (data) { + return JSON.parse(JSON.stringify(data)) } } - this.media = function(val) - { - var service = val.split(" ")[0]; - var id = val.split(" ")[1]; + this.media = function (val) { + var service = val.split(' ')[0] + var id = val.split(' ')[1] - if(service == "itchio"){ - return `<iframe frameborder="0" src="https://itch.io/embed/${id}?link_color=000000" width="600" height="167"></iframe>`; + if (service == 'itchio') { + return `<iframe frameborder="0" src="https://itch.io/embed/${id}?link_color=000000" width="600" height="167"></iframe>` } - if(service == "bandcamp"){ - return `<iframe style="border: 0; width: 600px; height: 274px;" src="https://bandcamp.com/EmbeddedPlayer/album=${id}/size=large/bgcol=ffffff/linkcol=333333/artwork=small/transparent=true/" seamless></iframe>`; + if (service == 'bandcamp') { + return `<iframe style="border: 0; width: 600px; height: 274px;" src="https://bandcamp.com/EmbeddedPlayer/album=${id}/size=large/bgcol=ffffff/linkcol=333333/artwork=small/transparent=true/" seamless></iframe>` } return `<img src='media/${val}'/>` } - this.parse = function(raw = this.raw) - { - if(!raw){ return ""; } - - var html = ""; - var lines = raw; - var lines = !Array.isArray(raw) ? raw.split("\n") : raw; - - for(id in lines){ - var char = lines[id].substr(0,1).trim().toString() - var rune = this.runes[char]; - var trail = lines[id].substr(1,1); - if(char == "$"){ html += "<p>"+Ø("operation").request(lines[id].substr(2)).to_markup()+"</p>"; continue; } - if(char == "%"){ html += this.media(lines[id].substr(2)); continue; } - var line = lines[id].substr(2).to_markup(); - if(!line || line.trim() == ""){ continue; } - if(!rune){ console.log(`Unknown rune:${char} : ${line}`); } - if(trail != " "){ console.warn("Runic","Non-rune["+trail+"] at:"+id+"("+line+")"); continue; } - - if(this.stash.is_pop(rune)){ html += this.render_stash(); } - if(rune.stash === true){ this.stash.add(rune,line) ; continue; } - html += this.render(line,rune); + this.parse = function (raw = this.raw) { + if (!raw) { return '' } + + var html = '' + var lines = raw + var lines = !Array.isArray(raw) ? raw.split('\n') : raw + + for (id in lines) { + var char = lines[id].substr(0, 1).trim().toString() + var rune = this.runes[char] + var trail = lines[id].substr(1, 1) + if (char == '$') { html += '<p>' + Ø('operation').request(lines[id].substr(2)).to_markup() + '</p>'; continue } + if (char == '%') { html += this.media(lines[id].substr(2)); continue } + var line = lines[id].substr(2).to_markup() + if (!line || line.trim() == '') { continue } + if (!rune) { console.log(`Unknown rune:${char} : ${line}`) } + if (trail != ' ') { console.warn('Runic', 'Non-rune[' + trail + '] at:' + id + '(' + line + ')'); continue } + + if (this.stash.is_pop(rune)) { html += this.render_stash() } + if (rune.stash === true) { this.stash.add(rune, line); continue } + html += this.render(line, rune) } - if(this.stash.length() > 0){ html += this.render_stash(); } - return html; + if (this.stash.length() > 0) { html += this.render_stash() } + return html } - this.render_stash = function() - { - var rune = this.stash.rune; - var stash = this.stash.pop(); + this.render_stash = function () { + var rune = this.stash.rune + var stash = this.stash.pop() - var html = ""; - for(id in stash){ - var rune = stash[id].rune; - var line = stash[id].item; - html += rune.wrap ? `<${rune.sub}><${rune.wrap}>${line.replace(/\|/g,`</${rune.wrap}><${rune.wrap}>`).trim()}</${rune.wrap}></${rune.sub}>` : `<${rune.sub}>${line}</${rune.sub}>`; + var html = '' + for (id in stash) { + var rune = stash[id].rune + var line = stash[id].item + html += rune.wrap ? `<${rune.sub}><${rune.wrap}>${line.replace(/\|/g, `</${rune.wrap}><${rune.wrap}>`).trim()}</${rune.wrap}></${rune.sub}>` : `<${rune.sub}>${line}</${rune.sub}>` } return `<${rune.tag} class='${rune.class}'>${html}</${rune.tag}>` } - this.render = function(line = "",rune = null) - { - if(rune && rune.tag == "img"){ return `<img src='media/${line}'/>`; } - if(rune && rune.tag == "table"){ return "HEY"; } + this.render = function (line = '', rune = null) { + if (rune && rune.tag == 'img') { return `<img src='media/${line}'/>` } + if (rune && rune.tag == 'table') { return 'HEY' } - return rune ? (rune.tag ? "<"+rune.tag+" class='"+rune.class+"'>"+line+"</"+rune.tag+">" : line) : ""; + return rune ? (rune.tag ? '<' + rune.tag + " class='" + rune.class + "'>" + line + '</' + rune.tag + '>' : line) : '' } - this.html = function() - { - return this.parse(raw); + this.html = function () { + return this.parse(raw) } - this.toString = function() - { - return this.html(); + this.toString = function () { + return this.html() } } -String.prototype.capitalize = function() -{ - return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase(); +String.prototype.capitalize = function () { + return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase() } -String.prototype.to_url = function() -{ - return this.toLowerCase().replace(/ /g,"+").replace(/[^0-9a-z\+]/gi,"").trim(); +String.prototype.to_url = function () { + return this.toLowerCase().replace(/ /g, '+').replace(/[^0-9a-z\+]/gi, '').trim() } -String.prototype.to_path = function() -{ - return this.toLowerCase().replace(/ /g,".").replace(/[^0-9a-z\.]/gi,"").trim(); +String.prototype.to_path = function () { + return this.toLowerCase().replace(/ /g, '.').replace(/[^0-9a-z\.]/gi, '').trim() } -String.prototype.to_markup = function() -{ - html = this; - html = html.replace(/{_/g,"<i>").replace(/_}/g,"</i>") - html = html.replace(/{\*/g,"<b>").replace(/\*}/g,"</b>") - html = html.replace(/{\#/g,"<code class='inline'>").replace(/\#}/g,"</code>") - - var parts = html.split("{{") - for(id in parts){ - var part = parts[id]; - if(part.indexOf("}}") == -1){ continue; } - var content = part.split("}}")[0]; - if(content.substr(0,1) == "$"){ html = html.replace(`{{${content}}}`, Ø("operation").request(content.replace("$",""))); continue; } +String.prototype.to_markup = function () { + html = this + html = html.replace(/{_/g, '<i>').replace(/_}/g, '</i>') + html = html.replace(/{\*/g, '<b>').replace(/\*}/g, '</b>') + html = html.replace(/{\#/g, "<code class='inline'>").replace(/\#}/g, '</code>') + + var parts = html.split('{{') + for (id in parts) { + var part = parts[id] + if (part.indexOf('}}') == -1) { continue } + var content = part.split('}}')[0] + if (content.substr(0, 1) == '$') { html = html.replace(`{{${content}}}`, Ø('operation').request(content.replace('$', ''))); continue } // if(content.substr(0,1) == "%"){ html = html.replace(`{{${content}}}`, this.media(content)); continue; } - var target = content.indexOf("|") > -1 ? content.split("|")[1] : content; - var name = content.indexOf("|") > -1 ? content.split("|")[0] : content; - var external = (target.indexOf("https:") > -1 || target.indexOf("http:") > -1 || target.indexOf("dat:") > -1); - html = html.replace(`{{${content}}}`,external ? `<a href='${target}' class='external' target='_blank'>${name}</a>` : `<a class='local' onclick="Ø('query').bang('${target}')">${name}</a>`) + var target = content.indexOf('|') > -1 ? content.split('|')[1] : content + var name = content.indexOf('|') > -1 ? content.split('|')[0] : content + var external = (target.indexOf('https:') > -1 || target.indexOf('http:') > -1 || target.indexOf('dat:') > -1) + html = html.replace(`{{${content}}}`, external ? `<a href='${target}' class='external' target='_blank'>${name}</a>` : `<a class='local' onclick="Ø('query').bang('${target}')">${name}</a>`) } - return html; + return html } - - diff --git a/scripts/nodes/database.js b/scripts/nodes/database.js @@ -1,14 +1,12 @@ -function DatabaseNode(id,rect) -{ - Node.call(this,id,rect); +function DatabaseNode (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.builder - this.cache = null; + this.cache = null - this.receive = function(q) - { - this.cache = this.cache ? this.cache : this.request(); + this.receive = function (q) { + this.cache = this.cache ? this.cache : this.request() this.send(this.request(this.cache)) } -}- \ No newline at end of file +} diff --git a/scripts/nodes/document.js b/scripts/nodes/document.js @@ -1,11 +1,9 @@ -function DocumentNode(id,rect,...params) -{ - Node.call(this,id,rect); +function DocumentNode (id, rect, ...params) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.dom - - this.receive = function(content) - { + + this.receive = function (content) { document.title = content.title } -}- \ No newline at end of file +} diff --git a/scripts/nodes/dom.js b/scripts/nodes/dom.js @@ -1,46 +1,41 @@ -function DomNode(id,rect,...params) -{ - Node.call(this,id,rect); +function DomNode (id, rect, ...params) { + Node.call(this, id, rect) - this.type = params[0] ? params[0] : "yu"; + this.type = params[0] ? params[0] : 'div' this.glyph = NODE_GLYPHS.dom this.label = `${this.id}:${this.type}` this.el = document.createElement(this.type) this.el.id = this.id - this.is_installed = false; + this.is_installed = false - if(params[1]){ + if (params[1]) { this.el.innerHTML = params[1] } - this.receive = function(content) - { - if(content[this.id]){ - this.update(content[this.id]); + this.receive = function (content) { + if (content[this.id]) { + this.update(content[this.id]) this.send(content[this.id]) } } - this.answer = function() - { - if(!this.is_installed){ - this.install(this.request()); + this.answer = function () { + if (!this.is_installed) { + this.install(this.request()) } return this.el } - this.install = function(elements) - { - this.is_installed = true; - for(id in elements){ + this.install = function (elements) { + this.is_installed = true + for (id in elements) { this.el.appendChild(elements[id]) } } - this.update = function(content) - { - if(typeof content == "string"){ - this.el.innerHTML = content; + this.update = function (content) { + if (typeof content === 'string') { + this.el.innerHTML = content } } -}- \ No newline at end of file +} diff --git a/scripts/nodes/indental.js b/scripts/nodes/indental.js @@ -1,78 +1,70 @@ -function IndentalNode(id,rect,type) -{ - Node.call(this,id,rect); +function IndentalNode (id, rect, type) { + Node.call(this, id, rect) - this.type = type; + this.type = type this.glyph = NODE_GLYPHS.database - this.answer = function(q) - { - if(!DATABASE[this.id]){ + this.answer = function (q) { + if (!DATABASE[this.id]) { console.warn(`Missing /database/${this.id}.js`) - return null; + return null } - if(this.cache){ - return this.cache; + if (this.cache) { + return this.cache } - this.label = this.type ? `${this.id}=${this.type.name}` : `${this.id}`; - this.cache = parse(DATABASE[this.id],this.type) - return this.cache; + this.label = this.type ? `${this.id}=${this.type.name}` : `${this.id}` + this.cache = parse(DATABASE[this.id], this.type) + return this.cache } - function parse(data,type) - { - return build(data.split("\n").map(liner),type) - - function build(lines,type) - { + function parse (data, type) { + return build(data.split('\n').map(liner), type) + + function build (lines, type) { // Assoc lines var stack = {} var target = lines[0] - for(id in lines){ + for (id in lines) { var line = lines[id] - if(line.skip){ continue; } - target = stack[line.indent-2]; - if(target){ target.children.push(line) } + if (line.skip) { continue } + target = stack[line.indent - 2] + if (target) { target.children.push(line) } stack[line.indent] = line } // Format var h = {} - for(id in lines){ - var line = lines[id]; - if(line.skip || line.indent > 0){ continue; } + for (id in lines) { + var line = lines[id] + if (line.skip || line.indent > 0) { continue } var key = line.content.toUpperCase() - h[key] = type ? new type(key,format(line)) : format(line) + h[key] = type ? new type(key, format(line)) : format(line) } return h } - function format(line) - { - var a = []; - var h = {}; - for(id in line.children){ - var child = line.children[id]; - if(child.key){ h[child.key.toUpperCase()] = child.value } - else if(child.children.length == 0 && child.content){ a.push(child.content) } - else{ h[child.content.toUpperCase()] = format(child) } + function format (line) { + var a = [] + var h = {} + for (id in line.children) { + var child = line.children[id] + if (child.key) { h[child.key.toUpperCase()] = child.value } else if (child.children.length == 0 && child.content) { a.push(child.content) } else { h[child.content.toUpperCase()] = format(child) } } return a.length > 0 ? a : h } - function liner(line) - { + function liner (line) { return { - indent:line.search(/\S|$/), - content:line.trim(), - skip:line == "" || line.substr(0,1) == "~", - key:line.indexOf(" : ") > -1 ? line.split(" : ")[0].trim() : null, - value:line.indexOf(" : ") > -1 ? line.split(" : ")[1].trim() : null, - children:[] + indent: line.search(/\S|$/), + content: line.trim(), + skip: line == '' || line.substr(0, 1) == '~', + key: line.indexOf(' : ') > -1 ? line.split(' : ')[0].trim() : null, + value: line.indexOf(' : ') > -1 ? line.split(' : ')[1].trim() : null, + children: [] } } } } -var DATABASE = {};- \ No newline at end of file +var DATABASE = {} diff --git a/scripts/nodes/query.js b/scripts/nodes/query.js @@ -1,54 +1,49 @@ -function QueryNode(id,rect) -{ - Node.call(this,id,rect); +function QueryNode (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.entry - this.label = "query" + this.label = 'query' - this.bang = function(input = window.location.hash) - { + this.bang = function (input = window.location.hash) { var target = input.to_url() === '' ? 'home' : input.to_url() - Ø("view").el.className = `${target.to_path()} loading` - + Ø('view').el.className = `${target.to_path()} loading` + this.label = `${this.id}|${target}` this.send(target) - if(target === ''){ - window.history.replaceState(undefined, undefined, "#" + target) - } - else { + if (target === '') { + window.history.replaceState(undefined, undefined, '#' + target) + } else { window.location.hash = target.to_url() } - setTimeout(()=>{ window.scrollTo(0,0); },250) + setTimeout(() => { window.scrollTo(0, 0) }, 250) } } -var detectBackOrForward = function(onBack, onForward) -{ - hashHistory = [window.location.hash]; - historyLength = window.history.length; +var detectBackOrForward = function (onBack, onForward) { + hashHistory = [window.location.hash] + historyLength = window.history.length - return function() - { - var hash = window.location.hash, length = window.history.length; + return function () { + var hash = window.location.hash; var length = window.history.length if (hashHistory.length && historyLength == length) { if (hashHistory[hashHistory.length - 2] == hash) { - hashHistory = hashHistory.slice(0, -1); - onBack(); + hashHistory = hashHistory.slice(0, -1) + onBack() } else { - hashHistory.push(hash); - onForward(); + hashHistory.push(hash) + onForward() } } else { - hashHistory.push(hash); - historyLength = length; + hashHistory.push(hash) + historyLength = length } } -}; +} -window.addEventListener("hashchange", detectBackOrForward( - function() { console.log("back"); Ø('query').bang() }, - function() { console.log("forward"); Ø('query').bang() } -)); +window.addEventListener('hashchange', detectBackOrForward( + function () { console.log('back'); Ø('query').bang() }, + function () { console.log('forward'); Ø('query').bang() } +)) diff --git a/scripts/nodes/router.js b/scripts/nodes/router.js @@ -1,39 +1,36 @@ -function RouterNode(id,rect) -{ - Node.call(this,id,rect); +function RouterNode (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.router - this.receive = function(q) - { - var target = q.indexOf(":") > -1 ? q.split(":")[0].replace(/\+/g," ") : q.replace(/\+/g," ") - var params = q.indexOf(":") > -1 ? q.split(":")[1] : null - var db = this.request("database").database; - var data = find(target.toUpperCase(),db) + this.receive = function (q) { + var target = q.indexOf(':') > -1 ? q.split(':')[0].replace(/\+/g, ' ') : q.replace(/\+/g, ' ') + var params = q.indexOf(':') > -1 ? q.split(':')[1] : null + var db = this.request('database').database + var data = find(target.toUpperCase(), db) this.label = `${this.id}|${target}|${params}` - console.log(this.id,`${data ? data.type : '?'}->${target}[${params}]`); + console.log(this.id, `${data ? data.type : '?'}->${target}[${params}]`) this.send({ - name:target, - type:data ? data.type : null, - result:data ? data.result : null, - params:params, - tables:db + name: target, + type: data ? data.type : null, + result: data ? data.result : null, + params: params, + tables: db }) } - function find(key,db) - { - if(parseInt(key) > 0){ return null; } - - for(id in db){ + function find (key, db) { + if (parseInt(key) > 0) { return null } + + for (id in db) { var table = db[id] - if(table[key]){ - return {type:id,result:table[key]} + if (table[key]) { + return { type: id, result: table[key] } } } - return {type:null,result:null} + return { type: null, result: null } } -}- \ No newline at end of file +} diff --git a/scripts/nodes/template.js b/scripts/nodes/template.js @@ -1,22 +1,20 @@ -function TemplateNode(id,rect) -{ - Node.call(this,id,rect); +function TemplateNode (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.parser - this.cache = null; + this.cache = null - this.receive = function(q) - { - var assoc = this.signal(q.type ? q.type.slice(0, -1) : "page"); + this.receive = function (q) { + var assoc = this.signal(q.type ? q.type.slice(0, -1) : 'page') var payload = assoc.answer(q) this.send(payload) this.label = `template:${assoc.id}` - + // Install Dom - document.body.appendChild(this.signal("view").answer()) + document.body.appendChild(this.signal('view').answer()) - setTimeout(()=>{ Ø("view").el.className = `${q.name} ready` },250) + setTimeout(() => { Ø('view').el.className = `${q.name} ready` }, 250) } -}- \ No newline at end of file +} diff --git a/scripts/templates/home.js b/scripts/templates/home.js @@ -1,114 +1,106 @@ -function HomeTemplate(id,rect) -{ - Node.call(this,id,rect); +function HomeTemplate (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.render - this.answer = function(q) - { + this.answer = function (q) { var ingredients = find_ingredients(q.tables.recipes) ingredients['coffee'] = 1 - var sorted_ingredients = sort_ingredients(ingredients); + var sorted_ingredients = sort_ingredients(ingredients) var html = ` - ${make_ingredients(sorted_ingredients,q.tables.ingredients)} + ${make_ingredients(sorted_ingredients, q.tables.ingredients)} <h1>Recipes</h1> ${make_recipes(q.tables.recipes)} ` return { - title:`GrimGrains — Home`, - view:{ + title: `GrimGrains — Home`, + view: { core: { content: html, - related: "" + related: '' } } } } - function find_ingredients(recipes) - { + function find_ingredients (recipes) { var h = {} - for(id in recipes){ - var recipe = recipes[id]; - for(id in recipe.INGR){ - var category = recipe.INGR[id]; - for(name in category){ - h[name] = h[name] ? h[name]+1 : 1 + for (id in recipes) { + var recipe = recipes[id] + for (id in recipe.INGR) { + var category = recipe.INGR[id] + for (name in category) { + h[name] = h[name] ? h[name] + 1 : 1 } } } return h } - function sort_ingredients(ingredients) - { - var a = []; - for(name in ingredients){ - var value = ingredients[name]; - a.push([name,value]) + function sort_ingredients (ingredients) { + var a = [] + for (name in ingredients) { + var value = ingredients[name] + a.push([name, value]) } - a.sort(function(a, b) { - return a[1] - b[1]; - }); - return a; + a.sort(function (a, b) { + return a[1] - b[1] + }) + return a } - function make_ingredients(ingredients,table) - { - var html = ""; - for(id in ingredients){ - var name = ingredients[id][0]; + function make_ingredients (ingredients, table) { + var html = '' + for (id in ingredients) { + var name = ingredients[id][0] html += ` - <ln class='ingredient ${!table[name] ? "missing" : ""}'> + <li class='ingredient ${!table[name] ? 'missing' : ''}'> <a href='#${name.to_url()}' onclick="Ø('query').bang('${name}')"> <img src='media/ingredients/${name.to_path()}.png'/> </a> <t class='name'>${name.capitalize()}</t> - </ln>` + </li>` } - return `<list class='ingredients'>${html}<hr/></list>` + return `<ul class='ingredients'>${html}<hr/></ul>` } - function count_ingredients(recipe) - { + function count_ingredients (recipe) { var ingredients = {} - for(cat in recipe.INGR){ - for(id in recipe.INGR[cat]){ + for (cat in recipe.INGR) { + for (id in recipe.INGR[cat]) { ingredients[id] = 1 } } return Object.keys(ingredients).length } - function make_recipes(recipes) - { - var html = "" + function make_recipes (recipes) { + var html = '' // Sort by tag var categorized = {} - for(name in recipes){ + for (name in recipes) { var recipe = recipes[name] - if(!categorized[recipe.TAGS[0]]){ categorized[recipe.TAGS[0]] = []; } + if (!categorized[recipe.TAGS[0]]) { categorized[recipe.TAGS[0]] = [] } recipe.name = name categorized[recipe.TAGS[0]].push(recipe) } - for(cat in categorized){ + for (cat in categorized) { var recipes = categorized[cat] html += `<h3>${cat.capitalize()}</h3>` - html += "<list style='margin-bottom:15px'>" - for(id in recipes){ + html += "<ul style='margin-bottom:15px'>" + for (id in recipes) { var recipe = recipes[id] - html += `<ln><a onclick="Ø('query').bang('${recipe.name.capitalize()}')">${recipe.name.capitalize()}</a></ln>` - + html += `<li><a href="#${recipe.name.to_url()}" onclick="Ø('query').bang('${recipe.name.capitalize()}')">${recipe.name.capitalize()}</a></li>` } - html += "</list>" + html += '</ul>' } - return `<columns id='recipes'>${html}</columns>`; + return `<columns id='recipes'>${html}</columns>` } -}- \ No newline at end of file +} diff --git a/scripts/templates/ingredient.js b/scripts/templates/ingredient.js @@ -1,161 +1,149 @@ -function IngredientTemplate(id,rect) -{ - Node.call(this,id,rect); +function IngredientTemplate (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.render // Create the recipe body - this.answer = function(t) - { - var ingredient = t.result; + this.answer = function (t) { + var ingredient = t.result return { - title:`GrimGrains — ${t.name.capitalize()}`, + title: `GrimGrains — ${t.name.capitalize()}`, view: { core: { - content: make_ingredient(t.name,ingredient,t.tables.recipes), - related:make_related(related_recipes(t.name,t.tables.recipes)) + content: make_ingredient(t.name, ingredient, t.tables.recipes), + related: make_related(related_recipes(t.name, t.tables.recipes)) } } } } - function make_ingredient(name,ingredient,recipes) - { - var html = "" + function make_ingredient (name, ingredient, recipes) { + var html = '' - html += `<h1>${ingredient.TYPE ? ingredient.TYPE.capitalize()+"/" : ''}${name.capitalize()}</h1>` + html += `<h1>${ingredient.TYPE ? ingredient.TYPE.capitalize() + '/' : ''}${name.capitalize()}</h1>` html += ingredient.BREF ? `<p class='bref'>${ingredient.BREF.to_markup()}</p>` : '' html += ingredient.LONG ? `${new Runic(ingredient.LONG)}` : '' - html += `${make_similar(name,recipes)}` + html += `${make_similar(name, recipes)}` return html } - function make_similar(name,recipes) - { - var html = "" - var ingredients = find_ingredients(recipes); - var similar_ingredients = find_similar_ingredients(name,ingredients) + function make_similar (name, recipes) { + var html = '' + var ingredients = find_ingredients(recipes) + var similar_ingredients = find_similar_ingredients(name, ingredients) - for(id in similar_ingredients){ - if(similar_ingredients[id][1] < 1){ break;} - var name = similar_ingredients[id][0]; + for (id in similar_ingredients) { + if (similar_ingredients[id][1] < 1) { break } + var name = similar_ingredients[id][0] html += ` - <ln class='ingredient'> + <li class='ingredient'> <a onclick="Ø('query').bang('${name}')" href='#${name.to_url()}'> <img src='media/ingredients/${name.to_path()}.png'/> </a> <t class='name'>${name.capitalize()}</t> - </ln>` + </li>` } - return similar_ingredients.length > 1 ? `<h2>Related Ingredients</h2><list class='ingredients'>${html}<hr /></list>` : '' + return similar_ingredients.length > 1 ? `<h2>Related Ingredients</h2><ul class='ingredients'>${html}<hr /></ul>` : '' } - function find_ingredients(recipes) - { + function find_ingredients (recipes) { var h = {} - for(id in recipes){ - var recipe = recipes[id]; - for(id in recipe.INGR){ - var category = recipe.INGR[id]; - for(name in category){ - h[name] = h[name] ? h[name]+1 : 1 + for (id in recipes) { + var recipe = recipes[id] + for (id in recipe.INGR) { + var category = recipe.INGR[id] + for (name in category) { + h[name] = h[name] ? h[name] + 1 : 1 } } } return h } - function find_similar_ingredients(name,ingredients) - { - var a = []; + function find_similar_ingredients (name, ingredients) { + var a = [] - for(id in ingredients){ - var words = id.toLowerCase().split(" ") - var index = similarity(name.toLowerCase().split(" "),words); - if(index > 0){ - a.push([id,index]) + for (id in ingredients) { + var words = id.toLowerCase().split(' ') + var index = similarity(name.toLowerCase().split(' '), words) + if (index > 0) { + a.push([id, index]) } } - a.sort(function(a, b) { - return a[1] - b[1]; - }); - - return a.reverse(); + a.sort(function (a, b) { + return a[1] - b[1] + }) + + return a.reverse() } - function similarity(a,b) - { - var score = 0; - for(a_id in a){ - var word_a = a[a_id]; - for(b_id in b){ - var word_b = b[b_id]; + function similarity (a, b) { + var score = 0 + for (a_id in a) { + var word_a = a[a_id] + for (b_id in b) { + var word_b = b[b_id] score += word_a == word_b ? 1 : 0 } } return score } - function make_related(recipes) - { - var html = "" + function make_related (recipes) { + var html = '' - var count = 0; - for(id in recipes){ + var count = 0 + for (id in recipes) { var recipe = recipes[id] - var name = id; + var name = id html += ` - <ln class='recipe'> + <li class='recipe'> <a onclick="Ø('query').bang('${name}')" class='photo' href='#${name}' style='background-image:url(media/recipes/${name.to_path()}.jpg)'></a> <t class='name'>${name.capitalize()}</t> <t class='details'><b>${recipe.TIME} minutes</b><br />${count_ingredients(recipe)} ingredients<br />${recipe.INST.length} steps</t> - </ln>` - if(count > 1){ break; } + </li>` + if (count > 1) { break } count += 1 } - return `${html}<hr/>` + return `${html}<hr/>` } - function sort(o) - { - return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {}); + function sort (o) { + return Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {}) } - function related_recipes(name,recipes) - { + function related_recipes (name, recipes) { var h = {} - for(id in recipes){ + for (id in recipes) { var recipe = recipes[id] - for(i in recipe.INGR){ - var ingredients = recipe.INGR[i]; - for(n in ingredients){ - if(n.indexOf(name.toUpperCase()) < 0){ continue; } + for (i in recipe.INGR) { + var ingredients = recipe.INGR[i] + for (n in ingredients) { + if (n.indexOf(name.toUpperCase()) < 0) { continue } h[id] = recipes[id] } } } - return h; + return h } - function related_ingredients(name,tag,ingredients) - { + function related_ingredients (name, tag, ingredients) { var a = [] - for(id in ingredients){ + for (id in ingredients) { var ingredient = ingredients[id] - if(!ingredient.TAGS || ingredient.TAGS.indexOf(tag) < 0 || id == name){ continue; } + if (!ingredient.TAGS || ingredient.TAGS.indexOf(tag) < 0 || id == name) { continue } a.push(id) } - return a; + return a } - function count_ingredients(recipe) - { + function count_ingredients (recipe) { var ingredients = {} - for(cat in recipe.INGR){ - for(id in recipe.INGR[cat]){ + for (cat in recipe.INGR) { + for (id in recipe.INGR[cat]) { ingredients[id] = 1 } } diff --git a/scripts/templates/page.js b/scripts/templates/page.js @@ -1,26 +1,24 @@ -function PageTemplate(id,rect) -{ - Node.call(this,id,rect); +function PageTemplate (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.render // Create the recipe body - this.answer = function(q) - { - if(this.signal(q.name.toLowerCase())){ + this.answer = function (q) { + if (this.signal(q.name.toLowerCase())) { this.label = `page:${q.name}` - return this.signal(q.name.toLowerCase()).answer(q) + return this.signal(q.name.toLowerCase()).answer(q) } - if(!q.type){ + if (!q.type) { this.label = `page:${q.name}` - return this.signal("search").answer(q) + return this.signal('search').answer(q) } var page = q.result return { - title:`GrimGrains — ${q.name.capitalize()}`, - view:{ + title: `GrimGrains — ${q.name.capitalize()}`, + view: { core: { content: `<h1>${q.name.capitalize()}</h1><p>${page.BREF.to_markup()}</p>${new Runic(page.LONG).toString()}` } @@ -28,13 +26,12 @@ function PageTemplate(id,rect) } } - function list(items) - { - var html = "" - for(id in items){ - html += `<ln>${id} -> ${items[id]}</ln>` + function list (items) { + var html = '' + for (id in items) { + html += `<li>${id} -> ${items[id]}</li>` // html += list(items[id]) } - return html; + return html } -}- \ No newline at end of file +} diff --git a/scripts/templates/recipe.js b/scripts/templates/recipe.js @@ -1,17 +1,15 @@ -function RecipeTemplate(id,rect) -{ - Node.call(this,id,rect); +function RecipeTemplate (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.render // Create the recipe body - this.answer = function(t) - { + this.answer = function (t) { return { - title:`GrimGrains — ${t.name.capitalize()}`, - view:{ - header:{ + title: `GrimGrains — ${t.name.capitalize()}`, + view: { + header: { search: t.name.capitalize() }, core: { @@ -22,123 +20,118 @@ function RecipeTemplate(id,rect) } } - function make_content(q) - { + function make_content (q) { var recipe = q.result - var html = ""; + var html = '' html += ` + <h1 class='name'>${q.name.capitalize()}</h1> + <h2 class='serving'>${recipe.SERV} — ${recipe.TIME} minutes</h2> + <hr /> + <img class='photo' src='media/recipes/${q.name.to_path()}.jpg'/> - <h1>${q.name.capitalize()}</h1> - <h2>${recipe.SERV} — ${recipe.TIME} minutes</h2> <columns>${new Runic(recipe.DESC)}</columns> ${make_ingredients(recipe.INGR)} - ${make_instructions(recipe)}`; + ${make_instructions(recipe)}` return html } - function make_instructions(recipe) - { - var html = ""; + function make_instructions (recipe) { + var html = '' html += `<h2>Instructions</h2>` var count = 1 - for(cat in recipe.INST){ + for (cat in recipe.INST) { html += `<h3>Step ${count}: ${cat.capitalize()}</h3>` - var category = recipe.INST[cat]; - html += new Runic(category).toString(); + var category = recipe.INST[cat] + html += new Runic(category).toString() count += 1 } - return `<yu id='instructions'>${html}</yu>` + return `<div id='instructions'>${html}</div>` } - function make_related(q) - { - var html = ""; + function make_related (q) { + var html = '' var recipe = q.result - var recipes = find_related(q.name,recipe,q.tables.recipes) + var recipes = find_related(q.name, recipe, q.tables.recipes) - var count = 0; - for(id in recipes){ - var name = recipes[id][0]; + var count = 0 + for (id in recipes) { + var name = recipes[id][0] var recipe = q.tables.recipes[name] html += ` - <ln class='recipe'> + <li class='recipe'> <a class='photo' onclick="Ø('query').bang('${name}')" href='#${name.to_url()}' style='background-image:url(media/recipes/${name.to_path()}.jpg)'></a> <t class='name'>${name.capitalize()}</t> <t class='details'><b>${recipe.TIME} minutes</b><br />${count_ingredients(recipe)} ingredients<br />${Object.keys(recipe.INST).length} step${Object.keys(recipe.INST).length > 1 ? 's' : ''}</t> - </ln>` - if(count > 1){ break; } + </li>` + if (count > 1) { break } count += 1 } - return `${html}<hr/>` + return `${html}<hr/>` } - function count_ingredients(recipe) - { + function count_ingredients (recipe) { var ingredients = {} - for(cat in recipe.INGR){ - for(id in recipe.INGR[cat]){ + for (cat in recipe.INGR) { + for (id in recipe.INGR[cat]) { ingredients[id] = 1 } } return Object.keys(ingredients).length } - function find_related(name,target,recipes) - { - var a = []; - for(id in recipes){ - var recipe = recipes[id]; - var index = similarity(target.TAGS,recipe.TAGS) - if(id.toLowerCase() != name.toLowerCase()){ - a.push([id,index]) + function find_related (name, target, recipes) { + var a = [] + for (id in recipes) { + var recipe = recipes[id] + var index = similarity(target.TAGS, recipe.TAGS) + if (id.toLowerCase() != name.toLowerCase()) { + a.push([id, index]) } } - a.sort(function(a, b) { - return a[1] - b[1]; - }); - return a.reverse(); + a.sort(function (a, b) { + return a[1] - b[1] + }) + return a.reverse() } - function make_ingredients(categories) - { - var html = ""; - for(id in categories){ - var elements = categories[id]; - - html += `<list class='ingredients'>` - html += Object.keys(categories).length > 1 ? `<h3>${id.capitalize()}</h3>` : "" - for(name in elements){ - var element = elements[name]; + function make_ingredients (categories) { + var html = '' + for (id in categories) { + var elements = categories[id] + + html += `<ul class='ingredients'>` + html += Object.keys(categories).length > 1 ? `<h3>${id.capitalize()}</h3>` : '' + for (name in elements) { + var element = elements[name] html += ` - <ln class='ingredient'> + <li class='ingredient'> <a onclick="Ø('query').bang('${name}')" href='#${name.to_url()}'> <img src='media/ingredients/${name.to_path()}.png'/> </a> <t class='name'>${name.capitalize()}</t> <t class='quantity'>${element}</t> - </ln>` + </li>` } - html += `<hr /></list>` + html += `<hr /></ul>` } return html } - function similarity(a,b) - { + function similarity (a, b) { var score = 0 - for(a_id in a){ - var tag_a = a[a_id]; - for(b_id in b){ - var tag_b = b[b_id]; + for (a_id in a) { + var tag_a = a[a_id] + for (b_id in b) { + var tag_b = b[b_id] score += tag_a.toLowerCase() == tag_b.toLowerCase() ? 1 : 0 } } return score } -}- \ No newline at end of file +} diff --git a/scripts/templates/search.js b/scripts/templates/search.js @@ -1,22 +1,20 @@ -function SearchTemplate(id,rect) -{ - Node.call(this,id,rect); +function SearchTemplate (id, rect) { + Node.call(this, id, rect) this.glyph = NODE_GLYPHS.render // Create the recipe body - this.answer = function(q) - { - var html = "" + this.answer = function (q) { + var html = '' return { core: { - content: "sup", - related:"hello" + content: 'sup', + related: 'hello' } } return html } -}- \ No newline at end of file +}