public void Can_parse_template_with_only_variable()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("{{ filter }}");

            Assert.That(fragments.Count, Is.EqualTo(1));
            Assert.That(((PageVariableFragment)fragments[0]).Binding, Is.EqualTo("filter"));
        }
        public void Can_parse_template_with_multiple_filters_and_multiple_args()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("<h1>{{ title | filter1 | filter2(1) | filter3(1,2.2,'a',\"b\",true) }}</h1>");

            Assert.That(fragments.Count, Is.EqualTo(3));

            var strFragment1 = fragments[0] as PageStringFragment;
            var varFragment2 = fragments[1] as PageVariableFragment;
            var strFragment3 = fragments[2] as PageStringFragment;

            Assert.That(strFragment1.Value.ToString(), Is.EqualTo("<h1>"));
            Assert.That(varFragment2.OriginalText.ToString(), Is.EqualTo("{{ title | filter1 | filter2(1) | filter3(1,2.2,'a',\"b\",true) }}"));
            Assert.That(varFragment2.Binding, Is.EqualTo("title"));
            Assert.That(varFragment2.FilterExpressions.Length, Is.EqualTo(3));

            Assert.That(varFragment2.FilterExpressions[0].Name, Is.EqualTo("filter1"));
            Assert.That(varFragment2.FilterExpressions[0].Arguments.Length, Is.EqualTo(0));

            Assert.That(varFragment2.FilterExpressions[1].Name, Is.EqualTo("filter2"));
            Assert.That(varFragment2.FilterExpressions[1].Arguments.Length, Is.EqualTo(1));
            Assert.That(varFragment2.FilterExpressions[1].Arguments[0], Is.EqualTo(new JsLiteral(1)));

            Assert.That(varFragment2.FilterExpressions[2].Name, Is.EqualTo("filter3"));
            Assert.That(varFragment2.FilterExpressions[2].Arguments.Length, Is.EqualTo(5));
            Assert.That(varFragment2.FilterExpressions[2].Arguments[0], Is.EqualTo(new JsLiteral(1)));
            Assert.That(varFragment2.FilterExpressions[2].Arguments[1], Is.EqualTo(new JsLiteral(2.2)));
            Assert.That(varFragment2.FilterExpressions[2].Arguments[2], Is.EqualTo(new JsLiteral("a")));
            Assert.That(varFragment2.FilterExpressions[2].Arguments[3], Is.EqualTo(new JsLiteral("b")));
            Assert.That(varFragment2.FilterExpressions[2].Arguments[4], Is.EqualTo(JsLiteral.True));

            Assert.That(strFragment3.Value.ToString(), Is.EqualTo("</h1>"));
        }
        public void Can_parse_template_with_multiple_variables_and_filters()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("<h1>{{ title | filter1 }}</h1>\n<p>{{ content | filter2(a) }}</p>");

            Assert.That(fragments.Count, Is.EqualTo(5));

            var strFragment1 = fragments[0] as PageStringFragment;
            var varFragment2 = fragments[1] as PageVariableFragment;
            var strFragment3 = fragments[2] as PageStringFragment;
            var varFragment4 = fragments[3] as PageVariableFragment;
            var strFragment5 = fragments[4] as PageStringFragment;

            Assert.That(strFragment1.Value.ToString(), Is.EqualTo("<h1>"));

            Assert.That(varFragment2.OriginalText.ToString(), Is.EqualTo("{{ title | filter1 }}"));
            Assert.That(varFragment2.Binding, Is.EqualTo("title"));
            Assert.That(varFragment2.FilterExpressions.Length, Is.EqualTo(1));
            Assert.That(varFragment2.FilterExpressions[0].Name, Is.EqualTo("filter1"));
            Assert.That(varFragment2.FilterExpressions[0].Arguments.Length, Is.EqualTo(0));

            Assert.That(strFragment3.Value.ToString(), Is.EqualTo("</h1>\n<p>"));

            Assert.That(varFragment4.OriginalText.ToString(), Is.EqualTo("{{ content | filter2(a) }}"));
            Assert.That(varFragment4.Binding, Is.EqualTo("content"));
            Assert.That(varFragment4.FilterExpressions.Length, Is.EqualTo(1));
            Assert.That(varFragment4.FilterExpressions[0].Name, Is.EqualTo("filter2"));
            Assert.That(varFragment4.FilterExpressions[0].Arguments.Length, Is.EqualTo(1));
            Assert.That(varFragment4.FilterExpressions[0].Arguments[0], Is.EqualTo(new JsIdentifier("a")));

            Assert.That(strFragment5.Value.ToString(), Is.EqualTo("</p>"));
        }
        public void Can_parse_template_with_filter_without_whitespace()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("<h1>{{title}}</h1>");

            Assert.That(fragments.Count, Is.EqualTo(3));

            var strFragment1 = fragments[0] as PageStringFragment;
            var varFragment2 = fragments[1] as PageVariableFragment;
            var strFragment3 = fragments[2] as PageStringFragment;

            Assert.That(strFragment1.Value.ToString(), Is.EqualTo("<h1>"));
            Assert.That(varFragment2.Binding, Is.EqualTo("title"));
            Assert.That(varFragment2.FilterExpressions.Length, Is.EqualTo(0));

            fragments = SharpPageUtils.ParseTemplatePage("<h1>{{title|filter}}</h1>");
            Assert.That(fragments.Count, Is.EqualTo(3));

            strFragment1 = fragments[0] as PageStringFragment;
            varFragment2 = fragments[1] as PageVariableFragment;
            strFragment3 = fragments[2] as PageStringFragment;

            Assert.That(strFragment1.Value.ToString(), Is.EqualTo("<h1>"));
            Assert.That(varFragment2.OriginalText.ToString(), Is.EqualTo("{{title|filter}}"));
            Assert.That(varFragment2.Binding, Is.EqualTo("title"));
            Assert.That(varFragment2.FilterExpressions.Length, Is.EqualTo(1));
            Assert.That(varFragment2.FilterExpressions[0].Name, Is.EqualTo("filter"));
            Assert.That(varFragment2.FilterExpressions[0].Arguments.Length, Is.EqualTo(0));
            Assert.That(strFragment3.Value.ToString(), Is.EqualTo("</h1>"));
        }
        public void Can_parse_filter_with_different_arg_types()
        {
            var fragments   = SharpPageUtils.ParseTemplatePage("{{ array(['a',1,'c']) }}");
            var varFragment = (PageVariableFragment)fragments[0];

            Assert.That(varFragment.OriginalText.ToString(), Is.EqualTo("{{ array(['a',1,'c']) }}"));
            Assert.That(varFragment.InitialExpression.Name, Is.EqualTo("array"));
            Assert.That(varFragment.InitialExpression.Arguments.Length, Is.EqualTo(1));
        }
        public void Can_parse_templates_within_literals()
        {
            JsToken token;

            "'<li>{{it}}</li>'".ParseJsExpression(out token);
            Assert.That(token, Is.EqualTo(new JsLiteral("<li>{{it}}</li>")));

            var fragments = SharpPageUtils.ParseTemplatePage("<ul>{{ '<li>{{it}}</li>' }}</ul>");

            Assert.That(fragments.Count, Is.EqualTo(3));
        }
        public void Can_parse_template_with_no_vars()
        {
            Assert.That(SharpPageUtils.ParseTemplatePage("").Count, Is.EqualTo(0));
            var fragments = SharpPageUtils.ParseTemplatePage("<h1>title</h1>");

            Assert.That(fragments.Count, Is.EqualTo(1));

            var strFragment = fragments[0] as PageStringFragment;

            Assert.That(strFragment.Value.ToString(), Is.EqualTo("<h1>title</h1>"));
        }
        public void Can_parse_template_with_arg_and_multiple_filters()
        {
            var fragments   = SharpPageUtils.ParseTemplatePage("{{ ' - {{it}}' | forEach(items) | markdown }}");
            var varFragment = fragments[0] as PageVariableFragment;

            Assert.That(varFragment.OriginalText.ToString(), Is.EqualTo("{{ ' - {{it}}' | forEach(items) | markdown }}"));
            Assert.That(varFragment.FilterExpressions.Length, Is.EqualTo(2));
            Assert.That(varFragment.FilterExpressions[0].Name, Is.EqualTo("forEach"));
            Assert.That(varFragment.FilterExpressions[0].Arguments.Length, Is.EqualTo(1));
            Assert.That(varFragment.FilterExpressions[0].Arguments[0], Is.EqualTo(new JsIdentifier("items")));
            Assert.That(varFragment.FilterExpressions[1].Name, Is.EqualTo("markdown"));
        }
        public void Can_use_cleaner_whitespace_sensitive_syntax_for_string_arguments()
        {
            var fragments1 = SharpPageUtils.ParseTemplatePage(
                @"{{ 
products 
  | where: it.UnitsInStock = 0 
  | select: { it.productName | raw } is sold out!\n 
}}");

            var fragments2 = SharpPageUtils.ParseTemplatePage(
                @"{{ products 
                 | where: it.UnitsInStock = 0 
                 | select: { it.productName | raw } is sold out!\n }}");

            // i.e. is rewritten and is equivalent to:
            var fragments3 = SharpPageUtils.ParseTemplatePage(
                @"{{ products | where(′it.UnitsInStock = 0′) | select(′{{ it.productName | raw }} is sold out!\n′)}}");

            Assert.That(fragments3.Count, Is.EqualTo(1));

            Assert.That(fragments1.Count, Is.EqualTo(1));
            var varFragment1 = fragments1[0] as PageVariableFragment;

            Assert.That(varFragment1.FilterExpressions[0].Name, Is.EqualTo("where"));
            Assert.That(varFragment1.FilterExpressions[0].Arguments.Length, Is.EqualTo(1));
            Assert.That(varFragment1.FilterExpressions[0].Arguments[0], Is.EqualTo(
                            new JsLiteral("it.UnitsInStock = 0")
                            ));
            Assert.That(varFragment1.FilterExpressions[1].Name, Is.EqualTo("select"));
            Assert.That(varFragment1.FilterExpressions[1].Arguments.Length, Is.EqualTo(1));
            Assert.That(varFragment1.FilterExpressions[1].Arguments[0], Is.EqualTo(
                            new JsLiteral("{{ it.productName | raw }} is sold out!\\n")
                            ));

            foreach (var fragments in new[] { fragments2, fragments3 })
            {
                var varFragment = fragments[0] as PageVariableFragment;
                Assert.That(varFragment.FilterExpressions[0].Name, Is.EqualTo(varFragment1.FilterExpressions[0].Name));
                Assert.That(varFragment.FilterExpressions[0].Arguments.Length, Is.EqualTo(varFragment1.FilterExpressions[0].Arguments.Length));
                Assert.That(varFragment.FilterExpressions[0].Arguments[0], Is.EqualTo(varFragment1.FilterExpressions[0].Arguments[0]));
                Assert.That(varFragment.FilterExpressions[1].Name, Is.EqualTo(varFragment1.FilterExpressions[1].Name));
                Assert.That(varFragment.FilterExpressions[1].Arguments.Length, Is.EqualTo(varFragment1.FilterExpressions[1].Arguments.Length));
                Assert.That(varFragment.FilterExpressions[1].Arguments[0], Is.EqualTo(varFragment1.FilterExpressions[1].Arguments[0]));
            }
        }
