diff --git a/app/css/app.css b/app/css/app.css new file mode 100644 index 0000000..a4b4fea --- /dev/null +++ b/app/css/app.css @@ -0,0 +1,167 @@ +html, +body { + height: 100%; + background-color: #eee; +} + +html, +body, +input, +textarea, +buttons { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004); +} + + +/** + * Layout CSS + */ +#header { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 2; + transition: left 0.2s; +} + +#sidedrawer { + position: fixed; + top: 0; + bottom: 0; + width: 200px; + left: -200px; + overflow: auto; + z-index: 2; + background-color: #fff; + transition: transform 0.2s; +} + +#content-wrapper { + min-height: 100%; + overflow-x: hidden; + margin-left: 0px; + transition: margin-left 0.2s; + + /* sticky bottom */ + margin-bottom: -160px; + padding-bottom: 160px; +} + +#footer { + height: 160px; + margin-left: 0px; + transition: margin-left 0.2s; +} + +@media (min-width: 768px) { + #header { + left: 200px; + } + + #sidedrawer { + transform: translate(200px); + } + + #content-wrapper { + margin-left: 200px; + } + + #footer { + margin-left: 200px; + } + + body.hide-sidedrawer #header { + left: 0; + } + + body.hide-sidedrawer #sidedrawer { + transform: translate(0px); + } + + body.hide-sidedrawer #content-wrapper { + margin-left: 0; + } + + body.hide-sidedrawer #footer { + margin-left: 0; + } +} + + +/** + * Toggle Side drawer + */ +#sidedrawer.active { + transform: translate(200px); +} + + +/** + * Header CSS + */ +.sidedrawer-toggle { + color: #fff; + cursor: pointer; + font-size: 20px; + line-height: 20px; + margin-right: 10px; +} + +.sidedrawer-toggle:hover { + color: #fff; + text-decoration: none; +} + + +/** + * Footer CSS + */ +#footer { + background-color: #0288D1; + color: #fff; +} + +#footer a { + color: #fff; + text-decoration: underline; +} + +/** +* Side drawer CSS +*/ +#sidedrawer-brand { + /* padding-left: 20px; */ +} + +#sidedrawer ul { + list-style: none; +} + +#sidedrawer > ul { + padding-left: 0px; +} + +#sidedrawer > ul > li:first-child { + padding-top: 15px; +} + +#sidedrawer strong { + display: block; + padding: 15px 22px; + cursor: pointer; +} + +#sidedrawer .entry:hover { + background-color: #E0E0E0; +} + +#sidedrawer strong + ul > li { + padding: 6px 0px; +} +#sidedrawer .entry { + padding-bottom: 5px; + border-bottom:1px solid #e0c0e0; +} \ No newline at end of file diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..95cf055 --- /dev/null +++ b/app/index.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + +
+
Recipes
+
+
+ +
+
+ Add
+
+ +
+
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/app/js/app.js b/app/js/app.js new file mode 100644 index 0000000..5f07363 --- /dev/null +++ b/app/js/app.js @@ -0,0 +1,129 @@ +/** + * Created by Martin on 24/02/2016. + */ +(function () { + "use strict"; + console.log('GO!'); + var $list = $('#listContainer'); + var displayList = function (obj) { + var html = new EJS({url: '/partials/list.ejs'}).render(obj); + console.log(html); + $list.empty(); + $list.append(html); + $("#listContainer .entry").not('.emptyMessage').click(function () { + console.log('Clicked list. ' + this.id); + getRecipe(this.id); + }); + }, displayPage = function (obj) { + var $bodyContents = $('#bodyContents'); + + if (obj.list[0].body.length > 0) { + $bodyContents.empty(); + $bodyContents.append(obj.list[0].body); + } + }, getRecipe = function (id) { + console.log('get recipe'); + var url = '/recipes/entry/' + id; + var data = ''; + $.ajax({ + type: 'GET', + url: url, + data: data, + dataType: 'json', + + timeout: 10000, + + //contentType: ('application/json'), + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'PUT, GET, POST, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + + }, + success: function (data) { + console.log(data); + displayPage(data); + }, + error: function (xhr, type) { + console.log("ajax error"); + console.log(xhr); + console.log(type); + } + }); + }, + + getList = function () { + + var url = '/recipes/list'; + + $.ajax({ + type: 'GET', + url: url, + data: '', + dataType: 'json', + + timeout: 10000, + + //contentType: ('application/json'), + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'PUT, GET, POST, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + + }, + success: function (data) { + console.log(data); + displayList(data); + }, + error: function (xhr, type) { + console.log("ajax error"); + console.log(xhr); + console.log(type); + } + }); + }, addNew = function (newUrl) { + var url = '/recipes/add'; + + var data = {url: JSON.stringify(newUrl)}; + $.ajax({ + type: 'POST', + url: url, + data: data, + dataType: 'json', + + timeout: 10000, + + //contentType: ('application/json'), + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'PUT, GET, POST, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + + }, + success: function (data) { + console.log(data); + // displayList(data); + }, + error: function (xhr, type) { + console.log("ajax error"); + console.log(xhr); + console.log(type); + } + }); + }, + start = function () { + + getList(); + }; + + $('#addNew').click(function () { + var url = prompt("Please enter a new url", ""); + + if (url != null) { + console.log('Adding: ' + url); + addNew(url); + } + }); + + start(); +})(); \ No newline at end of file diff --git a/app/js/shell.js b/app/js/shell.js new file mode 100644 index 0000000..86dda84 --- /dev/null +++ b/app/js/shell.js @@ -0,0 +1,45 @@ +jQuery(function($) { + var $bodyEl = $('body'), + $sidedrawerEl = $('#sidedrawer'); + + + function showSidedrawer() { + // show overlay + var options = { + onclose: function() { + $sidedrawerEl + .removeClass('active') + .appendTo(document.body); + } + }; + + var $overlayEl = $(mui.overlay('on', options)); + + // show element + $sidedrawerEl.appendTo($overlayEl); + setTimeout(function() { + $sidedrawerEl.addClass('active'); + }, 20); + } + + + function hideSidedrawer() { + $bodyEl.toggleClass('hide-sidedrawer'); + } + + + $('.js-show-sidedrawer').on('click', showSidedrawer); + $('.js-hide-sidedrawer').on('click', hideSidedrawer); +}); + +var $titleEls = $('strong', $sidedrawerEl); + +$titleEls + .next() + .hide(); + +$titleEls.on('click', function() { + $(this).next().slideToggle(200); +});/** + * Created by Martin on 24/02/2016. + */ diff --git a/app/libs/ejs.js b/app/libs/ejs.js new file mode 100644 index 0000000..49d9525 --- /dev/null +++ b/app/libs/ejs.js @@ -0,0 +1,505 @@ +(function(){ + + +var rsplit = function(string, regex) { + var result = regex.exec(string),retArr = new Array(), first_idx, last_idx, first_bit; + while (result != null) + { + first_idx = result.index; last_idx = regex.lastIndex; + if ((first_idx) != 0) + { + first_bit = string.substring(0,first_idx); + retArr.push(string.substring(0,first_idx)); + string = string.slice(first_idx); + } + retArr.push(result[0]); + string = string.slice(result[0].length); + result = regex.exec(string); + } + if (! string == '') + { + retArr.push(string); + } + return retArr; +}, +chop = function(string){ + return string.substr(0, string.length - 1); +}, +extend = function(d, s){ + for(var n in s){ + if(s.hasOwnProperty(n)) d[n] = s[n] + } +} + + +EJS = function( options ){ + options = typeof options == "string" ? {view: options} : options + this.set_options(options); + if(options.precompiled){ + this.template = {}; + this.template.process = options.precompiled; + EJS.update(this.name, this); + return; + } + if(options.element) + { + if(typeof options.element == 'string'){ + var name = options.element + options.element = document.getElementById( options.element ) + if(options.element == null) throw name+'does not exist!' + } + if(options.element.value){ + this.text = options.element.value + }else{ + this.text = options.element.innerHTML + } + this.name = options.element.id + this.type = '[' + }else if(options.url){ + options.url = EJS.endExt(options.url, this.extMatch); + this.name = this.name ? this.name : options.url; + var url = options.url + //options.view = options.absolute_url || options.view || options.; + var template = EJS.get(this.name /*url*/, this.cache); + if (template) return template; + if (template == EJS.INVALID_PATH) return null; + try{ + this.text = EJS.request( url+(this.cache ? '' : '?'+Math.random() )); + }catch(e){} + + if(this.text == null){ + throw( {type: 'EJS', message: 'There is no template at '+url} ); + } + //this.name = url; + } + var template = new EJS.Compiler(this.text, this.type); + + template.compile(options, this.name); + + + EJS.update(this.name, this); + this.template = template; +}; +/* @Prototype*/ +EJS.prototype = { + /** + * Renders an object with extra view helpers attached to the view. + * @param {Object} object data to be rendered + * @param {Object} extra_helpers an object with additonal view helpers + * @return {String} returns the result of the string + */ + render : function(object, extra_helpers){ + object = object || {}; + this._extra_helpers = extra_helpers; + var v = new EJS.Helpers(object, extra_helpers || {}); + return this.template.process.call(object, object,v); + }, + update : function(element, options){ + if(typeof element == 'string'){ + element = document.getElementById(element) + } + if(options == null){ + _template = this; + return function(object){ + EJS.prototype.update.call(_template, element, object) + } + } + if(typeof options == 'string'){ + params = {} + params.url = options + _template = this; + params.onComplete = function(request){ + var object = eval( request.responseText ) + EJS.prototype.update.call(_template, element, object) + } + EJS.ajax_request(params) + }else + { + element.innerHTML = this.render(options) + } + }, + out : function(){ + return this.template.out; + }, + /** + * Sets options on this view to be rendered with. + * @param {Object} options + */ + set_options : function(options){ + this.type = options.type || EJS.type; + this.cache = options.cache != null ? options.cache : EJS.cache; + this.text = options.text || null; + this.name = options.name || null; + this.ext = options.ext || EJS.ext; + this.extMatch = new RegExp(this.ext.replace(/\./, '\.')); + } +}; +EJS.endExt = function(path, match){ + if(!path) return null; + match.lastIndex = 0 + return path+ (match.test(path) ? '' : this.ext ) +} + + + + +/* @Static*/ +EJS.Scanner = function(source, left, right) { + + extend(this, + {left_delimiter: left +'%', + right_delimiter: '%'+right, + double_left: left+'%%', + double_right: '%%'+right, + left_equal: left+'%=', + left_comment: left+'%#'}) + + this.SplitRegexp = left=='[' ? /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/ : new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') ; + + this.source = source; + this.stag = null; + this.lines = 0; +}; + +EJS.Scanner.to_text = function(input){ + if(input == null || input === undefined) + return ''; + if(input instanceof Date) + return input.toDateString(); + if(input.toString) + return input.toString(); + return ''; +}; + +EJS.Scanner.prototype = { + scan: function(block) { + scanline = this.scanline; + regex = this.SplitRegexp; + if (! this.source == '') + { + var source_split = rsplit(this.source, /\n/); + for(var i=0; i 0) + { + for (var i=0; i 0) + { + buff.push(put_cmd + '"' + clean(content) + '")'); + } + content = ''; + break; + case scanner.double_left: + content = content + scanner.left_delimiter; + break; + default: + content = content + token; + break; + } + } + else { + switch(token) { + case scanner.right_delimiter: + switch(scanner.stag) { + case scanner.left_delimiter: + if (content[content.length - 1] == '\n') + { + content = chop(content); + buff.push(content); + buff.cr(); + } + else { + buff.push(content); + } + break; + case scanner.left_equal: + buff.push(insert_cmd + "(EJS.Scanner.to_text(" + content + ")))"); + break; + } + scanner.stag = null; + content = ''; + break; + case scanner.double_right: + content = content + scanner.right_delimiter; + break; + default: + content = content + token; + break; + } + } + }); + if (content.length > 0) + { + // Chould be content.dump in Ruby + buff.push(put_cmd + '"' + clean(content) + '")'); + } + buff.close(); + this.out = buff.script + ";"; + var to_be_evaled = '/*'+name+'*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {'+this.out+" return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};"; + + try{ + eval(to_be_evaled); + }catch(e){ + if(typeof JSLINT != 'undefined'){ + JSLINT(this.out); + for(var i = 0; i < JSLINT.errors.length; i++){ + var error = JSLINT.errors[i]; + if(error.reason != "Unnecessary semicolon."){ + error.line++; + var e = new Error(); + e.lineNumber = error.line; + e.message = error.reason; + if(options.view) + e.fileName = options.view; + throw e; + } + } + }else{ + throw e; + } + } + } +}; + + +//type, cache, folder +/** + * Sets default options for all views + * @param {Object} options Set view with the following options + * + + + + + + + + + + + +
OptionDefaultDescription
type'<'type of magic tags. Options are '<' or '[' +
cachetrue in production mode, false in other modestrue to cache template. +
+ * + */ +EJS.config = function(options){ + EJS.cache = options.cache != null ? options.cache : EJS.cache; + EJS.type = options.type != null ? options.type : EJS.type; + EJS.ext = options.ext != null ? options.ext : EJS.ext; + + var templates_directory = EJS.templates_directory || {}; //nice and private container + EJS.templates_directory = templates_directory; + EJS.get = function(path, cache){ + if(cache == false) return null; + if(templates_directory[path]) return templates_directory[path]; + return null; + }; + + EJS.update = function(path, template) { + if(path == null) return; + templates_directory[path] = template ; + }; + + EJS.INVALID_PATH = -1; +}; +EJS.config( {cache: true, type: '<', ext: '.ejs' } ); + + + +/** + * @constructor + * By adding functions to EJS.Helpers.prototype, those functions will be available in the + * views. + * @init Creates a view helper. This function is called internally. You should never call it. + * @param {Object} data The data passed to the view. Helpers have access to it through this._data + */ +EJS.Helpers = function(data, extras){ + this._data = data; + this._extras = extras; + extend(this, extras ); +}; +/* @prototype*/ +EJS.Helpers.prototype = { + /** + * Renders a new view. If data is passed in, uses that to render the view. + * @param {Object} options standard options passed to a new view. + * @param {optional:Object} data + * @return {String} + */ + view: function(options, data, helpers){ + if(!helpers) helpers = this._extras + if(!data) data = this._data; + return new EJS(options).render(data, helpers); + }, + /** + * For a given value, tries to create a human representation. + * @param {Object} input the value being converted. + * @param {Object} null_text what text should be present if input == null or undefined, defaults to '' + * @return {String} + */ + to_text: function(input, null_text) { + if(input == null || input === undefined) return null_text || ''; + if(input instanceof Date) return input.toDateString(); + if(input.toString) return input.toString().replace(/\n/g, '
').replace(/''/g, "'"); + return ''; + } +}; + EJS.newRequest = function(){ + var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }]; + for(var i = 0; i < factories.length; i++) { + try { + var request = factories[i](); + if (request != null) return request; + } + catch(e) { continue;} + } + } + + EJS.request = function(path){ + var request = new EJS.newRequest() + request.open("GET", path, false); + + try{request.send(null);} + catch(e){return null;} + + if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null; + + return request.responseText + } + EJS.ajax_request = function(params){ + params.method = ( params.method ? params.method : 'GET') + + var request = new EJS.newRequest(); + request.onreadystatechange = function(){ + if(request.readyState == 4){ + if(request.status == 200){ + params.onComplete(request) + }else + { + params.onComplete(request) + } + } + } + request.open(params.method, params.url) + request.send(null) + } + + +})(); \ No newline at end of file diff --git a/app/libs/ejs_production.js b/app/libs/ejs_production.js new file mode 100644 index 0000000..ccce922 --- /dev/null +++ b/app/libs/ejs_production.js @@ -0,0 +1 @@ +(function(){var rsplit=function(string,regex){var result=regex.exec(string),retArr=new Array(),first_idx,last_idx,first_bit;while(result!=null){first_idx=result.index;last_idx=regex.lastIndex;if((first_idx)!=0){first_bit=string.substring(0,first_idx);retArr.push(string.substring(0,first_idx));string=string.slice(first_idx)}retArr.push(result[0]);string=string.slice(result[0].length);result=regex.exec(string)}if(!string==""){retArr.push(string)}return retArr},chop=function(string){return string.substr(0,string.length-1)},extend=function(d,s){for(var n in s){if(s.hasOwnProperty(n)){d[n]=s[n]}}};EJS=function(options){options=typeof options=="string"?{view:options}:options;this.set_options(options);if(options.precompiled){this.template={};this.template.process=options.precompiled;EJS.update(this.name,this);return }if(options.element){if(typeof options.element=="string"){var name=options.element;options.element=document.getElementById(options.element);if(options.element==null){throw name+"does not exist!"}}if(options.element.value){this.text=options.element.value}else{this.text=options.element.innerHTML}this.name=options.element.id;this.type="["}else{if(options.url){options.url=EJS.endExt(options.url,this.extMatch);this.name=this.name?this.name:options.url;var url=options.url;var template=EJS.get(this.name,this.cache);if(template){return template}if(template==EJS.INVALID_PATH){return null}try{this.text=EJS.request(url+(this.cache?"":"?"+Math.random()))}catch(e){}if(this.text==null){throw ({type:"EJS",message:"There is no template at "+url})}}}var template=new EJS.Compiler(this.text,this.type);template.compile(options,this.name);EJS.update(this.name,this);this.template=template};EJS.prototype={render:function(object,extra_helpers){object=object||{};this._extra_helpers=extra_helpers;var v=new EJS.Helpers(object,extra_helpers||{});return this.template.process.call(object,object,v)},update:function(element,options){if(typeof element=="string"){element=document.getElementById(element)}if(options==null){_template=this;return function(object){EJS.prototype.update.call(_template,element,object)}}if(typeof options=="string"){params={};params.url=options;_template=this;params.onComplete=function(request){var object=eval(request.responseText);EJS.prototype.update.call(_template,element,object)};EJS.ajax_request(params)}else{element.innerHTML=this.render(options)}},out:function(){return this.template.out},set_options:function(options){this.type=options.type||EJS.type;this.cache=options.cache!=null?options.cache:EJS.cache;this.text=options.text||null;this.name=options.name||null;this.ext=options.ext||EJS.ext;this.extMatch=new RegExp(this.ext.replace(/\./,"."))}};EJS.endExt=function(path,match){if(!path){return null}match.lastIndex=0;return path+(match.test(path)?"":this.ext)};EJS.Scanner=function(source,left,right){extend(this,{left_delimiter:left+"%",right_delimiter:"%"+right,double_left:left+"%%",double_right:"%%"+right,left_equal:left+"%=",left_comment:left+"%#"});this.SplitRegexp=left=="["?/(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/:new RegExp("("+this.double_left+")|(%%"+this.double_right+")|("+this.left_equal+")|("+this.left_comment+")|("+this.left_delimiter+")|("+this.right_delimiter+"\n)|("+this.right_delimiter+")|(\n)");this.source=source;this.stag=null;this.lines=0};EJS.Scanner.to_text=function(input){if(input==null||input===undefined){return""}if(input instanceof Date){return input.toDateString()}if(input.toString){return input.toString()}return""};EJS.Scanner.prototype={scan:function(block){scanline=this.scanline;regex=this.SplitRegexp;if(!this.source==""){var source_split=rsplit(this.source,/\n/);for(var i=0;i0){for(var i=0;i0){buff.push(put_cmd+'"'+clean(content)+'")')}content="";break;case scanner.double_left:content=content+scanner.left_delimiter;break;default:content=content+token;break}}else{switch(token){case scanner.right_delimiter:switch(scanner.stag){case scanner.left_delimiter:if(content[content.length-1]=="\n"){content=chop(content);buff.push(content);buff.cr()}else{buff.push(content)}break;case scanner.left_equal:buff.push(insert_cmd+"(EJS.Scanner.to_text("+content+")))");break}scanner.stag=null;content="";break;case scanner.double_right:content=content+scanner.right_delimiter;break;default:content=content+token;break}}});if(content.length>0){buff.push(put_cmd+'"'+clean(content)+'")')}buff.close();this.out=buff.script+";";var to_be_evaled="/*"+name+"*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {"+this.out+" return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};";try{eval(to_be_evaled)}catch(e){if(typeof JSLINT!="undefined"){JSLINT(this.out);for(var i=0;i").replace(/''/g,"'")}return""}};EJS.newRequest=function(){var factories=[function(){return new ActiveXObject("Msxml2.XMLHTTP")},function(){return new XMLHttpRequest()},function(){return new ActiveXObject("Microsoft.XMLHTTP")}];for(var i=0;i")};EJS.Helpers.prototype.start_tag_for=function(A,B){return this.tag(A,B)};EJS.Helpers.prototype.submit_tag=function(A,B){B=B||{};B.type=B.type||"submit";B.value=A||"Submit";return this.single_tag_for("input",B)};EJS.Helpers.prototype.tag=function(C,E,D){if(!D){var D=">"}var B=" ";for(var A in E){if(E[A]!=null){var F=E[A].toString()}else{var F=""}if(A=="Class"){A="class"}if(F.indexOf("'")!=-1){B+=A+'="'+F+'" '}else{B+=A+"='"+F+"' "}}return"<"+C+B+D};EJS.Helpers.prototype.tag_end=function(A){return""};EJS.Helpers.prototype.text_area_tag=function(A,C,B){B=B||{};B.id=B.id||A;B.name=B.name||A;C=C||"";if(B.size){B.cols=B.size.split("x")[0];B.rows=B.size.split("x")[1];delete B.size}B.cols=B.cols||50;B.rows=B.rows||4;return this.start_tag_for("textarea",B)+C+this.tag_end("textarea")};EJS.Helpers.prototype.text_tag=EJS.Helpers.prototype.text_area_tag;EJS.Helpers.prototype.text_field_tag=function(A,C,B){return this.input_field_tag(A,C,"text",B)};EJS.Helpers.prototype.url_for=function(A){return'window.location="'+A+'";'};EJS.Helpers.prototype.img_tag=function(B,C,A){A=A||{};A.src=B;A.alt=C;return this.single_tag_for("img",A)} \ No newline at end of file diff --git a/app/libs/view.js b/app/libs/view.js new file mode 100644 index 0000000..9c969a9 --- /dev/null +++ b/app/libs/view.js @@ -0,0 +1,200 @@ +EJS.Helpers.prototype.date_tag = function(name, value , html_options) { + if(! (value instanceof Date)) + value = new Date() + + var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + var years = [], months = [], days =[]; + var year = value.getFullYear(); + var month = value.getMonth(); + var day = value.getDate(); + for(var y = year - 15; y < year+15 ; y++) + { + years.push({value: y, text: y}) + } + for(var m = 0; m < 12; m++) + { + months.push({value: (m), text: month_names[m]}) + } + for(var d = 0; d < 31; d++) + { + days.push({value: (d+1), text: (d+1)}) + } + var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} ) + var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'}) + var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'}) + + return year_select+month_select+day_select; +} + +EJS.Helpers.prototype.form_tag = function(action, html_options) { + + + html_options = html_options || {}; + html_options.action = action + if(html_options.multipart == true) { + html_options.method = 'post'; + html_options.enctype = 'multipart/form-data'; + } + + return this.start_tag_for('form', html_options) +} + +EJS.Helpers.prototype.form_tag_end = function() { return this.tag_end('form'); } + +EJS.Helpers.prototype.hidden_field_tag = function(name, value, html_options) { + return this.input_field_tag(name, value, 'hidden', html_options); +} + +EJS.Helpers.prototype.input_field_tag = function(name, value , inputType, html_options) { + + html_options = html_options || {}; + html_options.id = html_options.id || name; + html_options.value = value || ''; + html_options.type = inputType || 'text'; + html_options.name = name; + + return this.single_tag_for('input', html_options) +} + +EJS.Helpers.prototype.is_current_page = function(url) { + return (window.location.href == url || window.location.pathname == url ? true : false); +} + +EJS.Helpers.prototype.link_to = function(name, url, html_options) { + if(!name) var name = 'null'; + if(!html_options) var html_options = {} + + if(html_options.confirm){ + html_options.onclick = + " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} " + html_options.confirm = null; + } + html_options.href=url + return this.start_tag_for('a', html_options)+name+ this.tag_end('a'); +} + +EJS.Helpers.prototype.submit_link_to = function(name, url, html_options){ + if(!name) var name = 'null'; + if(!html_options) var html_options = {} + html_options.onclick = html_options.onclick || '' ; + + if(html_options.confirm){ + html_options.onclick = + " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} " + html_options.confirm = null; + } + + html_options.value = name; + html_options.type = 'submit' + html_options.onclick=html_options.onclick+ + (url ? this.url_for(url) : '')+'return false;'; + //html_options.href='#'+(options ? Routes.url_for(options) : '') + return this.start_tag_for('input', html_options) +} + +EJS.Helpers.prototype.link_to_if = function(condition, name, url, html_options, post, block) { + return this.link_to_unless((condition == false), name, url, html_options, post, block); +} + +EJS.Helpers.prototype.link_to_unless = function(condition, name, url, html_options, block) { + html_options = html_options || {}; + if(condition) { + if(block && typeof block == 'function') { + return block(name, url, html_options, block); + } else { + return name; + } + } else + return this.link_to(name, url, html_options); +} + +EJS.Helpers.prototype.link_to_unless_current = function(name, url, html_options, block) { + html_options = html_options || {}; + return this.link_to_unless(this.is_current_page(url), name, url, html_options, block) +} + + +EJS.Helpers.prototype.password_field_tag = function(name, value, html_options) { return this.input_field_tag(name, value, 'password', html_options); } + +EJS.Helpers.prototype.select_tag = function(name, value, choices, html_options) { + html_options = html_options || {}; + html_options.id = html_options.id || name; + html_options.value = value; + html_options.name = name; + + var txt = '' + txt += this.start_tag_for('select', html_options) + + for(var i = 0; i < choices.length; i++) + { + var choice = choices[i]; + var optionOptions = {value: choice.value} + if(choice.value == value) + optionOptions.selected ='selected' + txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option') + } + txt += this.tag_end('select'); + return txt; +} + +EJS.Helpers.prototype.single_tag_for = function(tag, html_options) { return this.tag(tag, html_options, '/>');} + +EJS.Helpers.prototype.start_tag_for = function(tag, html_options) { return this.tag(tag, html_options); } + +EJS.Helpers.prototype.submit_tag = function(name, html_options) { + html_options = html_options || {}; + //html_options.name = html_options.id || 'commit'; + html_options.type = html_options.type || 'submit'; + html_options.value = name || 'Submit'; + return this.single_tag_for('input', html_options); +} + +EJS.Helpers.prototype.tag = function(tag, html_options, end) { + if(!end) var end = '>' + var txt = ' ' + for(var attr in html_options) { + if(html_options[attr] != null) + var value = html_options[attr].toString(); + else + var value='' + if(attr == "Class") // special case because "class" is a reserved word in IE + attr = "class"; + if( value.indexOf("'") != -1 ) + txt += attr+'=\"'+value+'\" ' + else + txt += attr+"='"+value+"' " + } + return '<'+tag+txt+end; +} + +EJS.Helpers.prototype.tag_end = function(tag) { return ''; } + +EJS.Helpers.prototype.text_area_tag = function(name, value, html_options) { + html_options = html_options || {}; + html_options.id = html_options.id || name; + html_options.name = html_options.name || name; + value = value || '' + if(html_options.size) { + html_options.cols = html_options.size.split('x')[0] + html_options.rows = html_options.size.split('x')[1]; + delete html_options.size + } + + html_options.cols = html_options.cols || 50; + html_options.rows = html_options.rows || 4; + + return this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea') +} +EJS.Helpers.prototype.text_tag = EJS.Helpers.prototype.text_area_tag + +EJS.Helpers.prototype.text_field_tag = function(name, value, html_options) { return this.input_field_tag(name, value, 'text', html_options); } + +EJS.Helpers.prototype.url_for = function(url) { + return 'window.location="'+url+'";' +} +EJS.Helpers.prototype.img_tag = function(image_location, alt, options){ + options = options || {}; + options.src = image_location + options.alt = alt + return this.single_tag_for('img', options) +} diff --git a/app/partials/list.ejs b/app/partials/list.ejs new file mode 100644 index 0000000..c15539e --- /dev/null +++ b/app/partials/list.ejs @@ -0,0 +1,4 @@ + +<% for(var i=0; i +
<%= list[i].title %>
+<% } %> diff --git a/package.json b/package.json index 54d518a..afa825e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "express": "^4.13.4", "morgan": "^1.7.0", "serve-favicon": "^2.3.0", + "sqlite3": "^3.1.1", "string": "^3.3.1" }, "devDependencies": { diff --git a/recipe-server.js b/recipe-server.js index 15fef43..eb07caa 100644 --- a/recipe-server.js +++ b/recipe-server.js @@ -5,9 +5,12 @@ var express = require('express'), path = require('path'), http = require('http') logger = require('morgan'), cookieParser = require('cookie-parser'), bodyParser = require('body-parser'), + recipes = require('./server/recipes') +/* routes = require('./routes/index'), users = require('./routes/users') +*/ //train = require('lib/train') @@ -22,9 +25,9 @@ app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname, 'app'))); -app.use('/', routes); +app.use('/recipes', recipes); //app.use('/users', users); /* diff --git a/server/body.html b/server/body.html index 8ad48e5..73d0fdb 100644 --- a/server/body.html +++ b/server/body.html @@ -1,43 +1,47 @@ - + + + + + + + + + Shakshuka (Eggs Poached in Spicy Tomato Sauce) | Mark's Daily Apple + + + + + + + + - - - - - Health-Bent | Food Worth Eating | Mediterranean Beef Stew with Green Olive Pesto - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + +
+
+
+ Marks Daily Apple +
Serving up health and fitness insights (daily, of course) with a side of irreverence.
+
+ +
+
+
+ + +
+ + + +
+
+
+ +
+
+
+
+ 1 Sep
+
+
+

+ Shakshuka (Eggs Poached in Spicy Tomato Sauce)

+

Whether you’re looking for a new breakfast idea or are fond of serving breakfast for dinner, shakshuka fits the bill. Instead of calling the dish shakshuka you can also just call it “Eggs Poached in Spicy Tomato Sauce” because that’s exactly what this straightforward but surprisingly delicious meal is.

+

Especially popular in Israel, shakshuka is loved around the world for its comforting flavor and simple preparation. Although the sauce is often sopped up with pita bread, it’s thick enough that you can skip the bread and eat it with a spoon (or spread extra sauce over a hunk of grilled meat for a really fantastic meal.)

+

+

Most recipes for shakshuka call for canned (or boxed) tomatoes, but you shouldn’t hesitate to use plump, super-ripe fresh tomatoes if you can find them. Tomatoes are the main ingredient in shakshuka and some say that little else, besides eggs and garlic, should be added. However, this version leans in the direction of spicing things up with more flavor and variety. Onion, bell pepper, jalapeno, cumin and paprika make the meal more than just a pot of simmered tomatoes.

+

The eggs are added at the end and then cooked until just set. The contrasting flavors and textures in your bowl – creamy, soft eggs swimming in thick, spicy sauce – is what shakshuka is all about.

+

Servings: 4

+

Ingredients:

+ +
    +
  • 1/4 cup olive oil
  • +
  • 1 to 3 jalapeno peppers, (depending on how spicy you like it) seeded and finely chopped
  • +
  • 1 green bell pepper, cut into thin strips
  • +
  • 1 white or yellow onion, finely chopped
  • +
  • 4 cloves of garlic, finely chopped
  • +
  • 1/2 teaspoon ground cumin
  • +
  • 2 teaspoons paprika
  • +
  • 28-ounces whole peeled tomatoes in their juice or 2 pounds fresh tomatoes, chopped
  • +
  • 4 to 6 eggs
  • +
  • 1/4 cup roughly chopped parsley
  • +
  • Optional: crumbled feta cheese
  • +
  • Salt to taste
  • +
+

Instructions:

+

Preheat the oven to 400 degrees Fahrenheit.

+

Heat olive oil over medium-high heat in a deep skillet. Add peppers and onion and sauté until onion is lightly browned, about five minutes.

+ +

Add garlic, cumin and paprika and sauté one minute more.

+ +

Add tomatoes. Break them apart with a large spoon or spatula as they cook. Reduce heat slightly and simmer 15-20 minutes (longer if tomatoes are fresh), stirring occasionally, until sauce has thickened and most of the liquid is gone. Add salt to taste.

+ +

Crack the eggs evenly around the skillet. Place the skillet in the oven and cook until the egg whites are set, 6-8 minutes.

+ +

Garnish with parsley (and feta). Serve warm.

+


+ +

+ + +

+ +
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+

You want comments? We got comments:

+

Imagine you’re George Clooney. Take a moment to admire your grooming and wit. Okay, now imagine someone walks up to you and asks, “What’s your name?” You say, “I’m George Clooney.” Or maybe you say, “I’m the Clooninator!” You don’t say “I’m George of George Clooney Sells Movies Blog” and you certainly don’t say, “I’m Clooney Weight Loss Plan”. So while spam is technically meat, it ain’t anywhere near Primal. Please nickname yourself something your friends would call you.

+
+ +
    +
  1. +
    +
    +
    +

    eggs poached in bone broth is delicious too

    +
    +
    +
    +
    Jake wrote on September 1st, 2012
    + +
    +
    + +
  2. +
  3. +
    +
    +
    +

    I winged a version of shakshuka the other day and it’s since become my favorite breakfast. love it! we have some wilting bell peppers in the fridge so I have a feeling I’ll be making your version soon enough!

    +
    +
    +
    +
    alexandra @ sweet betweens [blog] wrote on September 1st, 2012
    + +
    +
    + +
  4. +
  5. +
    +
    +
    +

    Sounds good, and simple to make. Will try it for breakfast tomorrow.

    +
    +
    +
    +
    Anders wrote on September 1st, 2012
    + +
    +
    + +
  6. +
  7. +
    +
    +
    +

    My Italian grandmother made these — they were called “Eggs in Purgatory.”

    +
    +
    +
    +
    honeybee wrote on September 1st, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      Yes, I was taught this last year by a Neapolitan. Great name for a dish. And you can do it with less ingredients. For one person I use 1 onion, 1 can of tomatoes, and 3 eggs. Delicious. But I might add the feta, for something new.

      +
      +
      +
      +
      Michelle wrote on September 1st, 2012
      + +
      +
      + +
    • +
    • +
      +
      +
      +

      YES! Eggs in purgatory is how I know these. Also, there is no reason to complicate things by heating your oven up. Just poach them as is. Put a lid on if you want the tops a little firmer.

      +
      +
      +
      +
      Paleo-Leo wrote on September 4th, 2012
      + +
      +
      + +
    • +
    +
  8. +
  9. +
    +
    +
    +

    Hi!
    +It’s so nice to see a shakshuka recipe here on my favorite blog!
    +Being Israeli, seeing the shakshuka definitely brings stuff back!
    +I would say this is an extremely refined version that you put up here! I actually never used an oven! just simmered the tomatoes and bell peppers in the covered skillet until thick!
    +In fact, it is a long and ancient tradition (30 years or so), to make shakshuka in a skillet over a fire on the beach:) very very primal event:)
    +I have been eating it primally (sans pita) forever and i can testify that it is indeed a very comforting and satiating food.
    +Anyway I just wanted to say that I really enjoyed seeing this food in a primal context, made me think of the positive things at home when I’m so far away… Thanks Mark!

    +
    +
    +
    +
    Roaming Wanderer wrote on September 1st, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      Mark, you made me cry in a good endearing way!! I agree, food is a comforting way of sending LOVE to your Heart!! I love the name SHAKSHUKA it means so much vibration to me!! I LOVE the Isreali way!! Literally!! Eggs Purgatory just doesn’t feel right to me although it is in Dante’s original language. I love fresh meat SHAKSHUKA for breakfast!! A better way to start the day rather than Kellog’s!! HA HA I am a person of substance and that is how I choose to eat and live!! Skakshuka says that in a name for me!!!
      +Peace and keep on SHAKSHUKING!!!!!
      +KLC

      +
      +
      +
      +
      Karen wrote on February 17th, 2013
      + +
      +
      + +
    • +
    +
  10. +
  11. +
    +
    +
    +

    We call that Juevos Rancheros here in the south!

    +
    +
    +
    +
    Shara wrote on September 1st, 2012
    + +
    +
    + +
  12. +
  13. +
    +
    +
    +

    Look delicious.. adding this to my breakfast list!

    +
    +
    +
    +
    Gift Clumsywarrior wrote on September 1st, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      You won’t be disappointed, strangely enough though, it is usually a dinner dish! :)

      +
      +
      +
      +
      Primal Wanderer wrote on September 1st, 2012
      + +
      +
      + +
        +
      • +
        +
        +
        +

        hah that’s interesting but yeah, this dish cooking time is more appropriate for dinner too. (I usually spend 5 mins on average making breakfast =p)

        +
        +
        +
        +
        Gift Clumsywarrior wrote on September 1st, 2012
        + +
        +
        + +
          +
        • +
          +
          +
          +

          :) I guess it could work as an extra fancy Sunday breakfast… or a brunch kind of thing…
          +I usually skip breakfast altogether, eating breakfast usually makes me hungrier later in the day. I guess I’m IF’ing by default hehe.

          +
          +
          +
          +
          Primal Wanderer wrote on September 2nd, 2012
          +
          +
          + +
        • +
        +
      • +
      +
    • +
    +
  14. +
  15. +
    +
    +
    +

    A variation on this theme is very Italian, just substitute the feta for scamorza and make it less spicy!

    +

    http://www.davidrocco.com/recipes/mains/fried_eggs_scamorza.asp

    +
    +
    +
    +
    Cody wrote on September 1st, 2012
    + +
    +
    + +
  16. +
  17. +
    +
    +
    +

    I don’t think I would be able to skip the pita bread. Scooping up all that sauce with just a spoon doesn’t seem right.

    +
    +
    +
    +
    James wrote on September 1st, 2012
    + +
    +
    + +
  18. +
  19. +
    +
    +
    +

    I just made this. Pretty good. I added some sausage in with the onion, for extra juiciness.

    +
    +
    +
    +
    Daniel wrote on September 1st, 2012
    + +
    +
    + +
  20. +
  21. +
    +
    +
    +

    Holy Crap. I was in Israel for 3 months this past spring and we probably had shakshuka every single day. It is pretty primally delicious. Some people like to mix the eggs up in the sauce also. I just enjoy popping the yolk and mixing it in with the rest of the vegetables. You can also add some sausage to this and it is freakin delish.

    +
    +
    +
    +
    Max Ungar wrote on September 1st, 2012
    + +
    +
    + +
  22. +
  23. +
    +
    +
    +

    An Israeli houseguest cooked me this for dinner a few months ago, and I was planning to try my hand at making it up tonight. His version was very Italian-inspired, with lots of garlic and oregano, and big chunks of onions and peppers. It was fantastic.

    +
    +
    +
    +
    ajt wrote on September 1st, 2012
    + +
    +
    + +
  24. +
  25. +
    +
    +
    +

    Hint: for those of you who want an extra thick and creamy sauce, you can try mixing one whole egg into the tomato-pepper mixture as it simmers (right before you’d add in the other eggs), it will thicken up the sauce and will solidify a bit the whole thing so you’ll be able to eat it with a fork!
    +(skip that pitaaaa:))
    +Yep!

    +
    +
    +
    +
    Primal Wanderer wrote on September 1st, 2012
    + +
    +
    + +
  26. +
  27. +
    +
    +
    +

    Any thoughts on anti depressants and anxiety? My doc has urged me to take them for the last 2 yeras…
    +– I’m gloomy, unmotivated
    +– aches, pains (but also low weight)
    +– easy distracted
    +– always “on edge” and anxious like
    +– irritated super easy
    +– always worrying and regretting stuff

    +

    would GABA and OR 5-HTP be better? or just bit the bullet and take mirtazapine and lorazapam? the mirtazapine i dont wanna take cause it causes weight gain (whcih admittedly i need….but in an unnatural way it seems “wrong”)

    +

    i need something for sleep and to lift the anxiety and depression

    +

    By the way not paleo…lots of digestive issues…but don’t think i could be paleo since i live in a place and have a wallet unable to get ANYTHING grassfed, etc and if i overdose on fat (cause i need to gain weight, not lose) i tend to get sickish…

    +
    +
    +
    +
    Jeri wrote on September 1st, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      I sleep better when I take 5-HTP after dinner. I also have had success with Sedalia Stress Relief by Boiron. It’s a homeopathic, dissolve under the tongue tablet I get at at Sprouts or Sunflower or Whole Foods. It helps me with quite a bit with anxiety.

      +

      I had many digestive problems such as gas, bloating, cramping, diarrhea, constipation, etc. They all went away when I stopped eating grains. I don’t miss them either.

      +

      I wish you luck in your quest and am glad you are trying to find a better way than pharmaceuticals.

      +
      +
      +
      +
      Katydid wrote on September 1st, 2012
      + +
      +
      + +
        +
      • +
        +
        +
        +

        Thanks for the reply :)
        +Does the 5-HTP help with the depression or the anxiety?
        +I am:
        +– low weight
        +– anxious, “on edge” all the time
        +– irritate
        +– not energetic, lethargic, achy
        +– unmotivated
        +– sad at times…

        +

        you found grains the MAIN source of digestive troubles? I assume mine might be due to dairy or maybe egg allergies…eliminating stuff is toughie for me when low weight, ugh

        +

        i was wondering about GABA?…

        +

        i’m afraid of the mirtazapine becuz while its awesome for sleep…it does cause some constipation AND weight gain (yes, i need the weight gain…but in that way?..idk).

        +
        +
        +
        +
        Jeri wrote on September 2nd, 2012
        + +
        +
        + +
      • +
      +
    • +
    • +
      +
      +
      +

      Hi Jeri – I would give the mirtazapine and lorazepam a shot. If they help, then you can use them temporarily as you work on and learn new ways to decrease the anxiety and gloominess. The weight gain from these meds comes from carb binging. I think if you make wise choices, it won’t be cheating; you’ll be winning the battle.

      +
      +
      +
      +
      Brian wrote on September 2nd, 2012
      + +
      +
      + +
        +
      • +
        +
        +
        +

        Hi, thanks for reply…I’m worried though becuz the carb binging is becuz of an excessive high need for sweets and carbs and i have no willpower :( I also hear the drug lowers your metabolism hence the gain…I’m in my 30’s , i don’t wanna screw with my metabolism :(

        +
        +
        +
        +
        Jeri wrote on September 2nd, 2012
        + +
        +
        + +
      • +
      +
    • +
    • +
      +
      +
      +

      Stay away from the lorazepam. It’s highly addictive and a bitch to withdrawal from.
      +Trust me on this one.

      +
      +
      +
      +
      honeybee wrote on September 2nd, 2012
      + +
      +
      + +
        +
      • +
        +
        +
        +

        any alternatives you know of ? safe ones?

        +
        +
        +
        +
        Jeri wrote on September 2nd, 2012
        + +
        +
        + +
          +
        • +
          +
          +
          +

          Jeri: I empathize with your situation,having been through it, and I understand the impulse to want think that just finding the right thing to take will make the problem get better quickly. It’s normal, but a dead end, as I know from bitter experience.

          +

          Having been through a long slog with withdraw with various pharma “solutions,” the best advice I can give is to suggest that you find a cognitive behavioral therapist and try that route first. You could try acupunture and I would also seek out a trained homeopathic doctor. Perhaps a naturopathic doctor could also help you find a solution.

          +

          Believe me, I wish I had done this before I got caught in the horrible web of psychoactive pharma drugs. The difficulty of the withdrawal process (even from SSRIs)cannot be adequately described. It’s hell. The benzos will definitely wreck your life.

          +

          Getting out from under depression and anxiety is possible, but it takes time, patience,courage and hard work. Unforunately, there really is no easy, quick and painless way through.

          +
          +
          +
          +
          honeybee wrote on September 2nd, 2012
          +
          +
          + +
        • +
        • +
          +
          +
          +

          thanks honeybee…BUT homeopathic and acupuncture and naturopaths cause major money…I don’t have money. I’m a below-below-below average fincanical situation and can barely pay rent. So I know with my heart that naturopaths and homeopaths and acupuncture would Be AMAZING…but i just cna’t afford it…
          +I read “The Depression Cure”, “Unstuck” and “Spent” and “The FOod Mood Solution” and they all resonated with me…the best I can do i pick out pieces that i CAN afford….and otherwise, have a little faith.
          +The depression is one thing to deal with. The damn anxiey and low weight is another thing. I’m a ball of lethargy. And i have a TON of digestive troubles (I don’t eat paleo, but don’t see how I could seeing where i live…ii already eat tons of fats)…anyway..i’ll shut up now :)

          +
          +
          +
          +
          jeri wrote on September 3rd, 2012
          +
          +
          + +
        • +
        • +
          +
          +
          +

          Hey Jeri , I think yoga and meditation would help you more than any drug. The best thing about yoga is that there are huge varieties of asnas to choose from. You can adapt any that works for you. Yoga helps in detoxifiyng the body. Your problems arise mainly due to stress and negativity. Once you conquer that you are surely gonna be on the path of healing. Give it a try. You could be amazed at the results.

          +
          +
          +
          +
          fathima wrote on September 7th, 2012
          +
          +
          + +
        • +
        • +
          +
          +
          +

          It seems that ending it all would be best. With such dependence on assistance – when all that’s really needed is proper diet and movement – you should consider just giving up. The “I’m not okay – you’re not okay” mindset is a difficult one…best to press the [RESET] before you cause more problems for those around you.

          +
          +
          +
          +
          Nate wrote on October 4th, 2012
          +
          +
          + +
        • +
        +
      • +
      +
    • +
    • +
      +
      +
      +

      We have had similar problems at my house and the solution was twofold:
      +1. Stop eating wheat
      +2. Take magnesium and zinc supplements.
      +Those two things have done us more good than you can imagine. Try it!

      +
      +
      +
      +
      Laura F wrote on September 2nd, 2012
      + +
      +
      + +
        +
      • +
        +
        +
        +

        Hi, but is it intense depression and intense anxiety (like the kind i described above….cause its not just the regular stuff )….I do take Mg natural calm :)
        +and i take cod liver oil, multi, vit B, vit C, and vit D..
        +was thinking about taking some L-glutamine cause i hear it helps the GI tract .
        +I haven’t eaten wheat in years. Gluten free.

        +
        +
        +
        +
        Jeri wrote on September 2nd, 2012
        + +
        +
        + +
      • +
      +
    • +
    • +
      +
      +
      +

      Hi Jeri, maybe start by reading around John McManamy’s stuff for awhile? Definitely helped me get out of my last low cycle…

      +

      http://www.mcmanweb.com/index.html

      +
      +
      +
      +
      Khainag wrote on September 5th, 2012
      + +
      +
      + +
    • +
    • +
      +
      +
      +

      Hey there Jeri,

      +

      Sorry if this has already been said. I have to start work in 5 minutes so I haven’t read all of your replies etc.

      +

      I was in a really dire finacial situation with severe depression/anxiety some years back and I found that the thing that kept me afloat until I could afford more help was walking every day, drinking plenty of water, cutting grain except rice (cheap) and meditation. On days when I didnt “Feel” it I still did the walk and the meditiation and viewed it as medicinal. I also did a negativity fast where I immediately cut short any negative thoughts even if they seemed rational.

      +

      It really did help.

      +

      I hope you feel better soon and that your situation also improves.

      +

      Kindest,

      +

      PrimalJasper

      +
      +
      +
      +
      Primal Jasper wrote on September 7th, 2012
      + +
      +
      + +
    • +
    • +
      +
      +
      +

      GABA and Sam-e are both helpful… Under “normal” circumstances (work stress, household concerns, etc), 400 mg Sam-e in the morning and 750 mg GABA at night works great. I’ve varied dosages depending on stress levels and it really helps. My husband says it helps his anxiety, concentration (he has ADHD), and excessive sweating as well.

      +

      As far as digestive troubles, try adding chia seeds to your diet. (They can be ordered from Amazon for a pretty reasonable price.) Aloe vera juice (the natural, unsweetened kind) can also help with issues.

      +
      +
      +
      +
      Cristy wrote on October 3rd, 2012
      + +
      +
      + +
    • +
    +
  28. +
  29. +
    +
    +
    +

    Feta cheese is an awesome addition to a Shakshuka. Marguez sausage is also a classic, but my favorite would have to be spinach, which improves both taste and texture.

    +
    +
    +
    +
    Yonatan wrote on September 2nd, 2012
    + +
    +
    + +
  30. +
  31. +
    +
    +
    +

    This is awesome! I actually gave my husband a recipe for a spicy tomato sauce that he whipped up the other day with real tomatoes, jalapenos, and whatnot. I literally have all the ingredients and could whip this up in 10 minutes, and I never thought to put it together this way. I didn’t even know I had a dinner dilemma, but this solved it.

    +
    +
    +
    +
    Deanna wrote on September 2nd, 2012
    + +
    +
    + +
  32. +
  33. +
    +
    +
    +

    This is an interesting coincidence – I had seen other similar presentations elsewhere, and they looked interesting to me, but just a bit more work than I want to do for breakfast or brunch.

    +

    Just a few days ago though, I had an inspiration for an easier version of this. My local market sells pre-made gazpacho, (which is made fresh, refrigerated, and has all-natural ingredients), so we poured some into a cast iron skillet, brought it to a simmer, and poached the eggs in it (covered) for about 5 minutes.

    +

    It was not only delicious, it was the ultimate in simplicity.

    +
    +
    +
    +
    Ken Green wrote on September 2nd, 2012
    + +
    +
    + +
  34. +
  35. +
    +
    +
    +

    I do a version of this every day as my breakfast. Super easy and fast. I just use some rotel tomatoes, along with a bit of chopped ham or sausage; heat, add a couple of eggs, cook until done (I like my eggs hard so I flip it). Top with a small dollop of labna.

    +
    +
    +
    +
    Robin wrote on September 2nd, 2012
    + +
    +
    + +
  36. +
  37. +
    +
    +
    +

    This looks great, I am going to try it this morning, but…how does 4 eggs serve 4 people? That’s got to be a typo. Who can stop at one egg?

    +
    +
    +
    +
    Sabine wrote on September 3rd, 2012
    + +
    +
    + +
  38. +
  39. +
    +
    +
    +

    Looks tasty and easy to make. I’ll try it tomorrow and let you know. Cheers

    +
    +
    +
    +
    Adam wrote on September 3rd, 2012
    + +
    +
    + +
  40. +
  41. +
    +
    +
    +

    All I had in the kitchen was egg, tomatoes, and garlic, so I thought I’d give shakshuka a try.

    +

    The tomatoes were small, underripe, and watery. I finely diced three and set them to drain on a tilted plate. Meanwhile in a non-stick frying pan I gently fried three chopped cloves of garlic in olive oil with a little black pepper. When the oil was nicely flavoured I added the tomato and left to simmer for 15 minutes. I added salt after about 5 minutes, and stirred occasionally.

    +

    Then I cracked two eggs on the mush, put a plate over the pan to retain the heat, and simmered until done.

    +

    Verdict: delicious.

    +

    Next time: The eggs were done unevenly (they’d do better in an oven with a cast iron skillet, but I have neither.) So I’ll try beating them and making basically an omelet on tomato sauce. Also, the tomatoes were still too watery. Maybe I’ll simmer them longer, although I get impatient. Also, they might taste better if peeled, but I’m too lazy to do it.

    +

    One nice thing is that you don’t have to stand at the stove the whole time. You can just leave it to simmer and do other stuff.

    +
    +
    +
    +
    Martin_B wrote on September 4th, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      I never peel the tomatoes, but I highly recommend using ripe tomatoes, even overripe! Like right before you’d throw them away-too soft for salad ripe! They definitely make the difference in a shakshuka!
      +Ideally I wait till I have 3-4 of these tomatoes (slightly wrinkled,soft spots etc.) this way I don’t waste food by thowing them away AND make great shakshuka! :)

      +
      +
      +
      +
      Primal Wanderer wrote on September 4th, 2012
      + +
      +
      + +
    • +
    +
  42. +
  43. +
    +
    +
    +

    This was absolutely fantastic – thanks!

    +
    +
    +
    +
    Mirella wrote on September 4th, 2012
    + +
    +
    + +
  44. +
  45. +
    +
    +
    +

    Thanks for the recipe!

    +

    Quick question.

    +

    Tomatoes in a cast iron skillet? I thought tha was no no – doesn’t the acid damage the skillet’s (seasoning; i.e. finish)?

    +
    +
    +
    +
    Marc wrote on September 4th, 2012
    + +
    +
    + +
      +
    • +
      +
      +
      +

      Hi Marc, yes the acid can take the seasoning off a cast iron pan, so you need to be careful. My suggestion is to get a Creuset type cast iron pan, it has an enamel coating over the cast iron and does not need seasoning. They are pricey but can be found sometimes at places like Home Goods for less. I highly recommend them! Also I think everyone should ditch their teflon/nonstick pans, those coatings are nasty.

      +

      I hope this is a help.

      +
      +
      +
      +
      Lisa in JP wrote on September 6th, 2012
      + +
      +
      + +
    • +
    +
  46. +
  47. +
    +
    +
    +

    Made this last night – so simple, so delicious. Chucked a thinly sliced aubergine (egg plant) in there too. This meal is going to be a new regular in our house!

    +
    +
    +
    +
    Jamie wrote on September 5th, 2012
    + +
    +
    + +
  48. +
  49. +
    +
    +
    +

    Whoa just had this for a breakfast/lunch at 2 pm… amazing. Did use some jarred tomatoes as the ones at the shop the other day looked a bit questionable, but will try it with fresh ASAP! If it tastes as good I won’t believe that I could make something so flavorful myself.

    +
    +
    +
    +
    Khainag wrote on September 5th, 2012
    + +
    +
    + +
  50. +
  51. +
    +
    +
    +

    I’ve been poaching eggs in Pace’s Picante Sauce for several years.

    +
    +
    +
    +
    Phocion Timon wrote on September 5th, 2012
    + +
    +
    + +
  52. +
  53. +
    +
    +
    +

    Shakshuka is popular for breakfast throughout the Middle East, especially in Egypt and Saudi Arabia. However, it’s normally eaten in a hot dog bun for a quick “on-the-go” breakfast or with Arabic flat-bread. There is another version in some Arab countries that goes by the wonderful name of “juz-muz”!

    +
    +
    +
    +
    Waleed wrote on September 5th, 2012
    + +
    +
    + +
  54. +
  55. +
    +
    +
    +

    Excellent dish recipe
    +I live in Greece, we make Shakshuka Greek.
    +Your recipe is similar recipe but with cheese and more ..

    +
    +
    +
    +
    chef tom wrote on September 5th, 2012
    + +
    +
    + +
  56. +
  57. +
    +
    +
    +

    Great with red peppers, or add in spinach and feta cheese, mushrooms optional

    +
    +
    +
    +
    chanah wrote on September 6th, 2012
    + +
    +
    + +
  58. +
  59. +
    +
    +
    +

    Hey Jeri I think u should try yoga and meditation. Your problem is not medical its spritual. There are many asnas which will heal you naturally. Don’t impurify ur blood using drugs to help u sleep. It ain’t worth it.

    +
    +
    +
    +
    fathima wrote on September 6th, 2012
    + +
    +
    + +
  60. +
  61. +
    +
    +
    +

    I will probably do a Tex-Mex version of this. All jalapenos, substitute Cilantro for Parsley and use Queso Fresca instead of Feta.

    +
    +
    +
    +
    Grace wrote on September 7th, 2012
    + +
    +
    + +
  62. +
  63. +
    +
    +
    +

    I have made this twice, the lazy way, with Ro-tel canned tomatoes and it is wonderful.

    +
    +
    +
    +
    Jenny wrote on September 13th, 2012
    + +
    +
    + +
  64. +
  65. +
    +
    +
    +

    Don not cook them until just set, cook until firm and they have the texture of GNOCCHI!

    +
    +
    +
    +
    Harry wrote on September 14th, 2012
    + +
    +
    + +
  66. +
  67. +
    +
    +
    +

    I’m thinking of adding some kielbasa. Does that sound good to anyone else?

    +
    +
    +
    +
    Dana wrote on October 14th, 2012
    + +
    +
    + +
  68. +
  69. +
    +
    +
    +

    Not sure if this has been mentioned yet, there are a lot of comments and I don’t feel like reading all of them.

    +

    In regards to canned tomatoes, if you don’t know this canned tomatoes are just as, if not better than fresh tomatoes. Most tomatoes in grocery stores are artificially ripened while the tomatoes in cans were picked and canned fresh. So unless you can get tomatoes from a farmers market, or until the day comes when you retire and dedicate your life to growing your own tomatoes, you’re best bet is always canned tomato.

    +
    +
    +
    +
    Bloop wrote on January 3rd, 2013
    + +
    +
    + +
  70. +
