("context", requestContext)
+ }
+ );
+ templateDocument.RenderTemplate(renderContext);
+ return true;
+ }
+
+ public void Dispose()
+ {
+ _parentRouter?.UnMap(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ln.http.templates/ln.http.templates.csproj b/ln.http.templates/ln.http.templates.csproj
new file mode 100644
index 0000000..6bd7ddd
--- /dev/null
+++ b/ln.http.templates/ln.http.templates.csproj
@@ -0,0 +1,17 @@
+
+
+
+ enable
+ enable
+ 0.9.2
+ true
+ net5.0;net6.0
+ default
+
+
+
+
+
+
+
+
diff --git a/ln.templates.sln b/ln.templates.sln
index bef4b5c..82acb01 100644
--- a/ln.templates.sln
+++ b/ln.templates.sln
@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.templates", "ln.template
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.templates.test", "ln.templates.test\ln.templates.test.csproj", "{36593773-B517-4B62-BAD2-8AA632AA159E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.templates", "ln.http.templates\ln.http.templates.csproj", "{011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -44,5 +46,17 @@ Global
{36593773-B517-4B62-BAD2-8AA632AA159E}.Release|x64.Build.0 = Release|Any CPU
{36593773-B517-4B62-BAD2-8AA632AA159E}.Release|x86.ActiveCfg = Release|Any CPU
{36593773-B517-4B62-BAD2-8AA632AA159E}.Release|x86.Build.0 = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|x64.Build.0 = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Debug|x86.Build.0 = Debug|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|Any CPU.Build.0 = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|x64.ActiveCfg = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|x64.Build.0 = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|x86.ActiveCfg = Release|Any CPU
+ {011E8B81-DF87-4AFB-BEA8-ADA6FD3F3665}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/ln.templates.test/HtmlTests.cs b/ln.templates.test/HtmlTests.cs
index a2fb594..920e463 100644
--- a/ln.templates.test/HtmlTests.cs
+++ b/ln.templates.test/HtmlTests.cs
@@ -17,56 +17,35 @@ namespace ln.templates.test
[TestFixture()]
public class HtmlTests
{
- [Test()]
- public void TestCase()
+
+ [TestCase()]
+ public void Test_Base()
{
- html.TemplateReader templateReader = new html.TemplateReader();
- templateReader.Read("\n\n\n Hello\n\n\n Welcome to this example.
\n {{ 'Ich bin ein ScriptText!' }}
\n DateTime: {{ Date }}
\n Ein bisschen JavaScript: {{ 5 + ' mal ' + 5 + ' = ' + (5*5) }}
\n\n");
+ Template template = new Template("tests/test_base.html", null);
+ Console.WriteLine("Template Source:\n{0}", template.Document.ToString());
- Console.WriteLine("Source rendered:\n{0}", templateReader.Document.ToString());
-
- StringWriter stringWriter = new StringWriter();
- RenderContext renderContext = new RenderContext(stringWriter);
-
- renderContext.SetScriptObject("Date", DateTime.Now);
-
- templateReader.TemplateDocument.RenderTemplate(renderContext);
-
- Console.WriteLine("Template rendered:\n{0}", stringWriter.ToString());
+ StringWriter targetWriter = new StringWriter();
+ template.Render(targetWriter);
+
+ Console.WriteLine("Rendered Document:\n{0}", targetWriter.ToString());
}
- [Test()]
- public void TestFileSystemTemplateSource()
+ [TestCase()]
+ public void Test_Slots()
{
- if (File.Exists("templates.tst/frame.html"))
- File.Delete("templates.tst/frame.html");
- if (File.Exists("templates.tst/head.html"))
- File.Delete("templates.tst/head.html");
+ FileSystemTemplateSource templateSource = new FileSystemTemplateSource("tests");
+ Template template = templateSource.GetTemplateByPath("test_slots.html");
+
+ Console.WriteLine("Template Source:\n{0}", template.Document.ToString());
- Directory.CreateDirectory("templates.tst");
- using (FileStream fs = new FileStream("templates.tst/frame.html", FileMode.CreateNew))
- using (TextWriter tw = new StreamWriter(fs))
- {
- tw.Write("");
- tw.Flush();
- }
-
- using (FileStream fs = new FileStream("templates.tst/head.html", FileMode.CreateNew))
- using (TextWriter tw = new StreamWriter(fs))
- {
- tw.Write("{{ title }}");
- tw.Flush();
- }
-
- FileSystemTemplateSource fileSystemTemplateSource = new FileSystemTemplateSource("templates.tst");
- TemplateDocument templateDocument = fileSystemTemplateSource.GetTemplateByPath("frame.html");
-
- StringWriter stringWriter = new StringWriter();
- RenderContext renderContext = new RenderContext(stringWriter,fileSystemTemplateSource);
-
- templateDocument.RenderTemplate(renderContext);
-
- Console.WriteLine("Document rendered to: {0}", stringWriter.ToString());
+ StringWriter targetWriter = new StringWriter();
+ template.Render(targetWriter);
+
+ using (StreamWriter sw = new StreamWriter("test.out.slots.html"))
+ sw.Write(targetWriter.ToString());
+
+ Console.WriteLine("Rendered Document:\n{0}", targetWriter.ToString());
}
+
}
}
diff --git a/ln.templates.test/ln.templates.test.csproj b/ln.templates.test/ln.templates.test.csproj
index bcd3b74..4c3df6f 100644
--- a/ln.templates.test/ln.templates.test.csproj
+++ b/ln.templates.test/ln.templates.test.csproj
@@ -1,9 +1,12 @@
- netcoreapp3.1
false
+
+ net5.0;net6.0
+
+ default
@@ -16,4 +19,16 @@
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
diff --git a/ln.templates.test/tests/test_base.html b/ln.templates.test/tests/test_base.html
new file mode 100644
index 0000000..f128b70
--- /dev/null
+++ b/ln.templates.test/tests/test_base.html
@@ -0,0 +1,10 @@
+
+
+
+ Basic Test Template
+
+
+ Let's check for iterations...
+ This is paragraph #{{i}}
+
+
\ No newline at end of file
diff --git a/ln.templates.test/tests/test_slot_a.html b/ln.templates.test/tests/test_slot_a.html
new file mode 100644
index 0000000..e16b6f2
--- /dev/null
+++ b/ln.templates.test/tests/test_slot_a.html
@@ -0,0 +1,3 @@
+
+ Default Title
+
\ No newline at end of file
diff --git a/ln.templates.test/tests/test_slots.html b/ln.templates.test/tests/test_slots.html
new file mode 100644
index 0000000..90d57c4
--- /dev/null
+++ b/ln.templates.test/tests/test_slots.html
@@ -0,0 +1,16 @@
+
+
+
+ Slot Test
+
+
+
+
+ Title A1
+
+
+ Title A2
+
+
+
+
\ No newline at end of file
diff --git a/ln.templates/Context.cs b/ln.templates/Context.cs
new file mode 100644
index 0000000..407988c
--- /dev/null
+++ b/ln.templates/Context.cs
@@ -0,0 +1,53 @@
+using System.Collections.Generic;
+using System.IO;
+using Jint;
+using ln.templates.html;
+
+namespace ln.templates;
+
+
+public class Context
+{
+ public Context(ITemplateResolver resolver, IEnumerable> scriptObjects, TextWriter targetWriter)
+ {
+ Resolver = resolver;
+ Engine = new Engine();
+ foreach (KeyValuePair pair in scriptObjects)
+ Engine.SetValue(pair.Key, pair.Value);
+ TargetWriter = targetWriter;
+ }
+ public Context(ITemplateResolver resolver, Engine engine, TextWriter targetWriter)
+ {
+ Resolver = resolver;
+ Engine = engine;
+ TargetWriter = targetWriter;
+ }
+ public Context(Context source)
+ {
+ Resolver = source.Resolver;
+ Engine = source.Engine;
+ TargetWriter = source.TargetWriter;
+ }
+
+ public Engine Engine { get; private set; }
+ public ITemplateResolver Resolver { get; }
+
+ public TextWriter TargetWriter { get; }
+
+ /**
+ * Slots to be used for v-include and v-frame
+ */
+ private Dictionary _slots = new Dictionary();
+ public bool TryGetSlot(string slotName, out Element slot) => _slots.TryGetValue(slotName, out slot);
+ public void SetSlot(string slotName, Element slot) => _slots[slotName] = slot;
+ public void ClearSlot(string slotName) => _slots.Remove(slotName);
+ public void ClearSlots() => _slots.Clear();
+
+ public void SetSlots(IEnumerable> slots)
+ {
+ _slots.Clear();
+ foreach (var pair in slots)
+ _slots.Add(pair.Key, pair.Value);
+ }
+}
+
diff --git a/ln.templates/Expression.cs b/ln.templates/Expression.cs
deleted file mode 100644
index 4ad83b9..0000000
--- a/ln.templates/Expression.cs
+++ /dev/null
@@ -1,559 +0,0 @@
-using System;
-using System.Reflection;
-using System.IO;
-using System.Text;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Linq;
-namespace ln.templates
-{
- delegate bool ConditionDelegate(char ch);
-
- public class Expression
- {
- public String Source { get; }
- private Eval TopEval { get; set; }
-
- public Expression(String expr)
- {
- Source = expr;
-
- Compile();
- }
-
- public object Evaluate(object o)
- {
- Context context = new Context(o, null);
- return TopEval.Evaluate(context);
- }
- public object Evaluate(Context context)
- {
- return TopEval.Evaluate(context);
- }
-
- public bool IsTrue(Context context)
- {
- try
- {
- object v = Evaluate(context);
- if ((v is bool) && ((bool)v))
- return true;
- if ((v is string) && (!String.Empty.Equals(v)))
- return true;
- if ((v is int) && ((int)v != 0))
- return true;
- return false;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
-
- private void Compile()
- {
- try
- {
- StringReader reader = new StringReader(Source);
- List tokens = new List();
- while (reader.Peek() != -1)
- ReadToken(reader, tokens);
-
- Queue qtokens = new Queue(tokens);
-
- TopEval = BuildExpression(qtokens);
- } catch (Exception e)
- {
- throw new Exception(String.Format("Failed to compile expression: {0}", Source), e);
- }
- }
-
-
- private Eval BuildName(Token nameToken,Eval parent,Queue tokens)
- {
- if ((tokens.Count > 0) && (tokens.Peek().TokenType == TokenType.OPENLIST))
- {
- tokens.Dequeue();
-
- List pl = new List();
- while (tokens.Peek().TokenType != TokenType.ENDLIST)
- {
- pl.Add(BuildExpression(tokens));
-
- if (tokens.Peek().TokenType == TokenType.ENDLIST)
- break;
-
- if (tokens.Peek().TokenType != TokenType.COMMA)
- throw new FormatException("Expected ',' between parameters to call statement");
-
- tokens.Dequeue();
- }
-
- tokens.Dequeue();
-
- return new MethodCall(parent, nameToken.Value, pl.ToArray());
- }
- else
- {
- return new Name(parent, nameToken.Value);
- }
- }
-
- private Eval BuildPath(Queue tokens)
- {
- Eval currentEval = BuildName(tokens.Dequeue(), null, tokens);
-
- while (tokens.Count > 0)
- {
- Token token = tokens.Peek();
- switch (token.TokenType)
- {
- case TokenType.DOT:
- tokens.Dequeue();
- currentEval = BuildName(tokens.Dequeue(), currentEval, tokens);
- break;
- case TokenType.OPENINDEXER:
- tokens.Dequeue();
- Eval index = BuildExpression(tokens);
- token = tokens.Dequeue();
- if (token.TokenType != TokenType.ENDINDEXER)
- throw new FormatException("Expected ']'");
- currentEval = new Indexer(currentEval, index);
- break;
- default:
- return currentEval;
- }
- }
- return currentEval;
- }
-
-
- private Eval BuildExpression(Queue tokens)
- {
- Token next = tokens.Peek();
-
- switch (next.TokenType)
- {
- case TokenType.NAME:
- return BuildPath(tokens);
- case TokenType.NUMBER:
- return new Number(tokens.Dequeue().Value);
- case TokenType.STRING:
- return new CString(tokens.Dequeue().Value);
- }
-
- throw new FormatException(String.Format("unexpected Token: {0}", next.Value));
- }
-
- private void ReadToken(TextReader reader, List tokens)
- {
- if (reader.Peek() == -1)
- return;
- char ch = (char)reader.Peek();
- if (char.IsWhiteSpace(ch))
- {
- reader.Read();
- }
- else if (char.IsLetter(ch) || (ch == '_'))
- {
- ReadName(reader, tokens);
- }
- else if (char.IsDigit(ch))
- {
- ReadNumber(reader, tokens);
- }
- else if (ch == '"')
- {
- ReadString(reader, tokens);
- }
- else if (ch == '.')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.DOT, "."));
- }
- else if (ch == '[')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.OPENINDEXER, new string(new char[] { ch })));
- }
- else if (ch == ']')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.ENDINDEXER, new string(new char[] { ch })));
- }
- else if (ch == '(')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.OPENLIST, new string(new char[] { ch })));
- }
- else if (ch == ')')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.ENDLIST, new string(new char[] { ch })));
- }
- else if (ch == ',')
- {
- reader.Read();
- tokens.Add(new Token(TokenType.COMMA, new string(new char[] { ch })));
- }
- else
- {
- throw new FormatException(String.Format("Unexpected character: {0}", (char)reader.Peek()));
- }
- }
- private void ReadName(TextReader reader, List tokens)
- {
- StringBuilder sb = new StringBuilder();
- int ch = 0;
- while (char.IsLetterOrDigit((char)(ch = reader.Peek())) || (ch == '_'))
- {
- sb.Append((char)reader.Read());
- }
- tokens.Add(new Token(TokenType.NAME, sb.ToString()));
- }
- private void ReadNumber(TextReader reader, List tokens)
- {
- StringBuilder sb = new StringBuilder();
- int ch = 0;
- while (char.IsDigit((char)(ch = reader.Peek())) | (ch == '.'))
- {
- sb.Append((char)reader.Read());
- }
- tokens.Add(new Token(TokenType.NUMBER, sb.ToString()));
- }
- private void ReadString(TextReader reader, List tokens)
- {
- StringBuilder sb = new StringBuilder();
- int ch = 0;
- reader.Read();
- while ((ch = reader.Peek())!='"')
- {
- if (ch == '\\')
- {
- reader.Read();
- char sch = (char)reader.Read();
- switch (sch)
- {
- case 'n':
- sb.Append('\n');
- break;
- case 'r':
- sb.Append('\r');
- break;
- case 't':
- sb.Append('\t');
- break;
- default:
- sb.Append(sch);
- break;
- }
- }
- else
- {
- sb.Append((char)reader.Read());
- }
- }
- reader.Read();
-
- tokens.Add(new Token(TokenType.STRING, sb.ToString()));
- }
-
-
- enum TokenType { NAME, DOT, NUMBER, STRING, OPENINDEXER, ENDINDEXER, OPENLIST, ENDLIST, COMMA }
- class Token
- {
- public TokenType TokenType;
- public string Value;
-
- public Token(TokenType tokenType,String value)
- {
- this.TokenType = tokenType;
- this.Value = value;
- }
-
- public override string ToString()
- {
- return String.Format("[Token TokenType={0:8} Value={1}]", TokenType, Value);
- }
- }
-
- public class Context
- {
- public object This { get; }
- public Dictionary MappedValues { get; }
-
- public Context(Context source)
- : this(source.This, source.MappedValues)
- {
- }
-
- public Context(object o,IEnumerable> mappedValues)
- {
- this.This = o;
- this.MappedValues = new Dictionary();
-
- if (mappedValues != null)
- foreach (KeyValuePair kvp in mappedValues)
- MappedValues.Add(kvp.Key,kvp.Value);
- }
-
- public void AddMappedValue(string name, object value)
- {
- MappedValues.Add(name, value);
- }
- public void SetMappedValue(string name, object value)
- {
- MappedValues[name] = value;
- }
- public void RemoveMappedValue(string name)
- {
- MappedValues.Remove(name);
- }
-
- public object Evaluate(string name)
- {
- if (MappedValues.ContainsKey(name))
- return MappedValues[name];
-
- if (This != null)
- {
- FieldInfo fieldInfo = This.GetType().GetField(name);
- if (fieldInfo != null)
- {
- return fieldInfo.GetValue(This);
- }
- PropertyInfo propertyInfo = This.GetType().GetProperty(name);
- if (propertyInfo != null)
- {
- return propertyInfo.GetValue(This);
- }
- }
- throw new KeyNotFoundException(name);
- }
-
- }
-
- abstract class Eval
- {
- public Eval Parent { get; }
-
- public Eval(Eval parent)
- {
- this.Parent = parent;
- }
-
- public abstract object Evaluate(Context context);
- }
-
- class Name : Eval
- {
- public string name;
-
- public Name(Eval parent,String name)
- :base(parent)
- {
- this.name = name;
- }
-
- public override object Evaluate(Context context)
- {
- if (Parent == null)
- {
- return context.Evaluate(name);
- }
-
- object p = Parent.Evaluate(context);
- if (p != null)
- {
- FieldInfo fieldInfo = p.GetType().GetField(name);
- if (fieldInfo != null)
- {
- return fieldInfo.GetValue(p);
- }
- PropertyInfo propertyInfo = p.GetType().GetProperty(name);
- if (propertyInfo != null)
- {
- return propertyInfo.GetValue(p);
- }
- throw new KeyNotFoundException(name);
- }
- throw new NullReferenceException();
- }
- }
-
- class Indexer : Eval
- {
- Eval index;
-
- public Indexer(Eval parent,Eval index)
- :base(parent)
- {
- this.index = index;
- }
-
- public override object Evaluate(Context context)
- {
- object i = index.Evaluate(context);
- Type itype = i.GetType();
-
- object p = Parent.Evaluate(context);
-
- if (p is Array)
- {
- Array pa = p as Array;
- return pa.GetValue((int)i);
- }
-
- foreach (PropertyInfo pi in p.GetType().GetProperties())
- {
- ParameterInfo[] infos = pi.GetIndexParameters();
- if (infos.Length == 1)
- {
- if (infos[0].ParameterType.IsAssignableFrom(itype))
- {
- return pi.GetValue(p, new object[] { i });
- }
- }
- }
- throw new KeyNotFoundException();
- }
- }
-
- class MethodCall : Eval
- {
- Eval[] Parameters;
- String Name;
-
- public MethodCall(Eval parent, String name,params Eval[] p)
- : base(parent)
- {
- Name = name;
- Parameters = p;
- }
-
- public override object Evaluate(Context context)
- {
- object p = Parent.Evaluate(context);
-
- object[] pvalues = new object[Parameters.Length];
- Type[] ptypes = new Type[Parameters.Length];
-
- for (int i=0;i char.IsLetterOrDigit(ch));
- //}
-
- //abstract class Token
- //{
- // public abstract object Evaluate();
- //}
-
- //class Field : Token
- //{
- // Token owner;
- // String fieldName;
-
- // public Field(Token owner,String fieldName)
- // {
- // this.owner = owner;
- // this.fieldName = fieldName;
- // }
-
- // public override object Evaluate()
- // {
- // if (o == null)
- // return null;
-
- // Type t = o.GetType();
- // FieldInfo fieldInfo = t.GetField(this.fieldName);
- // if (fieldInfo != null)
- // {
- // return fieldInfo.GetValue(owner.Evaluate());
- // }
- // PropertyInfo propertyInfo = t.GetProperty(this.fieldName);
- // if (propertyInfo != null)
- // {
- // return propertyInfo.GetValue(owner.Evaluate());
- // }
- // throw new MissingFieldException(t.FullName, this.fieldName);
- // }
- //}
-
- }
-
-
-
-}
diff --git a/ln.templates/FileSystemTemplateResolver.cs b/ln.templates/FileSystemTemplateResolver.cs
new file mode 100644
index 0000000..264434f
--- /dev/null
+++ b/ln.templates/FileSystemTemplateResolver.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using ln.templates.html;
+
+namespace ln.templates
+{
+ public class FileSystemTemplateSource : ITemplateResolver
+ {
+ public String BasePath { get; }
+ public bool Throws { get; }
+
+ Dictionary _templates = new Dictionary();
+
+ public FileSystemTemplateSource(String path,bool throws)
+ :this(path)
+ {
+ Throws = throws;
+ }
+ public FileSystemTemplateSource(String path)
+ {
+ path = Path.GetFullPath(path);
+
+ if (!Directory.Exists(path))
+ throw new FileNotFoundException();
+ BasePath = path;
+ }
+
+ public Template GetTemplateByPath(string path) => GetTemplateByPath(path, Throws);
+ public Template GetTemplateByPath(string path,bool _throw)
+ {
+ string templatePath = Path.Combine(BasePath, path);
+ if (!File.Exists(templatePath))
+ {
+ if (_templates.ContainsKey(path))
+ _templates.Remove(path);
+
+ if (_throw)
+ throw new FileNotFoundException();
+ return null;
+ }
+
+ if (!_templates.TryGetValue(path,out Template template))
+ {
+ template = new Template(templatePath, this);
+ _templates[path] = template;
+ }
+
+ return template;
+ }
+ }
+}
diff --git a/ln.templates/FormContext.cs b/ln.templates/FormContext.cs
deleted file mode 100644
index 5cac569..0000000
--- a/ln.templates/FormContext.cs
+++ /dev/null
@@ -1,254 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Reflection;
-using System.Linq;
-using System.ComponentModel;
-using System.Resources;
-
-namespace ln.templates
-{
- //public class FormContext
- //{
- //private Dictionary vars = new Dictionary();
- //protected MemoryStream contentStream, headStream;
-
- //public Template SharpForm { get; }
- //public Request Request { get; }
-
- //public Stream ContentStream => contentStream;
- //public TextWriter ContentWriter { get; protected set; }
-
- //public Stream HeadStream => headStream;
- //public TextWriter HeadWriter { get; protected set; }
-
- //public FormContext Parent { get; }
- //public bool UsesClonedVars { get; }
-
- //public bool IsRootContext => Parent == null;
-
- //public FormContext SubFrameContext { get; protected set; }
-
- //public FormContext(Template sharpForm,Request request,object o)
- //{
- // Parent = null;
-
- // SharpForm = sharpForm;
- // Request = request;
-
- // contentStream = new MemoryStream();
- // ContentWriter = new StreamWriter(contentStream);
-
- // headStream = new MemoryStream();
- // HeadWriter = new StreamWriter(headStream);
-
- // vars["o"] = o;
- // vars["this"] = o;
- // vars["StrMax"] = GetType().GetMethod("StrMax");
- //}
-
- //public FormContext(FormContext parent,bool cloneVars = false,bool independentContent = false,FormContext subFrameContext = null)
- //{
- // Parent = parent;
-
- // SharpForm = parent.SharpForm;
- // Request = parent.Request;
-
- // contentStream = independentContent ? new MemoryStream() : parent.contentStream;
- // ContentWriter = new StreamWriter(ContentStream);
-
- // headStream = parent.headStream;
- // HeadWriter = parent.HeadWriter;
-
- // UsesClonedVars = cloneVars;
-
- // SubFrameContext = subFrameContext == null ? parent.SubFrameContext : subFrameContext;
-
- // if (cloneVars){
- // foreach (KeyValuePair var in parent.vars)
- // {
- // this.vars.Add(var.Key, var.Value);
- // }
- // }
-
- // parent.ContentWriter.Flush();
- //}
-
- //public byte[] ContentBytes
- //{
- // get
- // {
- // ContentWriter.Flush();
- // return contentStream.ToArray();
- // }
- //}
- //public byte[] HeadBytes
- //{
- // get
- // {
- // HeadWriter.Flush();
- // return headStream.ToArray();
- // }
- //}
- //public String Content => Encoding.UTF8.GetString(ContentBytes);
- //public String Head => Encoding.UTF8.GetString(HeadBytes);
-
- //public void Insert(FormContext context, bool allToHead = false)
- //{
- // if (context.headStream != headStream)
- // {
- // HeadWriter.Flush();
- // byte[] headBytes = context.HeadBytes;
- // headStream.Write(headBytes, 0, headBytes.Length);
- // }
-
- // ContentWriter.Flush();
- // byte[] contentBytes = context.ContentBytes;
-
- // if (allToHead)
- // headStream.Write(contentBytes, 0, contentBytes.Length);
- // else
- // contentStream.Write(contentBytes, 0, contentBytes.Length);
- //}
-
- //public bool HasVar(String name)
- //{
- // if (vars.ContainsKey(name))
- // return true;
- // if (!UsesClonedVars && (Parent != null))
- // return Parent.HasVar(name);
-
- // return false;
- //}
-
- //public object Get(String name){
- // if (vars.ContainsKey(name))
- // return vars[name];
- // else if (Parent != null)
- // return Parent.Get(name);
- // else
- // return null;
- //}
-
- //public void Set(String name,object value){
- // if (!UsesClonedVars && (Parent != null) && (Parent.HasVar(name)))
- // {
- // Parent.Set(name, value);
- // } else {
- // this.vars[name] = value;
- // }
- //}
-
-
- //public object EvaluateExpression(Token[] tokens)
- //{
- // if (tokens.Length == 0)
- // {
- // return "";
- // }
-
- // Stack tokenStack = new Stack(tokens);
- // object currentValue = null;
- // Token currentToken = null;
-
- // while (tokenStack.Count > 0){
- // currentToken = tokenStack.Pop();
-
- // if (currentToken is PathToken)
- // {
- // PathToken pathToken = (PathToken)currentToken;
- // Response response = Request.SubRequest(pathToken.Path);
- // if (response.Reference != null)
- // currentValue = response.Reference;
- // else
- // currentValue = Encoding.UTF8.GetString(response.ContentBytes);
- // } else if (currentToken is KeywordToken)
- // {
- // KeywordToken keywordToken = (KeywordToken)currentToken;
- // currentValue = keywordToken.Evaluate(this);
- // }
-
- // if (tokenStack.Count > 0){
- // currentToken = tokenStack.Pop();
- // throw new NotImplementedException("Currently no expression operators are implemented, sorry");
- // }
-
- // }
- // return currentValue;
- //}
-
- //public object EvaluateValue(String sValue)
- //{
- // Stack vpath = new Stack(sValue.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Reverse());
-
- // if (vpath.Count > 0)
- // {
- // object value = null;
- // string key = vpath.Pop();
-
- // value = Get(key);
-
- // while (vpath.Count > 0)
- // {
- // key = vpath.Pop();
- // value = GetObjectFieldOrProperty(value, key);
- // }
- // return value;
- // }
- // return null;
- //}
-
- //public bool EvaluateBoolean(String expression)
- //{
- // bool invert = (expression[0] == '!');
- // if (invert)
- // expression = expression.Substring(1);
-
- // object value = EvaluateValue(expression);
- // if (value != null)
- // {
- // if (
- // ((value is bool) && (((bool)value))) ||
- // ((value is string) && (!String.Empty.Equals(value))) ||
- // ((value is int) && (((int)value) != 0)) ||
- // ((value is long) && (((long)value) != 0)) ||
- // ((value is float) && (((float)value) != 0)) ||
- // ((value is double) && (((double)value) != 0))
- // )
- // {
- // return !invert;
- // }
- // }
- // return invert;
- //}
-
- //private object GetObjectFieldOrProperty(object o, string name)
- //{
- // if (o == null)
- // {
- // return null;
- // }
- // FieldInfo fieldInfo = o.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
- // if (fieldInfo != null)
- // {
- // return fieldInfo.GetValue(o);
- // }
- // PropertyInfo propertyInfo = o.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
- // if (propertyInfo != null)
- // {
- // return propertyInfo.GetValue(o);
- // }
-
- // throw new KeyNotFoundException(String.Format("object of type {0} has no field/property named {1}", o.GetType().FullName, name));
- //}
-
- //public static string StrMax(string s,int len,string suffix = "")
- //{
- // if (len < s.Length)
- // return s.Substring(0, len) + suffix;
- // return s;
- //}
-
-// }
-}
diff --git a/ln.templates/FormElement.cs b/ln.templates/FormElement.cs
deleted file mode 100644
index 4dfa845..0000000
--- a/ln.templates/FormElement.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using System.Xml;
-using System.Collections.Generic;
-namespace ln.templates
-{
- //public abstract class FormElement
- //{
- // /* Instance Members */
- // FormElement Container { get; }
- // List children = new List();
-
- // public FormElement(FormElement container)
- // {
- // Container = container;
- // if (container != null)
- // {
- // container.children.Add(this);
- // }
- // }
-
- // public abstract void Run(FormContext context);
-
- // public FormElement[] Children => children.ToArray();
- // public virtual Template Form => Container.Form;
-
- // public void RunChildren(FormContext context)
- // {
- // foreach (FormElement child in children)
- // {
- // child.Run(context);
- // }
- // }
-
- //}
-}
diff --git a/ln.templates/ITemplateResolver.cs b/ln.templates/ITemplateResolver.cs
new file mode 100644
index 0000000..4bd5fe7
--- /dev/null
+++ b/ln.templates/ITemplateResolver.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ln.templates.html;
+
+namespace ln.templates
+{
+ public interface ITemplateResolver
+ {
+ Template GetTemplateByPath(string path);
+ }
+}
diff --git a/ln.templates/RecursiveResolver.cs b/ln.templates/RecursiveResolver.cs
new file mode 100644
index 0000000..92d7fbf
--- /dev/null
+++ b/ln.templates/RecursiveResolver.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Esprima.Ast;
+using ln.templates.html;
+
+namespace ln.templates;
+
+public class RecursiveResolver : ITemplateResolver
+{
+ public RecursiveResolver(string path)
+ :this(null, path)
+ {
+ }
+
+ private RecursiveResolver(RecursiveResolver parent, string path)
+ {
+ Parent = parent;
+ Path = path;
+ if (!Directory.Exists(path))
+ throw new DirectoryNotFoundException(path);
+ }
+
+ public RecursiveResolver Root => Parent?.Root ?? this;
+ public RecursiveResolver Parent { get; private set; }
+ public string Path { get; private set; }
+
+ private bool IsAlive => Directory.Exists(Path);
+
+ private Dictionary _children = new Dictionary();
+ private Dictionary _templates = new Dictionary();
+
+
+ public RecursiveResolver FindResolver(string path) => FindResolver(
+ System.IO.Path.GetDirectoryName(path)?.Split(System.IO.Path.PathSeparator) ?? Array.Empty());
+ private RecursiveResolver FindResolver(Span pathElements)
+ {
+ if (pathElements.Length == 0)
+ throw new ArgumentOutOfRangeException(nameof(pathElements));
+
+ if (_children.TryGetValue(pathElements[0], out RecursiveResolver child))
+ {
+ if (!child.IsAlive)
+ {
+ _children.Remove(pathElements[0]);
+ return null;
+ }
+ if (pathElements.Length > 1)
+ return child.FindResolver(pathElements.Slice(1));
+ return child;
+ }
+
+ return null;
+ }
+
+
+ public Template GetTemplateByPath(string templatePath)
+ {
+ Span pathElements = templatePath.Split(System.IO.Path.DirectorySeparatorChar);
+ RecursiveResolver resolver = FindResolver(pathElements.Slice(0, pathElements.Length - 1));
+ return resolver?.GetTemplate(pathElements[^1]);
+ }
+
+ public Template GetTemplate(string name)
+ {
+ string filename = System.IO.Path.Combine(Path, name);
+ if (File.Exists(filename))
+ {
+ if (!_templates.TryGetValue(name, out Template template))
+ {
+ template = new Template(filename, this);
+ _templates.Add(name, template);
+ }
+
+ return template;
+ }
+
+ return null;
+ }
+
+
+}
\ No newline at end of file
diff --git a/ln.templates/Template.cs b/ln.templates/Template.cs
index 6bd7b31..c9341e2 100644
--- a/ln.templates/Template.cs
+++ b/ln.templates/Template.cs
@@ -1,132 +1,56 @@
-using System;
+using System;
+using System.Collections.Generic;
using System.IO;
-using System.Text;
-using ln.templates.elements;
+using ln.templates.html;
-namespace ln.templates
+namespace ln.templates;
+
+public class Template
{
- public class Template
+ public Template(string filename, ITemplateResolver resolver)
+ :this(filename, resolver, null)
+ {}
+
+ private Template(string filename, ITemplateResolver resolver, string source)
{
- public TemplateProvider Provider { get; private set; }
- public String SourceFilename { get; private set; }
- public String PseudoFilename { get; private set; }
- public DateTime SourceTimeStamp { get; private set; }
+ FileName = filename;
+ Resolver = resolver;
- public Element RootElement { get; private set; }
-
- public Expression FrameExpression { get; private set; }
-
- public Template(String sourceFilename)
+ if (source is null)
{
- SourceFilename = sourceFilename;
- PseudoFilename = sourceFilename;
-
- LoadSource(null);
+ Load();
}
-
- public Template(String sourceFilename, TemplateProvider provider)
+ else
{
- Provider = provider;
- SourceFilename = sourceFilename;
- PseudoFilename = sourceFilename;
-
- LoadSource(null);
+ Document = TemplateReader.Parse(source);
}
-
- public Template(String source,String pseudoFilename,TemplateProvider provider)
- {
- Provider = provider;
- PseudoFilename = pseudoFilename;
-
- LoadSource(source);
- }
-
- private void LoadSource(String source)
- {
- if (source == null)
- {
- using (FileStream fileStream = new FileStream(SourceFilename, FileMode.Open))
- {
- byte[] loadBuffer = new byte[fileStream.Length];
- fileStream.Read(loadBuffer, 0, loadBuffer.Length);
- fileStream.Close();
- source = Encoding.UTF8.GetString(loadBuffer);
-
- SourceTimeStamp = File.GetLastWriteTimeUtc(SourceFilename);
- }
- }
-
- TemplateReader templateReader = new TemplateReader(source);
-
- RootElement = templateReader.RootElement;
- FrameExpression = templateReader.FrameExpression;
- }
-
- public String Generate()
- {
- return Generate(false);
- }
- public String Generate(bool unframed)
- {
- Context context = new Context(this);
- return Generate(context);
- }
- public String Generate(Context context)
- {
- return Generate(context, false);
- }
- public String Generate(Context context,bool unframed)
- {
- if (SourceFilename != null)
- {
- DateTime ts = File.GetLastWriteTimeUtc(SourceFilename);
- if (ts > SourceTimeStamp)
- LoadSource(null);
- }
-
- StringWriter writer = new StringWriter();
- RootElement.Generate(writer, context);
-
- if (!unframed && (FrameExpression != null))
- {
- Template frame = context.Provider.FindTemplate(FrameExpression.Evaluate(context.ExpressionContext) as string);
- if (frame == null)
- {
- throw new NullReferenceException(String.Format("FindTemplate() returned null for {0}",FrameExpression.Source));
- }
- return frame.Generate(new Context(context, writer.ToString()));
- }
-
- return writer.ToString();
- }
-
-
- public class Context
- {
- public Context Parent { get; }
- public Template Template { get; }
- public TemplateProvider Provider => Template.Provider;
-
- public String FramedContent { get; }
- public Expression.Context ExpressionContext { get; }
-
- public Context(Template template)
- {
- Template = template;
- ExpressionContext = new Expression.Context(null, null);
- ExpressionContext.AddMappedValue("__template__", template.SourceFilename);
- ExpressionContext.AddMappedValue("__provider__", template.Provider);
- }
- public Context(Context parent,String framedContent)
- {
- Parent = parent;
- Template = parent.Template;
- FramedContent = framedContent;
- ExpressionContext = new Expression.Context(parent.ExpressionContext);
- if (framedContent != null)
- ExpressionContext.SetMappedValue("__frame__", framedContent);
- }
- }
-
}
-}
+
+ private void Load()
+ {
+ Document = TemplateReader.ReadTemplate(FileName);
+ LastWriteTime = File.GetLastWriteTime(FileName);
+ }
+
+
+ public ITemplateResolver Resolver { get; }
+ public string FileName { get; }
+ public TemplateDocument Document { get; private set; }
+ public DateTime LastWriteTime { get; private set; }
+
+ public void Render(TextWriter target) => Render(target, Array.Empty>());
+ public void Render(TextWriter target, IEnumerable> scriptObjects)
+ {
+ Context context = new Context(Resolver, scriptObjects, target);
+ Render(context);
+ }
+
+ public void Render(Context context)
+ {
+ DateTime currentLastWriteTime = File.GetLastWriteTime(FileName);
+ if (currentLastWriteTime > LastWriteTime)
+ Load();
+
+ Document.RenderTemplate(context);
+ }
+}
\ No newline at end of file
diff --git a/ln.templates/TemplateProvider.cs b/ln.templates/TemplateProvider.cs
deleted file mode 100644
index 158191b..0000000
--- a/ln.templates/TemplateProvider.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System;
-namespace ln.templates
-{
- public interface TemplateProvider
- {
- Template FindTemplate(string templatePath);
- }
-}
diff --git a/ln.templates/TemplateReader.cs b/ln.templates/TemplateReader.cs
index c1254bd..78c41ca 100644
--- a/ln.templates/TemplateReader.cs
+++ b/ln.templates/TemplateReader.cs
@@ -1,151 +1,104 @@
-using System;
-using System.Collections.Generic;
-using ln.templates.elements;
+// /**
+// * File: TemplateReader.cs
+// * Author: haraldwolff
+// *
+// * This file and it's content is copyrighted by the Author and / or copyright holder.
+// * Any use wihtout proper permission is illegal and may lead to legal actions.
+// *
+// *
+// **/
+using System;
using System.IO;
-using System.Text;
+using System.Net;
+using ln.templates.html;
+
namespace ln.templates
{
- public class TemplateReader
+ public class TemplateReader : ElementReader
{
- public ContainerElement RootElement { get; private set; } = new ContainerElement(null);
- public ContainerElement CurrentElement { get; private set; }
- public Expression FrameExpression { get; private set; }
+ public virtual TemplateDocument TemplateDocument => Document as TemplateDocument;
- public String Source { get; private set; }
-
- public TemplateReader(String source)
+ protected TemplateReader()
{
- Source = source;
- Parse();
}
- private void Parse()
+ public override DocumentElement CreateDocument() => new TemplateDocument();
+ public override Element CreateElement(string tagName) => TemplateElement.Create(tagName);
+
+ public override void CloseTag(string tagName)
{
- CurrentElement = RootElement;
-
- while (Source.Length > 0)
+ Element saveCurrentElement = CurrentElement;
+ base.CloseTag(tagName);
+
+ if (saveCurrentElement.HasAttribute("v-slot") && (saveCurrentElement.Parent is TemplateElement parentElement))
{
- String t, op;
- int i, j;
+ parentElement.SetSlot(saveCurrentElement.GetAttribute("v-slot"), saveCurrentElement);
+ parentElement.RemoveChild(saveCurrentElement);
+ saveCurrentElement.RemoveAttribute("v-slot");
+ }
+ }
- i = Source.IndexOf("<%");
- if (i == -1)
+ public override void Text(string text)
+ {
+ if (text.Contains("{{"))
+ {
+ int pOpen = 0;
+ int pClose = 0;
+
+ while (pOpen < text.Length)
{
- t = Source;
- op = null;
- Source = "";
- }
- else
- {
- t = Source.Substring(0, i);
- j = Source.IndexOf("%>", i + 1);
- if (j == -1)
+ pOpen = text.IndexOf("{{", pClose);
+ if (pOpen == -1)
+ pOpen = text.Length;
+
+ string preText = text.Substring(pClose, pOpen - pClose);
+ if (preText.Length > 0)
{
- throw new FormatException(String.Format("missing '%>' in {0}", Source.Substring(i, 64)));
+ CurrentElement.AppendChild(CreateTextElement(preText));
}
- op = Source.Substring(i + 2, j - i - 2);
- Source = Source.Substring(j + 2);
+
+ if (pOpen == text.Length)
+ break;
+
+ pOpen += 2;
+
+ pClose = text.IndexOf("}}", pOpen);
+ if (pClose == -1)
+ throw new FormatException("missing }}");
+
+ string expr = text.Substring(pOpen, pClose - pOpen);
+
+ pClose += 2;
+
+ CurrentElement.AppendChild(new ExpressionElement(expr));
}
- new TextElement(CurrentElement, t);
- if (op != null)
- ParseOP(op);
+ } else
+ {
+ CurrentElement.AppendChild(
+ CreateTextElement(text)
+ );
}
}
- private void ParseOP(String op)
+
+ public static TemplateDocument Parse(string source)
{
- StringReader reader = new StringReader(op);
- String opkey;
-
- if (reader.Peek() == '=')
- {
- reader.Read();
- opkey = "=";
- }
- else
- {
- opkey = reader.PopWord();
- }
-
- switch (opkey)
- {
- case "=":
- new ExpressionElement(CurrentElement, new Expression(reader.ReadToEnd()));
- break;
- case "frame":
- FrameExpression = new Expression(reader.ReadToEnd());
- break;
- case "iterate":
- String iterName = reader.PopWord();
- CurrentElement = new IteratorElement(CurrentElement, iterName, new Expression(reader.ReadToEnd()));
- break;
- case "if":
- CurrentElement = new ConditionalElement(CurrentElement, new Expression(reader.ReadToEnd()));
- break;
- case "else":
- if (CurrentElement is ConditionalElement)
- {
- ConditionalElement ce = CurrentElement as ConditionalElement;
- CurrentElement = ce.AlternativeContainer;
- }
- break;
- case "elseif":
- if (CurrentElement is ConditionalElement)
- {
- ConditionalElement ce = CurrentElement as ConditionalElement;
- CurrentElement = new ConditionalElement(null, new Expression(reader.ReadToEnd()));
- ce.AlternativeContainer = CurrentElement;
- }
- break;
-
- case "include":
- new IncludeElement(CurrentElement, new Expression(reader.ReadToEnd()));
- break;
-
- case "set":
- String setName = reader.PopWord();
- new SetElement(CurrentElement, setName, new Expression(reader.ReadToEnd()));
- break;
-
- case "end":
- CurrentElement = CurrentElement.Container;
- break;
- default:
- throw new NotImplementedException(opkey);
- }
+ using (StringReader reader = new StringReader(source))
+ return ReadTemplate(reader);
}
- }
-
- static class StringHelper
- {
- public static int IndexOf(this String s,Func predicate)
+ public static TemplateDocument ReadTemplate(string filename)
{
- for (int i=0;i children { get; } = new List();
-
- public ContainerElement(ContainerElement container)
- :base(container)
- {
- }
-
- public void GenerateChildren(TextWriter writer, Template.Context context)
- {
- foreach (Element c in children)
- c.Generate(writer, context);
- }
-
- public override void Generate(TextWriter writer, Template.Context context)
- {
- GenerateChildren(writer, context);
- }
-
- public Element[] Children
- {
- get => children.ToArray();
- }
- }
-
- public class TextElement : Element
- {
- public String Text { get; }
- public TextElement(ContainerElement container,String text)
- :base(container)
- {
- Text = text;
- }
-
- public override void Generate(TextWriter writer, Template.Context context)
- {
- writer.Write(Text);
- }
- }
-
- public class ExpressionElement : Element
- {
- public Expression Expression { get; }
-
- public ExpressionElement(ContainerElement container,Expression expression)
- :base(container)
- {
- Expression = expression;
- }
-
- public override void Generate(TextWriter writer, Template.Context context)
- {
- object v = Expression.Evaluate(context.ExpressionContext);
- if (v != null)
- writer.Write(v.ToString());
- }
- }
- public class SetElement : Element
- {
- public String SetName { get; }
- public Expression Expression { get; }
-
- public SetElement(ContainerElement container, String setName,Expression expression)
- : base(container)
- {
- SetName = setName;
- Expression = expression;
- }
-
- public override void Generate(TextWriter writer, Template.Context context)
- {
- object v = Expression.Evaluate(context.ExpressionContext);
- context.ExpressionContext.SetMappedValue(SetName, v);
- }
- }
-}
diff --git a/ln.templates/elements/IncludeElement.cs b/ln.templates/elements/IncludeElement.cs
deleted file mode 100644
index 7cd04d3..0000000
--- a/ln.templates/elements/IncludeElement.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.IO;
-using System.Collections.Generic;
-
-namespace ln.templates.elements
-{
- public class IncludeElement : Element
- {
- Expression TargetExpression { get; set; }
-
- public IncludeElement(ContainerElement container,Expression targetExpression)
- :base(container)
- {
- TargetExpression = targetExpression;
- }
-
- public void Generate(TextWriter writer, Template.Context context,String templatePath)
- {
- Template iTemplate = context.Provider.FindTemplate(templatePath);
- Template.Context iContext = new Template.Context(context, null);
- String iContent = iTemplate.Generate(iContext);
-
- writer.Write(iContent);
- }
-
- public override void Generate(TextWriter writer, Template.Context context)
- {
- object target = TargetExpression.Evaluate(context.ExpressionContext);
-
- if (target is IEnumerable)
- {
- IEnumerable targets = (IEnumerable)target;
- foreach (String t in targets)
- {
- Generate(writer, context, t);
- }
- }
- else
- {
- Generate(writer, context, target as String);
- }
-
- }
- }
-}
diff --git a/ln.templates/html/DocumentElement.cs b/ln.templates/html/DocumentElement.cs
index a80f486..7a4c85b 100644
--- a/ln.templates/html/DocumentElement.cs
+++ b/ln.templates/html/DocumentElement.cs
@@ -19,9 +19,12 @@ namespace ln.templates.html
{
}
+ public string DocType { get; set; }
+
public override void Render(TextWriter writer)
{
- writer.Write("");
+ if (DocType is not null)
+ writer.Write("", DocType);
foreach (Element element in Children)
element.Render(writer);
diff --git a/ln.templates/html/Element.cs b/ln.templates/html/Element.cs
index 5691e1b..5311cda 100644
--- a/ln.templates/html/Element.cs
+++ b/ln.templates/html/Element.cs
@@ -38,9 +38,17 @@ namespace ln.templates.html
public virtual bool HasAttribute(string attributeName) => attributes.ContainsKey(attributeName);
public virtual string GetAttribute(string attributeName) => attributes[attributeName];
public virtual void SetAttribute(string attributeName, string attributeValue) => attributes[attributeName] = attributeValue;
+ public virtual void RemoveAttribute(string attributeName) => attributes.Remove(attributeName);
+ public virtual string GetAttribute(string attributeName, string defaultValue)
+ {
+ if (attributes.TryGetValue(attributeName, out string value))
+ return value;
+ return defaultValue;
+ }
+
public IEnumerable Children => children;
- public void AppendChild(Element element)
+ public virtual void AppendChild(Element element)
{
if (element.Parent != null)
element.Parent.RemoveChild(element);
@@ -55,7 +63,7 @@ namespace ln.templates.html
element.Parent = this;
}
}
- public void RemoveChild(Element element)
+ public virtual void RemoveChild(Element element)
{
if (element.Parent != this)
throw new KeyNotFoundException();
diff --git a/ln.templates/html/ElementReader.cs b/ln.templates/html/ElementReader.cs
index 8bcaf16..1220764 100644
--- a/ln.templates/html/ElementReader.cs
+++ b/ln.templates/html/ElementReader.cs
@@ -61,6 +61,12 @@ namespace ln.templates.html
{
Pop();
}
+
+ public override void DOCTYPE(string type)
+ {
+ Document.DocType = type;
+ }
+
public override void Attribute(string attributeName, string attributeValue)
{
CurrentElement.SetAttribute(attributeName, attributeValue);
diff --git a/ln.templates/html/ExpressionElement.cs b/ln.templates/html/ExpressionElement.cs
index 435beab..33200a1 100644
--- a/ln.templates/html/ExpressionElement.cs
+++ b/ln.templates/html/ExpressionElement.cs
@@ -29,10 +29,10 @@ namespace ln.templates.html
writer.Write("{{{{{0}}}}}", ExpressionText);
}
- public override void RenderTemplate(RenderContext renderContext)
+ public override void RenderTemplate(Context renderContext)
{
- object o = Expression.Resolve(renderContext);
- renderContext.ContentWriter.Write(o?.ToString());
+ object o = Expression.Resolve(renderContext.Engine);
+ renderContext.TargetWriter.Write(o?.ToString());
}
diff --git a/ln.templates/html/FileSystemTemplateSource.cs b/ln.templates/html/FileSystemTemplateSource.cs
deleted file mode 100644
index 4878149..0000000
--- a/ln.templates/html/FileSystemTemplateSource.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace ln.templates.html
-{
- public class FileSystemTemplateSource : ITemplateSource
- {
- public String BasePath { get; }
- public bool Throws { get; }
-
- Dictionary templateDocuments = new Dictionary();
-
- public FileSystemTemplateSource(String path,bool throws)
- :this(path)
- {
- Throws = throws;
- }
- public FileSystemTemplateSource(String path)
- {
- if (!Directory.Exists(path))
- throw new FileNotFoundException();
- BasePath = path;
- }
-
- public TemplateDocument GetTemplateByPath(string path) => GetTemplateByPath(path, Throws);
- public TemplateDocument GetTemplateByPath(string path,bool _throw)
- {
- string templatePath = Path.Combine(BasePath, path);
- if (!File.Exists(templatePath))
- {
- if (templateDocuments.ContainsKey(path))
- templateDocuments.Remove(path);
-
- if (_throw)
- throw new FileNotFoundException();
- return null;
- }
-
- if (!templateDocuments.TryGetValue(path,out TemplateDocument templateDocument))
- {
- templateDocument = ReadTemplateDocument(path);
- templateDocuments[path] = templateDocument;
- } else
- {
- DateTime templateDateTime = File.GetLastWriteTime(templatePath);
- if (templateDateTime.Ticks != templateDocument.TemplateVersion)
- {
- templateDocument = ReadTemplateDocument(path);
- templateDocuments[path] = templateDocument;
- }
- }
-
- return templateDocument;
- }
-
- TemplateDocument ReadTemplateDocument(string path)
- {
- string templatePath = Path.Combine(BasePath, path);
-
- TemplateReader templateReader = new TemplateReader();
- using (StreamReader sr = new StreamReader(templatePath))
- {
- templateReader.Read(sr);
- }
- templateReader.TemplateDocument.TemplateVersion = File.GetLastWriteTime(templatePath).Ticks;
-
- return templateReader.TemplateDocument;
- }
- }
-}
diff --git a/ln.templates/html/HtmlReader.cs b/ln.templates/html/HtmlReader.cs
index be21375..b9f3679 100644
--- a/ln.templates/html/HtmlReader.cs
+++ b/ln.templates/html/HtmlReader.cs
@@ -13,7 +13,7 @@ using System.Collections.Generic;
using System.Text;
namespace ln.templates.html
{
- public class HtmlReader
+ public class HtmlReader
{
public HtmlReader()
{
@@ -124,7 +124,7 @@ namespace ln.templates.html
}
void ReadLWS(TextReader textReader) => ReadToken(textReader, char.IsWhiteSpace);
- public string ReadTagName(TextReader textReader) => ReadTokenLWS(textReader, (ch) => char.IsLetterOrDigit(ch));
+ public string ReadTagName(TextReader textReader) => ReadTokenLWS(textReader, (ch) => char.IsLetterOrDigit(ch) || (ch == '-'));
public string ReadAttributeName(TextReader textReader) => ReadTokenLWS(textReader, (ch) => !char.IsWhiteSpace(ch) && (ch != '\0') && (ch != '"') && (ch != '\'') && (ch != '>') && (ch != '/') && (ch != '='));
public string ReadAttributeValue(TextReader textReader)
{
@@ -147,7 +147,7 @@ namespace ln.templates.html
public void ReadText(TextReader textReader)
{
StringBuilder stringBuilder = new StringBuilder();
- while (textReader.Peek() != '<')
+ while ((textReader.Peek() >= 0) && (textReader.Peek() != '<'))
stringBuilder.Append((char)textReader.Read());
Text(stringBuilder.ToString());
diff --git a/ln.templates/html/ITemplateSource.cs b/ln.templates/html/ITemplateSource.cs
deleted file mode 100644
index 1dde637..0000000
--- a/ln.templates/html/ITemplateSource.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace ln.templates.html
-{
- public interface ITemplateSource
- {
- TemplateDocument GetTemplateByPath(string path);
- }
-}
diff --git a/ln.templates/html/RenderContext.cs b/ln.templates/html/RenderContext.cs
deleted file mode 100644
index 39406fd..0000000
--- a/ln.templates/html/RenderContext.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// /**
-// * File: RenderContext.cs
-// * Author: haraldwolff
-// *
-// * This file and it's content is copyrighted by the Author and / or copyright holder.
-// * Any use wihtout proper permission is illegal and may lead to legal actions.
-// *
-// *
-// **/
-using System;
-using System.IO;
-using System.Collections.Generic;
-using ln.templates.script;
-namespace ln.templates.html
-{
- public class RenderContext : IScriptContext
- {
- public TextWriter ContentWriter { get; }
- public ITemplateSource TemplateSource { get; set; }
-
- Dictionary scriptObjects = new Dictionary();
- public IEnumerable ScriptObjectNames => scriptObjects.Keys;
-
- public RenderContext(TextWriter contentWriter)
- {
- ContentWriter = contentWriter;
- }
- public RenderContext(TextWriter contentWriter,ITemplateSource templateSource)
- :this(contentWriter)
- {
- TemplateSource = templateSource;
- }
-
- Dictionary values = new Dictionary();
-
- public object GetScriptObject(string itemName) => scriptObjects[itemName];
- public void SetScriptObject(string itemName, object value) => scriptObjects[itemName] = value;
- }
-}
diff --git a/ln.templates/html/TemplateDocument.cs b/ln.templates/html/TemplateDocument.cs
index 4d45f19..5ef8c8f 100644
--- a/ln.templates/html/TemplateDocument.cs
+++ b/ln.templates/html/TemplateDocument.cs
@@ -13,30 +13,22 @@ namespace ln.templates.html
{
public class TemplateDocument : DocumentElement
{
- public long TemplateVersion { get; set; }
-
public TemplateDocument()
{
}
-
- public void RenderTemplate(TextWriter contentWriter) => RenderTemplate(new RenderContext(contentWriter));
- public void RenderTemplate(RenderContext renderContext,bool withoutDocType = false)
+
+ public void RenderTemplate(Context renderContext)
{
- if (!withoutDocType)
- renderContext.ContentWriter.Write("");
+ if (DocType is not null)
+ renderContext.TargetWriter.Write("", DocType);
- foreach (Element element in Children)
+ foreach (var child in Children)
{
- if (element is TemplateElement templateElement)
- {
+ if (child is TemplateElement templateElement)
templateElement.RenderTemplate(renderContext);
- } else
- {
- renderContext.ContentWriter.Write(element.ToString());
- }
+ else
+ child.Render(renderContext.TargetWriter);
}
-
- renderContext.ContentWriter.Flush();
}
}
}
diff --git a/ln.templates/html/TemplateElement.SlotElement.cs b/ln.templates/html/TemplateElement.SlotElement.cs
new file mode 100644
index 0000000..e6ce7b0
--- /dev/null
+++ b/ln.templates/html/TemplateElement.SlotElement.cs
@@ -0,0 +1,23 @@
+namespace ln.templates.html;
+
+public partial class TemplateElement
+{
+ private class SlotElement : TemplateElement
+ {
+ public SlotElement(string tagName)
+ :base(tagName){}
+
+ public string Name => GetAttribute("name", "");
+ public override void RenderElement(Context renderContext)
+ {
+ if (renderContext.TryGetSlot(Name, out Element slot))
+ {
+ RenderElements(new Context(renderContext), new []{ slot });
+ }
+ else
+ {
+ RenderElements(new Context(renderContext), Children);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ln.templates/html/TemplateElement.cs b/ln.templates/html/TemplateElement.cs
index dc2794d..7b9d5d3 100644
--- a/ln.templates/html/TemplateElement.cs
+++ b/ln.templates/html/TemplateElement.cs
@@ -10,24 +10,33 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Jint.Native;
+using Jint.Native.Object;
using ln.templates.script;
namespace ln.templates.html
{
- public class TemplateElement : Element
+ public partial class TemplateElement : Element
{
+ private static string[] hiddenTags = new[] { "template", "slot" };
+
Dictionary expressions = new Dictionary();
Dictionary loops = new Dictionary();
List conditions = new List();
- NewExpression includeExpression;
+ private Dictionary _slots = new Dictionary();
+
+ private NewExpression classExpression;
bool hideTag;
public TemplateElement(string tagName)
:base(tagName)
{
- hideTag = "template".Equals(tagName.ToLower());
+ hideTag = hiddenTags.Contains(tagName.ToLower());
}
public override void SetAttribute(string attributeName, string attributeValue)
@@ -36,27 +45,50 @@ namespace ln.templates.html
loops.Add(attributeName.Substring(6), new NewExpression(attributeValue));
else if (attributeName.Equals("v-if", StringComparison.InvariantCultureIgnoreCase))
conditions.Add(new NewExpression(attributeValue));
- else if (attributeName.Equals("v-include", StringComparison.InvariantCultureIgnoreCase))
- includeExpression = new NewExpression(attributeValue);
+ else if (attributeName.Equals(":class", StringComparison.InvariantCultureIgnoreCase))
+ classExpression = new NewExpression(attributeValue);
+ else if (attributeName.StartsWith("::"))
+ base.SetAttribute(attributeName, attributeValue);
else if (attributeName[0] == ':')
expressions.Add(attributeName.Substring(1), new NewExpression(attributeValue));
else
base.SetAttribute(attributeName, attributeValue);
}
- public virtual void RenderTemplate(RenderContext renderContext)
+ public void SetSlot(string slotName, Element slotElement)
{
- if (loops.Count == 0)
- {
- RenderElement(renderContext);
- } else
- {
- Stack> loopStack = new Stack>(loops);
- DoLoop(renderContext, loopStack);
- }
+ _slots.Add(slotName, slotElement);
+ }
+
+ /**
+ * This is the render method to be called from external callers
+ */
+ public virtual void RenderTemplate(Context renderContext)
+ {
+ if (loops.Count == 0)
+ {
+ RenderElement(renderContext);
+ }
+ else
+ {
+ Stack> loopStack =
+ new Stack>(loops);
+ DoLoop(renderContext, loopStack);
+ }
}
- void DoLoop(RenderContext renderContext, Stack> loopStack)
+ private Template TemplateFromExpression(Context renderContext, NewExpression expression)
+ {
+ object templateValue = expression.Resolve(renderContext.Engine);
+ if (!(templateValue is Template template))
+ {
+ template = renderContext.Resolver.GetTemplateByPath((string)templateValue);
+ }
+
+ return template;
+ }
+
+ protected virtual void DoLoop(Context renderContext, Stack> loopStack)
{
if (loopStack.Count == 0)
{
@@ -64,77 +96,193 @@ namespace ln.templates.html
} else
{
KeyValuePair loop = loopStack.Pop();
- IEnumerable enumerable = (IEnumerable)loop.Value.Resolve(renderContext);
- foreach (object o in enumerable)
+ IEnumerable enumerable = (IEnumerable)loop.Value.Resolve(renderContext.Engine);
+ if (enumerable != null)
{
- renderContext.SetScriptObject(loop.Key, o);
- DoLoop(renderContext, loopStack);
+ bool hadBinding = renderContext.Engine.Realm.GlobalEnv.HasBinding(loop.Key);
+ JsValue _save = null;
+ if (hadBinding)
+ _save = renderContext.Engine.Realm.GlobalEnv.GetBindingValue(loop.Key, false);
+ try
+ {
+
+ foreach (object o in enumerable)
+ {
+ renderContext.Engine.SetValue(loop.Key, o);
+ DoLoop(renderContext, loopStack);
+ }
+ }
+ finally
+ {
+ if (hadBinding)
+ renderContext.Engine.Realm.GlobalEnv.SetMutableBinding(loop.Key, _save, false);
+ else
+ renderContext.Engine.Realm.GlobalEnv.DeleteBinding(loop.Key);
+ }
}
loopStack.Push(loop);
}
}
- void RenderElement(RenderContext renderContext)
+ /**
+ * This is the render method to be called to render the element itself (tag, attributes, children, ... )
+ */
+ public virtual void RenderElement(Context renderContext)
{
if (checkConditions(renderContext))
{
- if (includeExpression != null)
+ if (TryGetAttribute(renderContext, "v-include", out string templatePath))
{
- object includeValue = includeExpression.Resolve(renderContext);
- if (!(includeValue is TemplateDocument includeTemplate))
- {
- includeTemplate = renderContext.TemplateSource.GetTemplateByPath((string)includeValue);
- }
- includeTemplate.RenderTemplate(renderContext, true);
+ Template template = renderContext.Resolver.GetTemplateByPath(templatePath);
+ Context context = new Context(renderContext);
+ if (this._slots.Count == 0)
+ context.SetSlot("", this);
+ else
+ context.SetSlots(this._slots);
+
+ template.Render(context);
}
else
{
if (!hideTag)
{
- renderContext.ContentWriter.Write("<{0}", Name);
- foreach (KeyValuePair attributePair in Attributes)
- renderContext.ContentWriter.Write(" {0}=\"{1}\"", attributePair.Key, attributePair.Value);
-
- foreach (KeyValuePair keyValuePair in expressions)
+ object classObject = null;
+ if (classExpression is not null)
{
- object value = keyValuePair.Value.Resolve(renderContext);
- if (value != null)
+ classObject = renderContext.Engine.Evaluate("(function(){ return " + classExpression
+ .ExpressionText + ";})()");
+ }
+
+ renderContext.TargetWriter.Write("<{0}", Name);
+ foreach (KeyValuePair attributePair in Attributes)
+ {
+ if (attributePair.Key.Equals("class") && (classObject is ObjectInstance classObjectInstance))
{
- renderContext.ContentWriter.Write(" {0}=\"{1}\"", keyValuePair.Key, value);
+ StringBuilder valueBuilder = new StringBuilder(attributePair.Value);
+ foreach (var property in classObjectInstance.GetOwnProperties())
+ {
+ if ((property.Value.Value is JsBoolean jsBooleanValue) &&
+ jsBooleanValue.Equals(JsBoolean.True))
+ valueBuilder.AppendFormat(" {0}", property.Key.ToString());
+ }
+
+ renderContext.TargetWriter.Write(" {0}=\"{1}\"", attributePair.Key,
+ valueBuilder.ToString());
+ }
+ else
+ {
+ renderContext.TargetWriter.Write(" {0}=\"{1}\"", attributePair.Key,
+ attributePair.Value);
}
}
- renderContext.ContentWriter.Write(">");
+ foreach (KeyValuePair keyValuePair in expressions)
+ {
+ object value = keyValuePair.Value.Resolve(renderContext.Engine);
+ if (value != null)
+ {
+ renderContext.TargetWriter.Write(" {0}=\"{1}\"", keyValuePair.Key, value);
+ }
+ }
+
+ renderContext.TargetWriter.Write(">");
}
if (!IsVoid)
{
- foreach (Element element in Children)
- {
- if (element is TemplateElement templateElement)
- {
- templateElement.RenderTemplate(renderContext);
- }
- else
- {
- renderContext.ContentWriter.Write(element.ToString());
- }
- }
-
+ RenderElements(renderContext, Children);
+
if (!hideTag)
- renderContext.ContentWriter.Write("{0}>", Name);
+ renderContext.TargetWriter.Write("{0}>", Name);
}
}
}
}
- bool checkConditions(RenderContext renderContext)
+ public string GetAttribute(Context context, string attributeName)
+ {
+ if (expressions.TryGetValue(attributeName, out NewExpression expression))
+ return expression.Resolve(context.Engine).ToString();
+ return GetAttribute(attributeName);
+ }
+ public bool TryGetAttribute(Context context, string attributeName, out string attributeValue)
+ {
+ if (expressions.TryGetValue(attributeName, out NewExpression expression))
+ {
+ attributeValue = expression.Resolve(context.Engine).ToString();
+ return true;
+ }
+ else if (HasAttribute(attributeName))
+ {
+ attributeValue = GetAttribute(attributeName);
+ return true;
+ }
+
+ attributeValue = null;
+ return false;
+ }
+
+ protected void RenderElements(Context renderContext, IEnumerable elements)
+ {
+ foreach (Element element in elements)
+ {
+ if (element is TemplateElement templateElement)
+ {
+ templateElement.RenderTemplate(renderContext);
+ }
+ else
+ {
+ renderContext.TargetWriter.Write(element.ToString());
+ }
+ }
+ }
+
+ bool checkConditions(Context renderContext)
{
foreach (NewExpression condition in conditions)
- if (!condition.IsTrue(renderContext))
+ if (!condition.IsTrue(renderContext.Engine))
return false;
return true;
}
+ class TemplateScriptElement : TemplateElement
+ {
+ private StringBuilder scriptBuilder = new StringBuilder();
+
+ public TemplateScriptElement()
+ : base("template-script")
+ {
+ }
+
+ public override void AppendChild(Element element)
+ {
+ if (element is TextElement textElement)
+ {
+ scriptBuilder.Append(textElement.Text);
+ }
+ else
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+
+ public override void RenderElement(Context renderContext) =>
+ renderContext.Engine.Execute(scriptBuilder.ToString());
+
+ }
+
+ public static TemplateElement Create(string tagName)
+ {
+ switch (tagName)
+ {
+ case "slot":
+ return new SlotElement(tagName);
+ case "template-script":
+ return new TemplateScriptElement();
+ default:
+ return new TemplateElement(tagName);
+ }
+ }
}
}
diff --git a/ln.templates/html/TemplateReader.cs b/ln.templates/html/TemplateReader.cs
deleted file mode 100644
index 6704231..0000000
--- a/ln.templates/html/TemplateReader.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-// /**
-// * File: TemplateReader.cs
-// * Author: haraldwolff
-// *
-// * This file and it's content is copyrighted by the Author and / or copyright holder.
-// * Any use wihtout proper permission is illegal and may lead to legal actions.
-// *
-// *
-// **/
-using System;
-using System.IO;
-namespace ln.templates.html
-{
- public class TemplateReader : ElementReader
- {
-
- public virtual TemplateDocument TemplateDocument => Document as TemplateDocument;
-
- public TemplateReader()
- {
- }
-
- public override DocumentElement CreateDocument() => new TemplateDocument();
- public override Element CreateElement(string tagName) => new TemplateElement(tagName);
-
- public override void Text(string text)
- {
- if (text.Contains("{{"))
- {
- int pOpen = 0;
- int pClose = 0;
-
- while (pOpen < text.Length)
- {
- pOpen = text.IndexOf("{{", pClose);
- if (pOpen == -1)
- pOpen = text.Length;
-
- string preText = text.Substring(pClose, pOpen - pClose);
- if (preText.Length > 0)
- {
- CurrentElement.AppendChild(CreateTextElement(preText));
- }
-
- if (pOpen == text.Length)
- break;
-
- pOpen += 2;
-
- pClose = text.IndexOf("}}", pOpen);
- if (pClose == -1)
- throw new FormatException("missing }}");
-
- string expr = text.Substring(pOpen, pClose - pOpen - 1);
-
- pClose += 2;
-
- CurrentElement.AppendChild(new ExpressionElement(expr));
- }
-
- } else
- {
- CurrentElement.AppendChild(
- CreateTextElement(text)
- );
- }
- }
-
- }
-}
diff --git a/ln.templates/ln.templates.csproj b/ln.templates/ln.templates.csproj
index e4ebb05..d628acd 100644
--- a/ln.templates/ln.templates.csproj
+++ b/ln.templates/ln.templates.csproj
@@ -1,7 +1,10 @@
- netcoreapp3.1
+ 0.4.2
+ net5.0;net6.0
+ default
+ true
0.2.1-ci
@@ -13,7 +16,7 @@
-
+
diff --git a/ln.templates/script/IScriptContext.cs b/ln.templates/script/IScriptContext.cs
index 72d89ed..ae7c0e1 100644
--- a/ln.templates/script/IScriptContext.cs
+++ b/ln.templates/script/IScriptContext.cs
@@ -9,12 +9,12 @@
// **/
using System;
using System.Collections.Generic;
+using Jint;
+
namespace ln.templates.script
{
public interface IScriptContext
{
- IEnumerable ScriptObjectNames { get; }
- object GetScriptObject(string itemName);
- void SetScriptObject(string itemName, object value);
+ Engine GetEngine();
}
}
diff --git a/ln.templates/script/NewExpression.cs b/ln.templates/script/NewExpression.cs
index 74a3353..5be2889 100644
--- a/ln.templates/script/NewExpression.cs
+++ b/ln.templates/script/NewExpression.cs
@@ -9,8 +9,6 @@
// **/
using System;
using Jint;
-using Jint.Native;
-using Jint.Native.String;
namespace ln.templates.script
{
@@ -18,26 +16,20 @@ namespace ln.templates.script
{
public string ExpressionText { get; }
-
public NewExpression(string expression)
{
ExpressionText = expression;
}
- public virtual object Resolve(IScriptContext scriptContext)
+ public virtual object Resolve() => Resolve(new Engine());
+ public virtual object Resolve(Engine engine) =>
+ engine.Evaluate(ExpressionText).ToObject();
+
+ public virtual bool IsTrue() => IsTrue(new Engine());
+ public virtual bool IsTrue(Engine engine)
{
- Engine engine = new Engine();
- foreach (string itemName in scriptContext.ScriptObjectNames)
- engine.SetValue(itemName, scriptContext.GetScriptObject(itemName));
-
- JsValue jsv = engine.Eval.Call(null, new Jint.Native.JsValue[] { ExpressionText });
- return jsv.ToObject();
- }
-
- public virtual bool IsTrue(IScriptContext scriptContext)
- {
- object resolved = Resolve(scriptContext);
+ object resolved = Resolve(engine);
if (resolved == null)
return false;
if (resolved is bool b)
diff --git a/ln.templates/streams/CharStream.cs b/ln.templates/streams/CharStream.cs
deleted file mode 100644
index a2572d4..0000000
--- a/ln.templates/streams/CharStream.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Text;
-namespace ln.templates.streams
-{
- public class CharStream : PeekAbleStream
- {
- public CharStream(char[] buffer)
- :base(buffer)
- {
- }
- public CharStream(byte[] byteBuffer, Encoding encoding)
- : this(encoding.GetChars(byteBuffer))
- {
- }
- public CharStream(byte[] byteBuffer)
- :this(Encoding.UTF8.GetChars(byteBuffer))
- {
- }
- }
-}
diff --git a/ln.templates/streams/PeekableStream.cs b/ln.templates/streams/PeekableStream.cs
deleted file mode 100644
index ebc08ed..0000000
--- a/ln.templates/streams/PeekableStream.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-using System.Text;
-namespace ln.templates.streams
-{
- public class PeekAbleStream
- {
- private T[] buffer;
- private int position;
-
- public int Position => position;
- public bool EndOfBuffer => (position >= buffer.Length);
-
- public int MarkedPosition { get; set; }
-
- public PeekAbleStream(T[] buffer)
- {
- this.buffer = buffer;
- }
-
- public T Read(){
- if (position < buffer.Length)
- return buffer[position++];
-
- throw new IndexOutOfRangeException("Tried to read after end of buffer");
- }
-
- public T Peek(int shift = 0)
- {
- if ((position + shift) < buffer.Length)
- return buffer[position + shift];
-
- throw new IndexOutOfRangeException("Tried to peek after end of buffer");
- }
-
- public void Mark()
- {
- MarkedPosition = position;
- }
-
- public T[] GetMarkedIntervall()
- {
- T[] intervall = new T[position - MarkedPosition];
- Array.Copy(buffer, MarkedPosition, intervall, 0, intervall.Length);
- return intervall;
- }
-
- public int Remaining => buffer.Length - position;
-
- }
-}