Exemple #10
0
        public void Does_parse_Raw_block_body_as_string()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("BEFORE {{#raw}} Hi, {{ {{ name }} }} {{/raw}} AFTER");

            Assert.That(fragments.Count, Is.EqualTo(3));
            Assert.That(((PageStringFragment)fragments[0]).Value.ToString(), Is.EqualTo("BEFORE "));

            var statement = fragments[1] as PageBlockFragment;

            Assert.That(statement, Is.Not.Null);
            Assert.That(statement.Name, Is.EqualTo("raw"));
            Assert.That(statement.Argument.ToString(), Is.EqualTo(""));
            Assert.That(statement.Body.Length, Is.EqualTo(1));

            Assert.That(((PageStringFragment)statement.Body[0]).Value.ToString(), Is.EqualTo(" Hi, {{ {{ name }} }} "));

            Assert.That(((PageStringFragment)fragments[2]).Value.ToString(), Is.EqualTo(" AFTER"));
        }
        public void Can_parse_pages_starting_with_values()
        {
            var fragments = SharpPageUtils.ParseTemplatePage(
                @"{{ [c.CustomerId, o.OrderId, o.OrderDate] | jsv }}\n");

            var varFragment = (PageVariableFragment)fragments[0];

            Assert.That(varFragment.Expression, Is.EqualTo(new JsArrayExpression(
                                                               new JsMemberExpression(new JsIdentifier("c"), new JsIdentifier("CustomerId")),
                                                               new JsMemberExpression(new JsIdentifier("o"), new JsIdentifier("OrderId")),
                                                               new JsMemberExpression(new JsIdentifier("o"), new JsIdentifier("OrderDate"))
                                                               )));

            Assert.That(varFragment.OriginalText.ToString(), Is.EqualTo("{{ [c.CustomerId, o.OrderId, o.OrderDate] | jsv }}"));

            var newLine = (PageStringFragment)fragments[1];

            Assert.That(newLine.Value.ToString(), Is.EqualTo("\\n"));
        }