+ +
+
+

Leave a Reply

+ + + + +
+ + +

+

+

+

+

+

+ + +
+ + +
+ +

+ + +

+

+

If you'd like to add an avatar to all of your comments click here!

+ +
+
+
+
+
+ + + +
+ +
+ +
+
Like what you've seen?
+ Rss +

Subscribe to the RSS feed for daily emails:

+
+
+
+ + +
+
+ +
+
+ +
+
+
+
+
+
+
Looking for something specific?
+ + +
+
Or maybe you'd like to browse
+ posts about:
+ +
+
+
+
+

© 2016 Mark's Daily Apple

+
+
+
+ + + + + + + + + +
+ + + + + +
+

Subscribe to the Newsletter and Get a Free Copy
of Mark Sisson's Fitness eBook and more!

+
+
+ + +
+
+ +
+ + +
+ - - +.snp-theme1 .snp-footer .snp-no-thx { + color: #fff; +float: none; +} +.snp-pop-52648 .snp-theme1 .snp-subscribe-button, .snp-theme1 .snp-subscribe .snp-field { + font-size: 18px; +font-family: Arial, Helvetica, sans-serif; +} +.snp-fb, .snp-fb * { + background: #669900; +} +.snp-theme1 .snp-footer { +text-align: center; +} +.snp-theme1 .snp-footer .snp-privacy span { + margin-left: 24px; + color: #fff; +} +.snp-no-thx { +font-family: Arial, Helvetica, sans-serif; +} +.snp-theme1 .snp-columns { + margin-bottom: 0; +} +.snp-theme1 .snp-footer .snp-privacy:before { + content: none; +} +.snp-theme1 .snp-subscribe:after { +background: none; +} +.snp-theme1 .snp-field, .snp-theme1 .snp-subscribe-button { + border-radius: 0; +} +.snp-pop-52648 .snp-theme1 .snp-info, .snp-pop-52648 .snp-theme1 .snp-features { + float: none; + font-size: 18px; + font-style: normal; + font-weight: bold; + margin: auto; + text-align: center; + width: 100%; +}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - -
- -
- - - - - - - -
- - -
- -
- -
- - -
- -
- -
- - - - - - - -
- -
- - Beef Soups - -

Mediterranean Beef Stew with Green Olive Pesto

- - - - - -
- - - - -
- - -
Print Friendly


-Beef stew, also known as beef bourguignon, is good, but boring–and we personally think it tastes like straight up sour wine and that is not very tasty, especially by the spoonful. So we’ve added a bit of balsamic vinegar and raisins to counter the sour with a bit of sweet. We’re also swirling in a nice, briny, herbal pesto to brighten up the braise. Another change, we’re not using a crock pot! The dutch oven allows liquid to evaporate from the pot, thus creating a thicker, more intense flavored stew. And heck, I would rather eat in 2 hours than in 6 hours, agreed?

-

Ingredients

-
    -
  • 2 T fat of your choice
  • -
  • 2 lb. chuck shoulder, cubed
  • -
  • 1 yellow onion, chopped
  • -
  • 3 cloves garlic, finely chopped
  • -
  • 1 carrot, finely chopped
  • -
  • 3/4 c raisins
  • -
  • (1) 28 oz. can fire roasted crushed tomatoes
  • -
  • 1 c red wine
  • -
  • 1/4 c balsamic vinegar
  • -
  • 1 lemon, sliced and seeds removed
  • -
  • S&P
  • -
-

For the Pesto

-
    -
  • 1 handful of basil leaves
  • -
  • 1/2 handful of mint leaves
  • -
  • 1/2 c green olives (about 20)
  • -
  • 3 T extra virgin olive oil
  • -
-

Method

-

Preheat the oven to 350ºF.

-

In a dutch oven melt your fat. Salt and pepper the cubed chuck pieces, add them to the pot and let them brown on each side. Don’t fidget with them or remove them until you see a visible brown crust on the meat. Remove and reserve on a plate.  To the pot, add the onion, garlic and carrot. Let them sweat and saute until soft, about 10 minutes. Add the meat back to the pot, along with the tomatoes, raisins, red wine and balsamic vinegar. Stir to combine. Top with sliced lemons.

-

-

Lay a piece of parchment paper of the the top of the pot and press it down into the pot. Place in the oven and braise for 2 hours. Taste the meat, it should be super tender, if it’s not give it another half hour or so.

-

Once you’re about 10 minutes from the stew finishing; combine all the ingredients for the pesto in a mini food processor. Pulse until everything has come together.

-

When the stew is out of the oven, take the lemon rinds out, but leave in the flesh…it’ll separate very easily. Swirl in the pesto and serve.

-
- - - - -
- - -
- - - - - - - -
- - -

You Might Also Like

- - - -
-
- - - - - - -
- - - -
- - -
- - - -
- -
- - - - - -
- -
- -
- - - - - - - - - - + + + - - - + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/server/grab.js b/server/grab.js deleted file mode 100644 index 24f9755..0000000 --- a/server/grab.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Created by Martin on 22/02/2016. - */ - -var http = require('http'), request = require('request'), cheerio = require('cheerio'), util = require('util'); -var jsonfile = require('jsonfile'), fs = require('fs'), STRING = require('string'); -var log4js = require('log4js'); -var logger = log4js.getLogger(); - -var bodyfile = __dirname + '/' + 'body.html'; -var htmlfile = __dirname + '/' + 'testoutput.html'; -var generics = ['ARTICLE', 'div.content_column', 'div.post']; - -function cleaner(b) { - var _b = b; - - var unwanted = ['div#disqus_thread', 'SCRIPT', 'FOOTER', 'div.ssba', '.shareaholic-canvas', '.yarpp-related', 'div.dfad', 'div.postFooterShare', 'div#nextPrevLinks','.post-comments']; - - for (var i = 0; i < unwanted.length; i++) { - _b.find(unwanted[i]).remove(); - } - return _b; -} - -module.exports = { - - generic: function (url) { - logger.info(url); - request(url, function (err, resp, body) { - if (err) - throw err; - - $ = cheerio.load(body); - var title = $('TITLE').text(); - - // try to find a body to grab - - var i = 0; - - while (($(generics[i]).length == 0) && (i < generics.length)) { - - i++; - } - logger.debug(i); - - if (i < generics.length) { - var tdihbody = $(generics[i]); - logger.debug(tdihbody.length); - - tdihbody = cleaner(tdihbody); - logger.debug(title); - - fs.writeFileSync(htmlfile, tdihbody.html()); - } - fs.writeFileSync(bodyfile, $.html()); - }); - } -}; - -//module.exports.grabMarksDailyApple('http://www.marksdailyapple.com/spiced-pork-and-butternut-squash-with-sage'); -module.exports.generic('http://www.health-bent.com/soups/paleo-mediterranean-beef-stew'); \ No newline at end of file diff --git a/server/recipes.js b/server/recipes.js new file mode 100644 index 0000000..c1e93ed --- /dev/null +++ b/server/recipes.js @@ -0,0 +1,215 @@ +/** + * Created by Martin on 22/02/2016. + */ +var express = require('express'); +var http = require('http'), request = require('request'), cheerio = require('cheerio'), util = require('util'); +var jsonfile = require('jsonfile'), fs = require('fs'), STRING = require('string'); +var log4js = require('log4js'); +var logger = log4js.getLogger(); + +var router = express.Router(); + +var sqlite3 = require('sqlite3').verbose(); +var EventEmitter = require('events'); +var busEmitter = new EventEmitter(); + +var dbfile = process.env.DB_HOME + '/' + "recipes.db"; +var bodyfile = __dirname + '/' + 'body.html'; +var htmlfile = __dirname + '/' + 'testoutput.html'; +var generics = ['ARTICLE', 'div.content_column', 'div.post']; + +var db; + +function createDB() { + logger.debug('Creating recipes db...'); + logger.debug(dbfile); + if (!fs.existsSync(dbfile)) { + logger.debug('creating db file'); + fs.openSync(dbfile, 'w'); + db = new sqlite3.Database(dbfile, createTable); + db.close(); + } + else { + logger.info('Database already created.'); + connectDB(); + } +} + +function connectDB() { + "use strict"; + logger.debug('Connect db.'); + db = new sqlite3.Database(dbfile); + //logger.debug(temp_db); + + return db; +} + +function createTable() { + logger.debug('Creating temp table...'); + db.run('CREATE TABLE `recipes` (`id` INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, `url` TEXT, `html` TEXT, `reduced` TEXT );'); + +} + +function closeDB() { + "use strict"; + logger.debug('Closing db.'); + db.close(); +} + +function cleaner(b) { + var _b = b; + + var unwanted = ['div#disqus_thread', 'SCRIPT', 'FOOTER', 'div.ssba', '.shareaholic-canvas', '.yarpp-related', 'div.dfad', 'div.postFooterShare', 'div#nextPrevLinks', '.post-comments']; + + for (var i = 0; i < unwanted.length; i++) { + _b.find(unwanted[i]).remove(); + } + return _b; +} + +function insertRecipe(obj) { + logger.debug(obj); + + db.run('BEGIN TRANSACTION'); + db.run('INSERT INTO `recipes`(`url`,`html`,`reduced`,`title`) VALUES (?,?,?,?);', obj); + db.run('commit'); +} + +var doInsertRecipe = (obj) =>{ + // logger.info('sendSocket: ' + JSON.stringify(obj)); + insertRecipe(obj); +} + +var doGetRecipe = (url) =>{ + // logger.info('sendSocket: ' + JSON.stringify(obj)); + genericGrab(url); +} + + +busEmitter.on('saveRecipeData', doInsertRecipe); + +busEmitter.on('getRecipe', doGetRecipe); + +function genericGrab(url) { + logger.info(url); + request(url, function (err, resp, body) { + if (err) + throw err; + + $ = cheerio.load(body); + var title = $('TITLE').text(); + + // try to find a body to grab + + var i = 0; + + while (($(generics[i]).length == 0) && (i < generics.length)) { + + i++; + } + logger.debug(i); + + if (i < generics.length) { + var tdihbody = $(generics[i]); + var obj = []; + + logger.debug(tdihbody.length); + tdihbody = cleaner(tdihbody); + logger.debug(title); + fs.writeFileSync(htmlfile, tdihbody.html()); + obj.push(url); + obj.push($.html()); + obj.push(tdihbody.html()); + obj.push(title); + busEmitter.emit("saveRecipeData", obj); + + } + fs.writeFileSync(bodyfile, $.html()); + }); +} + + +router.get('/list', function(req, res) { + logger.debug('list..'); + + // 'select id, title from `recipes` where title is not null;' + db.all('select id, title from `recipes` where title is not null;', function (err, rows) { + + var out = []; + // logger.debug(err); + // logger.debug(rows); + rows.forEach(function (row) { + + out.push({"id": row.id, "title": row.title}); + }); + + res.writeHead(200, {"ContentType": "application/json"}); + //res.send(JSON.stringify(t)); + res.end(JSON.stringify({list:out})); + + //closeDB(); + }); +}); + +router.get('/entry/:id', function(req, res) { + logger.debug('entry..'); + + logger.debug(req.params.id); + // 'select id, title from `recipes` where title is not null;' + var sqlstr = 'select * from `recipes` where id = ' + req.params.id + ';'; + db.all(sqlstr, function (err, rows) { + + var out = []; + // logger.debug(err); + // logger.debug(rows); + rows.forEach(function (row) { + + var d = {"id": row.id, "title": row.title}; + + if (row.reduced.length !== 0) { + d.body = row.reduced; + } + else + { + d.body = row.html; + } + out.push(d); + }); + + res.writeHead(200, {"ContentType": "application/json"}); + //res.send(JSON.stringify(t)); + res.end(JSON.stringify({list:out})); + + //closeDB(); + }); +}); + +router.post('/add', function(req, res) { + logger.debug('add entry..'); + + var t = req.body; + if (t.hasOwnProperty('url')) { + var url = JSON.parse(t.url.toString()); + + logger.debug(url); + busEmitter.emit("getRecipe", url); + + + /* if (data.hasOwnProperty('temp')) { + // busEmitter.emit("saveTempData", {time: now.toJSON(), value: parseFloat(data.temp)}); + } + else { + logger.error('No url to add!'); + }*/ + } + else { + logger.error('No data block!'); + } + +}); + +module.exports = router; + +createDB(); +//module.exports.grabMarksDailyApple('http://www.marksdailyapple.com/spiced-pork-and-butternut-squash-with-sage'); +//module.exports.generic('http://www.health-bent.com/soups/paleo-mediterranean-beef-stew'); \ No newline at end of file diff --git a/server/testoutput.html b/server/testoutput.html index d3eb489..766dc95 100644 --- a/server/testoutput.html +++ b/server/testoutput.html @@ -1,113 +1,65 @@ - -
- - Beef Soups - -

Mediterranean Beef Stew with Green Olive Pesto

- - - - - -
- - - - -
- - -
Print Friendly


-Beef stew, also known as beef bourguignon, is good, but boring–and we personally think it tastes like straight up sour wine and that is not very tasty, especially by the spoonful. So we’ve added a bit of balsamic vinegar and raisins to counter the sour with a bit of sweet. We’re also swirling in a nice, briny, herbal pesto to brighten up the braise. Another change, we’re not using a crock pot! The dutch oven allows liquid to evaporate from the pot, thus creating a thicker, more intense flavored stew. And heck, I would rather eat in 2 hours than in 6 hours, agreed?

-

Ingredients

+
+
+
+ 1 Sep
+
+
+

+ Shakshuka (Eggs Poached in Spicy Tomato Sauce)

+

Whether you’re looking for a new breakfast idea or are fond of serving breakfast for dinner, shakshuka fits the bill. Instead of calling the dish shakshuka you can also just call it “Eggs Poached in Spicy Tomato Sauce” because that’s exactly what this straightforward but surprisingly delicious meal is.

+

Especially popular in Israel, shakshuka is loved around the world for its comforting flavor and simple preparation. Although the sauce is often sopped up with pita bread, it’s thick enough that you can skip the bread and eat it with a spoon (or spread extra sauce over a hunk of grilled meat for a really fantastic meal.)

+

+

Most recipes for shakshuka call for canned (or boxed) tomatoes, but you shouldn’t hesitate to use plump, super-ripe fresh tomatoes if you can find them. Tomatoes are the main ingredient in shakshuka and some say that little else, besides eggs and garlic, should be added. However, this version leans in the direction of spicing things up with more flavor and variety. Onion, bell pepper, jalapeno, cumin and paprika make the meal more than just a pot of simmered tomatoes.

+

The eggs are added at the end and then cooked until just set. The contrasting flavors and textures in your bowl – creamy, soft eggs swimming in thick, spicy sauce – is what shakshuka is all about.

+

Servings: 4

+

Ingredients:

+
    -
  • 2 T fat of your choice
  • -
  • 2 lb. chuck shoulder, cubed
  • -
  • 1 yellow onion, chopped
  • -
  • 3 cloves garlic, finely chopped
  • -
  • 1 carrot, finely chopped
  • -
  • 3/4 c raisins
  • -
  • (1) 28 oz. can fire roasted crushed tomatoes
  • -
  • 1 c red wine
  • -
  • 1/4 c balsamic vinegar
  • -
  • 1 lemon, sliced and seeds removed
  • -
  • S&P
  • +
  • 1/4 cup olive oil
  • +
  • 1 to 3 jalapeno peppers, (depending on how spicy you like it) seeded and finely chopped
  • +
  • 1 green bell pepper, cut into thin strips
  • +
  • 1 white or yellow onion, finely chopped
  • +
  • 4 cloves of garlic, finely chopped
  • +
  • 1/2 teaspoon ground cumin
  • +
  • 2 teaspoons paprika
  • +
  • 28-ounces whole peeled tomatoes in their juice or 2 pounds fresh tomatoes, chopped
  • +
  • 4 to 6 eggs
  • +
  • 1/4 cup roughly chopped parsley
  • +
  • Optional: crumbled feta cheese
  • +
  • Salt to taste
-

For the Pesto

-
    -
  • 1 handful of basil leaves
  • -
  • 1/2 handful of mint leaves
  • -
  • 1/2 c green olives (about 20)
  • -
  • 3 T extra virgin olive oil
  • -
-

Method

-

Preheat the oven to 350ºF.

-

In a dutch oven melt your fat. Salt and pepper the cubed chuck pieces, add them to the pot and let them brown on each side. Don’t fidget with them or remove them until you see a visible brown crust on the meat. Remove and reserve on a plate.  To the pot, add the onion, garlic and carrot. Let them sweat and saute until soft, about 10 minutes. Add the meat back to the pot, along with the tomatoes, raisins, red wine and balsamic vinegar. Stir to combine. Top with sliced lemons.

-

-

Lay a piece of parchment paper of the the top of the pot and press it down into the pot. Place in the oven and braise for 2 hours. Taste the meat, it should be super tender, if it’s not give it another half hour or so.

-

Once you’re about 10 minutes from the stew finishing; combine all the ingredients for the pesto in a mini food processor. Pulse until everything has come together.

-

When the stew is out of the oven, take the lemon rinds out, but leave in the flesh…it’ll separate very easily. Swirl in the pesto and serve.

-
- - - - -
- +

Instructions:

+

Preheat the oven to 400 degrees Fahrenheit.

+

Heat olive oil over medium-high heat in a deep skillet. Add peppers and onion and sauté until onion is lightly browned, about five minutes.

+ +

Add garlic, cumin and paprika and sauté one minute more.

+ +

Add tomatoes. Break them apart with a large spoon or spatula as they cook. Reduce heat slightly and simmer 15-20 minutes (longer if tomatoes are fresh), stirring occasionally, until sauce has thickened and most of the liquid is gone. Add salt to taste.

+ +

Crack the eggs evenly around the skillet. Place the skillet in the oven and cook until the egg whites are set, 6-8 minutes.

+ +

Garnish with parsley (and feta). Serve warm.

+


+ +

-
- - - - - - - -
- - -

You Might Also Like

- - - -
- \ No newline at end of file + +

+ +
+ +
+ +
+
+