Exemple #12
0
        public void Does_parse_template_with_if_else_statement()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("BEFORE {{#if a < b}}YES{{else}}NO{{/if}} AFTER");

            Assert.That(fragments.Count, Is.EqualTo(3));
            Assert.That(((PageStringFragment)fragments[0]).Value.ToString(), Is.EqualTo("BEFORE "));

            var statement = fragments[1] as PageBlockFragment;

            Assert.That(statement, Is.Not.Null);
            Assert.That(statement.Name, Is.EqualTo("if"));
            Assert.That(statement.Argument.ToString(), Is.EqualTo("a < b"));
            Assert.That(((PageStringFragment)statement.Body[0]).Value.ToString(), Is.EqualTo("YES"));

            Assert.That(statement.ElseBlocks[0].Argument.ToString(), Is.EqualTo(""));
            Assert.That(((PageStringFragment)statement.ElseBlocks[0].Body[0]).Value.ToString(), Is.EqualTo("NO"));

            Assert.That(((PageStringFragment)fragments[2]).Value.ToString(), Is.EqualTo(" AFTER"));
        }
Exemple #13
0
        public void Does_parse_template_with_Block_Statement()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("BEFORE {{#bold}} Hi, {{name}}! {{/bold}} AFTER");

            Assert.That(fragments.Count, Is.EqualTo(3));
            Assert.That(((PageStringFragment)fragments[0]).Value.ToString(), Is.EqualTo("BEFORE "));

            var statement = fragments[1] as PageBlockFragment;

            Assert.That(statement, Is.Not.Null);
            Assert.That(statement.Name, Is.EqualTo("bold"));
            Assert.That(statement.Argument.ToString(), Is.EqualTo(""));

            Assert.That(((PageStringFragment)statement.Body[0]).Value.ToString(), Is.EqualTo(" Hi, "));
            Assert.That(((PageVariableFragment)statement.Body[1]).Binding, Is.EqualTo("name"));
            Assert.That(((PageStringFragment)statement.Body[2]).Value.ToString(), Is.EqualTo("! "));

            Assert.That(((PageStringFragment)fragments[2]).Value.ToString(), Is.EqualTo(" AFTER"));
        }
        public void Can_detect_invalid_syntax()
        {
            try
            {
                var fragments = SharpPageUtils.ParseTemplatePage("{{ arg | filter(' 1) }}");
                Assert.Fail("should throw");
            }
            catch (ArgumentException e)
            {
                e.Message.Print();
            }

            try
            {
                var fragments = SharpPageUtils.ParseTemplatePage("square = {{ 'square-partial | partial({ ten }) }}");
                Assert.Fail("should throw");
            }
            catch (ArgumentException e)
            {
                e.Message.Print();
            }

            try
            {
                var fragments = SharpPageUtils.ParseTemplatePage("{{ arg | filter({ unterminated:1) }}");
                Assert.Fail("should throw");
            }
            catch (ArgumentException e)
            {
                e.Message.Print();
            }

            try
            {
                var fragments = SharpPageUtils.ParseTemplatePage("{{ arg | filter([ 1) }}");
                Assert.Fail("should throw");
            }
            catch (ArgumentException e)
            {
                e.Message.Print();
            }
        }
        public void Does_remove_new_line_between_var_literals()
        {
            var fragments = SharpPageUtils.ParseTemplatePage("{{ 'foo' | assignTo: bar }}\n{{ bar }}");

            Assert.That(fragments.Count, Is.EqualTo(2));
            fragments = SharpPageUtils.ParseTemplatePage("{{ 'foo' | assignTo: bar }}\r\n{{ bar }}");
            Assert.That(fragments.Count, Is.EqualTo(2));

            fragments = SharpPageUtils.ParseTemplatePage("{{ ['foo'] | do: assign('bar', it) }}\n{{ bar }}");
            Assert.That(fragments.Count, Is.EqualTo(2));
            fragments = SharpPageUtils.ParseTemplatePage("{{ do: assign('bar', 'foo') }}\n{{ bar }}");
            Assert.That(fragments.Count, Is.EqualTo(2));
            fragments = SharpPageUtils.ParseTemplatePage("{{ 10 | times | do: assign('bar', 'foo') }}\n{{ bar }}");
            Assert.That(fragments.Count, Is.EqualTo(2));
            fragments = SharpPageUtils.ParseTemplatePage("{{ 10 | times | do: assign('bar', 'foo') }}\nbar");
            Assert.That(fragments.Count, Is.EqualTo(2));
            var stringFragment = (PageStringFragment)fragments[1];

            Assert.That(stringFragment.Value.ToString(), Is.EqualTo("bar"));
        }
        public Action <ScriptScopeContext, object, object> GetAssignExpression(Type targetType, ReadOnlyMemory <char> expression)
        {
            if (targetType == null)
            {
                throw new ArgumentNullException(nameof(targetType));
            }
            if (expression.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var key = targetType.FullName + ':' + expression;

            if (AssignExpressionCache.TryGetValue(key, out var fn))
            {
                return(fn);
            }

            AssignExpressionCache[key] = fn = SharpPageUtils.CompileAssign(targetType, expression);

            return(fn);
        }
Exemple #17
0
        public async Task <SharpPage> Load()
        {
            string contents;

            using (var stream = File.OpenRead())
            {
                contents = await stream.ReadToEndAsync();
            }

            foreach (var preprocessor in Context.Preprocessors)
            {
                contents = preprocessor(contents);
            }

            var lastModified = File.LastModified;
            var fileContents = contents.AsMemory();
            var pageVars     = new Dictionary <string, object>();

            var pos          = 0;
            var bodyContents = fileContents;

            fileContents.AdvancePastWhitespace().TryReadLine(out ReadOnlyMemory <char> line, ref pos);
            if (line.StartsWith(Format.ArgsPrefix))
            {
                while (fileContents.TryReadLine(out line, ref pos))
                {
                    if (line.Trim().Length == 0)
                    {
                        continue;
                    }


                    if (line.StartsWith(Format.ArgsSuffix))
                    {
                        break;
                    }

                    var colonPos = line.IndexOf(':');
                    var spacePos = line.IndexOf(' ');
                    var bracePos = line.IndexOf('{');
                    var sep      = colonPos >= 0 ? ':' : ' ';

                    if (bracePos > 0 && spacePos > 0 && colonPos > spacePos)
                    {
                        sep = ' ';
                    }

                    line.SplitOnFirst(sep, out var first, out var last);

                    pageVars[first.Trim().ToString()] = !last.IsEmpty ? last.Trim().ToString() : "";
                }

                //When page has variables body starts from first non whitespace after variables end
                var argsSuffixPos = line.LastIndexOf(Format.ArgsSuffix);
                if (argsSuffixPos >= 0)
                {
                    //Start back from the end of the ArgsSuffix
                    pos -= line.Length - argsSuffixPos - Format.ArgsSuffix.Length;
                }
                bodyContents = fileContents.SafeSlice(pos).AdvancePastWhitespace();
            }

            var pageFragments = pageVars.TryGetValue("ignore", out object ignore) &&
                                ("page".Equals(ignore.ToString()) || "template".Equals(ignore.ToString()))
                ? new List <PageFragment> {
                new PageStringFragment(bodyContents)
            }
                : SharpPageUtils.ParseTemplatePage(bodyContents);

            foreach (var fragment in pageFragments)
            {
                if (fragment is PageVariableFragment var && var.Binding == ScriptConstants.Page)
                {
                    IsLayout = true;
                    break;
                }
            }

            lock (semaphore)
            {
                LastModified      = lastModified;
                LastModifiedCheck = DateTime.UtcNow;
                FileContents      = fileContents;
                Args          = pageVars;
                BodyContents  = bodyContents;
                PageFragments = pageFragments;

                HasInit    = true;
                LayoutPage = Format.ResolveLayout(this);
            }

            if (LayoutPage != null)
            {
                if (!LayoutPage.HasInit)
                {
                    await LayoutPage.Load();
                }
                else
                {
                    if (Context.DebugMode || Context.CheckForModifiedPagesAfter != null &&
                        DateTime.UtcNow - LayoutPage.LastModifiedCheck >= Context.CheckForModifiedPagesAfter.Value)
                    {
                        LayoutPage.File.Refresh();
                        LayoutPage.LastModifiedCheck = DateTime.UtcNow;
                        if (LayoutPage.File.LastModified != LayoutPage.LastModified)
                        {
                            await LayoutPage.Load();
                        }
                    }
                }
            }

            return(this);
        }