(string massage, Request request, SearchResult searchResult = null) where T : Response, new()
+ {
+ var response = new T() as Response;
+ var culture = Culture;
+
+ try
+ {
+ culture = new CultureInfo(request?.Header?.AcceptLanguage?.FirstOrDefault()?.ToLower());
+ }
+ catch
+ {
+ }
+
+ if (searchResult != null)
+ {
+ var statusPage = ComponentManager.ResponseManager.CreateStatusPage
+ (
+ massage,
+ response.Status,
+ searchResult?.ModuleContext?.PluginContext ??
+ searchResult?.ApplicationContext?.PluginContext
+ );
+
+ if (statusPage == null)
+ {
+ return response;
+ }
+
+ if (statusPage is II18N i18n)
+ {
+ i18n.Culture = culture;
+ }
+
+ if (statusPage is Resource resource)
+ {
+ resource.ApplicationContext = searchResult?.ApplicationContext ?? new ApplicationContext()
+ {
+ PluginContext = searchResult?.ModuleContext?.PluginContext ??
+ searchResult?.ApplicationContext?.PluginContext,
+ ApplicationId = "webex",
+ ApplicationName = "WebExpress",
+ ContextPath = new UriResource()
+ };
+
+ resource.ModuleContext = searchResult?.ModuleContext ?? new ModuleContext()
+ {
+ ApplicationContext = resource.ApplicationContext,
+ PluginContext = searchResult?.ModuleContext?.PluginContext ??
+ searchResult?.ApplicationContext?.PluginContext,
+ ModuleId = "webex",
+ ModuleName = "WebExpress",
+ ContextPath = new UriResource()
+ };
+
+ resource.Initialization(new ResourceContext(resource.ModuleContext));
+ }
+
+ return statusPage.Process(request);
+ }
+
+ var message = $"{response.Status}" +
+ $"{massage}
" +
+ $"";
+
+ response.Content = message;
+ response.Header.ContentLength = message.Length;
+ response.Header.ContentType = "text/html; charset=utf-8";
+
+ return response;
+ }
+
+ ///
+ /// Create an HttpContext with a collection of HTTP features.
+ ///
+ /// A collection of HTTP features to use to create the HttpContext.
+ /// The HttpContext created.
+ public HttpContext CreateContext(IFeatureCollection contextFeatures)
+ {
+ try
+ {
+ return new HttpContext(contextFeatures, this.HttpServerContext);
+ }
+ catch (Exception ex)
+ {
+ return new HttpExceptionContext(ex, contextFeatures);
+ }
+ }
+
+ ///
+ /// Processes an http context asynchronously.
+ ///
+ /// The http context that the operation processes.
+ /// Provides an asynchronous operation that handles the http context.
+ public async Task ProcessRequestAsync(HttpContext context)
+ {
+ if (context is HttpExceptionContext exceptionContext)
+ {
+ var message = "
404" +
+ $"Message
{exceptionContext.Exception.Message}
" +
+ $"Source
{exceptionContext.Exception.Source}
" +
+ $"StackTrace
{exceptionContext.Exception.StackTrace.Replace("\n", "
\n")}
" +
+ $"InnerException
{exceptionContext.Exception.InnerException?.ToString().Replace("\n", "
\n")}" +
+ "";
+
+ var response500 = CreateStatusPage(message, context?.Request);
+
+ await SendResponseAsync(exceptionContext, response500);
+
+ return;
+ }
+
+ var response = HandleClient(context);
+
+ await SendResponseAsync(context, response);
+ }
+
+ ///
+ /// Discard a specified http context.
+ ///
+ /// The http context to discard.
+ /// The exception that is thrown if processing did not complete successfully; otherwise null.
+ public void DisposeContext(HttpContext context, Exception exception)
+ {
+ }
+ }
+}
diff --git a/src/WebExpress/HttpServerContext.cs b/src/WebExpress/HttpServerContext.cs
new file mode 100644
index 0000000..eb4f588
--- /dev/null
+++ b/src/WebExpress/HttpServerContext.cs
@@ -0,0 +1,111 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using WebExpress.Config;
+using WebExpress.WebUri;
+
+namespace WebExpress
+{
+ ///
+ /// The context of the http server.
+ ///
+ public class HttpServerContext : IHttpServerContext
+ {
+ ///
+ /// Returns the uri of the web server.
+ ///
+ public string Uri { get; protected set; }
+
+ ///
+ /// Returns the endpoints to which the web server responds.
+ ///
+ public ICollection Endpoints { get; protected set; }
+
+ ///
+ /// Returns the version of the http(s) server.
+ ///
+ public string Version { get; protected set; }
+
+ ///
+ /// Returns the package home directory.
+ ///
+ public string PackagePath { get; protected set; }
+
+ ///
+ /// Returns the asset home directory.
+ ///
+ public string AssetPath { get; protected set; }
+
+ ///
+ /// Returns the data home directory.
+ ///
+ public string DataPath { get; protected set; }
+
+ ///
+ /// Returns the configuration directory.
+ ///
+ public string ConfigPath { get; protected set; }
+
+ ///
+ /// Returns the basic context path.
+ ///
+ public UriResource ContextPath { get; protected set; }
+
+ ///
+ /// Returns the culture.
+ ///
+ public CultureInfo Culture { get; protected set; }
+
+ ///
+ /// Returns the log for writing status messages to the console and to a log file.
+ ///
+ public Log Log { get; protected set; }
+
+ ///
+ /// Returns the host.
+ ///
+ public IHost Host { get; protected set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The uri of the web server.
+ /// The endpoints to which the web server responds.
+ /// The package home directory.chnis
+ /// The asset home directory.
+ /// The data home directory.
+ /// The configuration directory.
+ /// The basic context path.
+ /// The culture.
+ /// The log.
+ /// The host.
+ public HttpServerContext
+ (
+ string uri,
+ ICollection endpoints,
+ string packageBaseFolder,
+ string assetBaseFolder,
+ string dataBaseFolder,
+ string configBaseFolder,
+ UriResource contextPath,
+ CultureInfo culture,
+ Log log,
+ IHost host
+ )
+ {
+ var assembly = typeof(HttpServer).Assembly;
+ Version = assembly.GetCustomAttribute()?.InformationalVersion;
+
+ Uri = uri;
+ Endpoints = endpoints;
+ PackagePath = packageBaseFolder;
+ AssetPath = assetBaseFolder;
+ DataPath = dataBaseFolder;
+ ConfigPath = configBaseFolder;
+ ContextPath = contextPath;
+ Culture = culture;
+ Log = log;
+ Host = host;
+ }
+ }
+}
diff --git a/src/WebExpress/IHost.cs b/src/WebExpress/IHost.cs
new file mode 100644
index 0000000..72e4eed
--- /dev/null
+++ b/src/WebExpress/IHost.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace WebExpress
+{
+ ///
+ /// The host interface.
+ ///
+ public interface IHost
+ {
+ ///
+ /// Returns the context of the host.
+ ///
+ IHttpServerContext HttpServerContext { get; }
+
+ ///
+ /// Event is triggered after the web server starts.
+ ///
+ event EventHandler Started;
+ }
+}
diff --git a/src/WebExpress/IHttpServerContext.cs b/src/WebExpress/IHttpServerContext.cs
new file mode 100644
index 0000000..7728ad1
--- /dev/null
+++ b/src/WebExpress/IHttpServerContext.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using System.Globalization;
+using WebExpress.Config;
+using WebExpress.WebUri;
+
+namespace WebExpress
+{
+ ///
+ /// The context interface of the http server.
+ ///
+ public interface IHttpServerContext
+ {
+ ///
+ /// Returns the uri of the web server.
+ ///
+ string Uri { get; }
+
+ ///
+ /// Returns the endpoints to which the web server responds.
+ ///
+ ICollection Endpoints { get; }
+
+ ///
+ /// Returns the version of the http(s) server.
+ ///
+ string Version { get; }
+
+ ///
+ /// Returns the package home directory.
+ ///
+ string PackagePath { get; }
+
+ ///
+ /// Returns the asset home directory.
+ ///
+ string AssetPath { get; }
+
+ ///
+ /// Returns the data home directory.
+ ///
+ string DataPath { get; }
+
+ ///
+ /// Returns the configuration directory.
+ ///
+ string ConfigPath { get; }
+
+ ///
+ /// Returns the basic context path.
+ ///
+ UriResource ContextPath { get; }
+
+ ///
+ /// Returns the culture.
+ ///
+ CultureInfo Culture { get; }
+
+ ///
+ /// Returns the log for writing status messages to the console and to a log file.
+ ///
+ Log Log { get; }
+
+ ///
+ /// Returns the host.
+ ///
+ IHost Host { get; }
+ }
+}
diff --git a/src/WebExpress/Internationalization/II18N.cs b/src/WebExpress/Internationalization/II18N.cs
new file mode 100644
index 0000000..978d6bb
--- /dev/null
+++ b/src/WebExpress/Internationalization/II18N.cs
@@ -0,0 +1,12 @@
+using System.Globalization;
+
+namespace WebExpress.Internationalization
+{
+ public interface II18N
+ {
+ ///
+ /// Returns or sets the culture.
+ ///
+ CultureInfo Culture { get; set; }
+ }
+}
diff --git a/src/WebExpress/Internationalization/InternationalizationDictionary.cs b/src/WebExpress/Internationalization/InternationalizationDictionary.cs
new file mode 100644
index 0000000..0a8f5d8
--- /dev/null
+++ b/src/WebExpress/Internationalization/InternationalizationDictionary.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace WebExpress.Internationalization
+{
+ ///
+ /// key = language (ISO 639-1 two-letter)
+ /// value = { key = , value = }
+ ///
+ internal class InternationalizationDictionary : Dictionary
+ {
+ }
+}
diff --git a/src/WebExpress/Internationalization/InternationalizationExtensions.cs b/src/WebExpress/Internationalization/InternationalizationExtensions.cs
new file mode 100644
index 0000000..5c0473d
--- /dev/null
+++ b/src/WebExpress/Internationalization/InternationalizationExtensions.cs
@@ -0,0 +1,42 @@
+using WebExpress.WebApplication;
+
+namespace WebExpress.Internationalization
+{
+ public static class InternationalizationExtensions
+ {
+ ///
+ /// Internationalization of a key.
+ ///
+ /// An internationalization object that is being extended.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(this II18N obj, string key)
+ {
+ return InternationalizationManager.I18N(obj, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// An internationalization object that is being extended.
+ /// The plugin id.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(this II18N obj, string pluginId, string key)
+ {
+ return InternationalizationManager.I18N(obj.Culture, pluginId, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// An internationalization object that is being extended.
+ /// The allication context.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(this II18N obj, IApplicationContext applicationContext, string key)
+ {
+ return InternationalizationManager.I18N(obj.Culture, applicationContext?.PluginContext?.PluginId, key);
+ }
+ }
+}
diff --git a/src/WebExpress/Internationalization/InternationalizationItem.cs b/src/WebExpress/Internationalization/InternationalizationItem.cs
new file mode 100644
index 0000000..75687c1
--- /dev/null
+++ b/src/WebExpress/Internationalization/InternationalizationItem.cs
@@ -0,0 +1,8 @@
+using System.Collections.Generic;
+
+namespace WebExpress.Internationalization
+{
+ internal class InternationalizationItem : Dictionary
+ {
+ }
+}
diff --git a/src/WebExpress/Internationalization/InternationalizationManager.cs b/src/WebExpress/Internationalization/InternationalizationManager.cs
new file mode 100644
index 0000000..49250a1
--- /dev/null
+++ b/src/WebExpress/Internationalization/InternationalizationManager.cs
@@ -0,0 +1,237 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using WebExpress.WebMessage;
+using WebExpress.WebComponent;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.Internationalization
+{
+ ///
+ /// Internationalization
+ ///
+ public sealed class InternationalizationManager : IComponentPlugin, ISystemComponent
+ {
+ ///
+ /// Returns the default language.
+ ///
+ public static CultureInfo DefaultCulture { get; private set; } = CultureInfo.CurrentCulture;
+
+ ///
+ /// Returns the directory by listing the internationalization key-value pairs.
+ ///
+ private static InternationalizationDictionary Dictionary { get; } = new InternationalizationDictionary();
+
+ ///
+ /// Returns or sets the reference to the context of the host.
+ ///
+ public IHttpServerContext HttpServerContext { get; private set; }
+
+ ///
+ /// Constructor
+ ///
+ internal InternationalizationManager()
+ {
+ ComponentManager.PluginManager.AddPlugin += (sender, pluginContext) =>
+ {
+ Register(pluginContext);
+ };
+
+ ComponentManager.PluginManager.RemovePlugin += (sender, pluginContext) =>
+ {
+ Remove(pluginContext);
+ };
+ }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ public void Initialization(IHttpServerContext context)
+ {
+ HttpServerContext = context;
+ DefaultCulture = HttpServerContext.Culture;
+
+ HttpServerContext.Log.Debug
+ (
+ I18N("webexpress:internationalizationmanager.initialization")
+ );
+ }
+
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A context of a plugin whose elements are to be registered.
+ public void Register(IPluginContext pluginContext)
+ {
+ var pluginId = pluginContext.PluginId;
+ Register(pluginContext.Assembly, pluginId);
+
+ HttpServerContext.Log.Debug
+ (
+ I18N("webexpress:internationalizationmanager.register", pluginId)
+ );
+ }
+
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A list with plugin contexts that contain the elements.
+ public void Register(IEnumerable pluginContexts)
+ {
+ foreach (var pluginContext in pluginContexts)
+ {
+ Register(pluginContext);
+ }
+ }
+
+ ///
+ /// Adds the internationalization key-value pairs from the specified assembly.
+ ///
+ /// The assembly that contains the key-value pairs to insert.
+ /// The id of the plugin to which the internationalization data will be assigned.
+ internal static void Register(Assembly assembly, string pluginId)
+ {
+ var assemblyName = assembly.GetName().Name.ToLower();
+ var name = assemblyName + ".internationalization.";
+ var resources = assembly.GetManifestResourceNames().Where(x => x.ToLower().Contains(name));
+
+ foreach (var languageResource in resources)
+ {
+ var language = languageResource.Split('.').LastOrDefault()?.ToLower();
+
+ if (!Dictionary.ContainsKey(language))
+ {
+ Dictionary.Add(language, new InternationalizationItem());
+ }
+
+ var dictItem = Dictionary[language];
+
+ using var stream = assembly.GetManifestResourceStream(languageResource);
+ using var streamReader = new StreamReader(stream);
+ while (!streamReader.EndOfStream)
+ {
+ var line = streamReader.ReadLine();
+ if (!line.StartsWith('#') && !string.IsNullOrWhiteSpace(line))
+ {
+ var split = line.Split('=');
+ var key = pluginId?.ToLower() + ":" + split[0]?.Trim().ToLower();
+
+ if (!dictItem.ContainsKey(key))
+ {
+ dictItem.Add(key, string.Join("=", split.Skip(1)));
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Removes all internationalization key-value pairs associated with the specified plugin context.
+ ///
+ /// The context of the plugin containing the key-value pairs to remove.
+ public void Remove(IPluginContext pluginContext)
+ {
+
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// An internationalization object that is being extended.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(II18N obj, string key)
+ {
+ return I18N(obj.Culture, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// The request with the language to use.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(Request request, string key)
+ {
+ return I18N(request.Culture, null, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// The culture with the language to use.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(CultureInfo culture, string key)
+ {
+ return I18N(culture, null, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// The culture with the language to use.
+ /// The plugin id.
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(CultureInfo culture, string pluginId, string key)
+ {
+ var language = culture?.TwoLetterISOLanguageName;
+ var k = string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(pluginId) || key.StartsWith($"{pluginId?.ToLower()}:") ? key?.ToLower() : $"{pluginId?.ToLower()}:{key?.ToLower()}";
+
+ if (string.IsNullOrWhiteSpace(key))
+ {
+ return null;
+ }
+
+ if (string.IsNullOrWhiteSpace(language) || language == "*")
+ {
+ language = DefaultCulture?.TwoLetterISOLanguageName;
+ }
+
+ var item = Dictionary[language];
+
+ if (item.ContainsKey(k))
+ {
+ return item[k];
+ }
+
+ return key;
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// The internationalization key.
+ /// The value of the key in the current language.
+ public static string I18N(string key)
+ {
+ return I18N(DefaultCulture, null, key);
+ }
+
+ ///
+ /// Internationalization of a key.
+ ///
+ /// The internationalization key.
+ /// The formatting arguments.
+ /// The value of the key in the current language.
+ public static string I18N(string key, params object[] args)
+ {
+ return string.Format(I18N(DefaultCulture, null, key), args);
+ }
+
+ ///
+ /// Information about the component is collected and prepared for output in the log.
+ ///
+ /// The context of the plugin.
+ /// A list of log entries.
+ /// The shaft deep.
+ public void PrepareForLog(IPluginContext pluginContext, IList output, int deep)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/Internationalization/de b/src/WebExpress/Internationalization/de
new file mode 100644
index 0000000..8880cbc
--- /dev/null
+++ b/src/WebExpress/Internationalization/de
@@ -0,0 +1,131 @@
+# Deutsch
+
+app.startup=Programmstart
+app.version=Programmversion: {0}
+app.arguments=Argumente: {0}
+app.workingdirectory=Arbeitsverzeichnis: {0}
+app.packagebase=Paketverzeichnis: {0}
+app.assetbase=Assetverzeichnis: {0}
+app.database=Datenverzeichnis: {0}
+app.configurationdirectory=Konfigurationsverzeichnis: {0}
+app.configuration=Konfiguration: {0}
+app.logdirectory=Logverzeichnis: {0}
+app.log=Log: {0}
+app.uri=Uri: {0}
+app.errors={0} Fehler
+app.warnings={0} Warnung(en)
+app.done=Programmende
+
+httpserver.run=Starte HttpServer.
+httpserver.notsupported=Das Betriebssystem auf dem WebExpress ausgeführt werden soll wird nicht unterstützt.
+httpserver.start=Der HttpServer wurde am {0} um {1} Uhr gestartet.
+httpserver.connected={0}: Client wurde verbunden.
+httpserver.rejected={0}: Client wurde abgelehnt.
+httpserver.request={0}: Anfrage #{1} '{2}'
+httpserver.request.unexpected={0}: Unerwartete Anfrage '{1}'
+httpserver.request.done={0}: Anfrage #{1} wurde in {2} ms bearbeitet. Status = {3}
+httpserver.connectionlimit=Das Limit für gleichzeitige Anfragen wurde überschritten.
+httpserver.endpoint=Endpunkt '{0}' wird registriert.
+httpserver.listen=Der Webserver lauscht auf den Endpunkt {0}.
+httpserver.listen.exeption=Fehler beim Einrichten eines Endpunktes für die Uri {0}.
+httpserver.listener.try=Falls Ihnen Zugriffsrechte fehlen, führen Sie unter Windows folgende Anweisung als Administrator aus:
+httpserver.listener.windows=netsh http add urlacl url={0} user=Jeder listen=yes
+
+componentmanager.initialization=Der Komponentenmanager wurde initialisiert.
+componentmanager.register=Die Komponente '{0}' wurde im Komponentenmanager registriert.
+componentmanager.execute=Startet den Komponenten-Manager.
+componentmanager.shutdown=Herunterfahren des Komponentenmanagers.
+componentmanager.wrongtype=Der Typ '{0}' implementiert die Schnittstelle '{1}' nicht.
+componentmanager.duplicate=Die Komponente '{0}' wurde bereits registriert.
+componentmanager.remove=Die Komponente '{0}' wurde entfernt.
+componentmanager.component=Komponenten:
+
+internationalizationmanager.initialization=Der Internationalisierungsmanager wurde initialisiert.
+internationalizationmanager.register=Das Plugin '{0}' wurde im Internationalizationmanager registriert.
+
+packagemanager.initialization=Der Paketmanager wurde initialisiert.
+packagemanager.existing=Das Paket '{0}' ist im Katalog registriert.
+packagemanager.add=Das Paket '{0}' wird im Katalog neu aufgenommen.
+packagemanager.remove=Das bestehende Paket '{0}' wird aus dem Katalog entfernt.
+packagemanager.scan=Das Verzeichnis '{0}' wird auf neue Pakete gescannt.
+packagemanager.save=Der Katalog wird gespeichert.
+packagemanager.packagenotfound=Das Paket '{0}' wurde nicht im Dateisystem gefunden.
+packagemanager.boot.notfound=Das Plugin '{0}' ist nicht bekannt.
+
+pluginmanager.initialization=Der Pluginmanager wurde initialisiert.
+pluginmanager.load={0}.dll wird geladen. Version = '{1}'
+pluginmanager.created=Das Plugin '{0}' wurde erstellt und im PluginManager registriert.
+pluginmanager.duplicate=Das Plugin '{0}' wurde bereits im PluginManager registriert.
+pluginmanager.notavailable=Das Plugin '{0}' ist im PluginManager nicht vorhanden.
+pluginmanager.plugin=Plugin: '{0}'
+pluginmanager.pluginmanager.label=Plugin Manager:
+pluginmanager.pluginmanager.system=Systemplugin: '{0}'
+pluginmanager.pluginmanager.custom=Benutzerdefiniertes Plugin: '{0}'
+pluginmanager.pluginmanager.unfulfilleddependencies=Plugin mit unerfüllten Abhängigkeiten: '{0}'
+pluginmanager.plugin.initialization=Das Plugin '{0}' wurde initialisiert.
+pluginmanager.plugin.processing.start=Das Plugin '{0}' wird ausgeführt.
+pluginmanager.plugin.processing.end=Die Ausführung des Plugin '{0}' wurde beendet.
+pluginmanager.fulfilleddependencies=Das Plugin '{0}' erfüllt alle Abhängigkeiten.
+pluginmanager.unfulfilleddependencies=Das Plugin '{0}' erfüllt eine Abhängigkeit zu dem Plugin '{1}' nicht.
+
+applicationmanager.initialization=Der Anwendungsmanager wurde initialisiert.
+applicationmanager.register=Die Anwendung '{0}' wurde erstellt und im Anwendungsmanager registriert.
+applicationmanager.duplicate=Die Anwendung '{0}' wurde bereits im Anwendungsmanager registriert.
+applicationmanager.application=Anwendung: '{0}'
+applicationmanager.application.initialization=Die Anwendung '{0}' wurde initialisiert.
+applicationmanager.application.processing.start=Die Anwendung '{0}' wird ausgeführt.
+applicationmanager.application.processing.end=Die Ausführung der Anwendung '{0}' wurde beendet.
+applicationmanager.application.boot.notfound=Das Plugin '{0}' ist nicht bekannt.
+
+modulemanager.initialization=Der Modulmanager wurde initialisiert.
+modulemanager.register=Das Modul '{0}' wurde der Anwendung '{1}' zugewiesen und im Modulmanager registriert.
+modulemanager.duplicat=Das Modul '{0}' wurde bereits in der Anwendung '{1}' registriert.
+modulemanager.applicationless=Das Modul '{0}' besitzt keine Angaben zur Anwendung.
+modulemanager.module=Module: '{0}' für die Anwendung(n) '{1}'
+modulemanager.module.initialization=Das Modul '{1}' der Anwendung {0} wurde initialisiert.
+modulemanager.module.processing.start=Das Modul '{1}' der Anwendung {0} wird ausgeführt.
+modulemanager.module.processing.end=Die Ausführung des Modul '{1}' der Anwendung {0} wurde beendet.
+
+resourcemanager.initialization=Der Ressourcenmanager wurde initialisiert.
+resourcemanager.register={0} Ressource(n) wurden dem Modul '{1}' zugewiesen.
+resourcemanager.modulenotfound=Das Modul '{1}' wurde nicht gefunden, welches in der Ressource '{0}' angegeben wurde.
+resourcemanager.moduleless=Die Ressource '{0}' besitzt keine Angaben zum Modul.
+resourcemanager.addresource=Die Ressource '{0}' wurde in dem Modul '{1}' registiert.
+resourcemanager.addresource.duplicate=Die Ressource '{0}' des Moduls '{1}' ist bereits hinzugefügt worden.
+resourcemanager.addresource.error=Die Ressource '{0}' des Moduls '{1}' konnte nicht hinzugefügt werden.
+resourcemanager.sitemap=Inhalt der Sitemap für das Modul '{0}':
+resourcemanager.wrongtype=Der Type '{0}' implementiert die Schnittstelle '{1}' nicht.
+resourcemanager.resource=Ressource: '{0}' für das Modul '{1}'
+
+responsemanager.initialization=Der Responsemanagermanager wurde initialisiert.
+responsemanager.register=Status {0} wurde im Module '{1}' registriert und der Statusseite '{2}' zugewiesen.
+responsemanager.duplicat=Der Status {0} wurde bereits im Module '{1}' registriert registriert. Die Statusseite '{2}' wird daher nicht verwendet.
+responsemanager.statuscode=Ein Statuscode wurde der Ressource '{1}' für das Modul '{0}' nicht zugewiesen.
+responsemanager.statuspage=Statuscode: '{0}'
+
+sitemapmanager.initialization=Der Sitemap-Manager wurde initialisiert.
+sitemapmanager.refresh=Die Sitemap wird neu aufgebaut.
+sitemapmanager.alreadyassigned=Der Knoten der Sitemap '{0}' ist bereits zugewiesen. Die Ressource '{1}' wird nicht in die Sitemap aufgenommen.
+sitemapmanager.addresource=Die Ressource '{0}' wurde in der Sitemap registriert.
+sitemapmanager.addresource.error=Die Ressource '{0}' konnte nicht in der Sitemap hinzugefügt werden.
+sitemapmanager.preorder={0} => {1}
+sitemapmanager.sitemap=Sitemap:
+sitemapmanager.merge.error=Die beiden Sitemaps '{0}' und '{1}' konnten nicht gemerdged werden.
+
+sessionmanager.initialization=Der Sessionmanager wurde initialisiert.
+
+eventmanager.initialization=Der Eventmanager wurde initialisiert.
+
+jobmanager.initialization=Der Schedulemanager wurde initialisiert.
+jobmanager.register=Das Plugin '{0}' wurde im Schedulemanager registriert.
+jobmanager.job.register=Der Job '{1}' wurden dem Modul '{0}' zugewiesen.
+jobmanager.moduleless=Der Job '{0}' besitzt keine Angaben zum Modul.
+jobmanager.wrongmodule=Der Job '{1}' ist kein Teil des Moduls {0}.
+jobmanager.job=Job: '{0}' für Modul '{1}'
+jobmanager.job.process=Der Job '{0}' wird ausgeführt.
+jobmanager.cron.parseerror=Syntaxfehler in der Zeitangabe eines Jobs. Der Wert '{0}' kann nicht verarbeitet werden.
+jobmanager.cron.range=Syntaxfehler in der Zeitangabe eines Jobs. Der Wert '{0}' ist außerhalb des gültigen Bereiches.
+
+resource.variable.duplicate=Variable '{0}' bereits vorhanden!
+resource.file={0}: Datei '{1}' wurde geladen.
+
diff --git a/src/WebExpress/Internationalization/en b/src/WebExpress/Internationalization/en
new file mode 100644
index 0000000..164d882
--- /dev/null
+++ b/src/WebExpress/Internationalization/en
@@ -0,0 +1,130 @@
+# Englisch
+
+app.startup=Startup
+app.version=Version: {0}
+app.arguments=Arguments: {0}
+app.workingdirectory=Working directory: {0}
+app.packagebase=Package directory: {0}
+app.assetbase=Asset directory: {0}
+app.database=Data directory: {0}
+app.configurationdirectory=Configuration directory: {0}
+app.configuration=Configuration: {0}
+app.logdirectory=Log directory: {0}
+app.log=Log: {0}
+app.uri=Uri: {0}
+app.errors={0} Errors
+app.warnings={0} Warnings
+app.done=End of program
+
+httpserver.run=Run HttpServer.
+httpserver.notsupported=The operating system on which WebExpress is to be run is not supported.
+httpserver.start=The HttpServer was started on {0} at {1} o'clock.
+httpserver.connected={0}: Client has been connected.
+httpserver.rejected={0}: Client rejected.
+httpserver.request={0}: Request '{1}'
+httpserver.unexpected.request={0}: Unexpected request '{1}'
+httpserver.request.done={0}: Request has been processed in {1} ms. Status = {2}
+httpserver.connectionlimit=The limit for concurrent requests has been exceeded.
+httpserver.endpoint=Endpoint '{0}' is registered.
+httpserver.listen=The web server listens for the endpoint {0}.
+httpserver.listen.exeption=Failed to set up an endpoint for the Uri {0}.
+httpserver.listener.try=If you do not have access rights follow the instruction as an administrator in the console:
+httpserver.listener.windows=netsh http add urlacl url={0} user=everyone listen=yes
+
+componentmanager.initialization=The component manager has been initialized.
+componentmanager.register=The component '{0}' has been registered in the component manager.
+componentmanager.execute=Starts the component manager.
+componentmanager.shutdown=Shutting down the component manager.
+componentmanager.wrongtype=The type '{0}' does not implement the interface '{1}'.
+componentmanager.duplicate=The component '{0}' has already been registered.
+componentmanager.remove=The component '{0}' has been removed.
+componentmanager.component=Components:
+
+internationalizationmanager.initialization=The internationalization manager has been initialized.
+internationalizationmanager.register=The plugin '{0}' is registered in the internationalization manager.
+
+packagemanager.initialization=The package manager has been initialized.
+packagemanager.existing=The package '{0}' is registered in the catalog.
+packagemanager.add=Package '{0}' is added to the catalog.
+packagemanager.remove=The existing package '{0}' is removed from the catalog.
+packagemanager.scan=The directory '{0}' is scanned for new packages.
+packagemanager.save=The catalog is saved.
+packagemanager.packagenotfound=The package '{0}' was not found in the file system.
+packagemanager.boot.notfound=The plugin '{0}' is unknown.
+
+pluginmanager.initialization=The plugin manager has been initialized.
+pluginmanager.load={0}.dll is loading. Version = '{1}'
+pluginmanager.created=The plugin '{0}' was created and registered in the plugin manager.
+pluginmanager.duplicate=The plugin '{0}' has already been registered in plugin manager.
+pluginmanager.notavailable=The plugin '{0}' does not exist in plugin manager.
+pluginmanager.plugin=Plugin: '{0}'
+pluginmanager.pluginmanager.label=Plugin manager:
+pluginmanager.pluginmanager.system=System plugin: '{0}'
+pluginmanager.pluginmanager.custom=custom plugin: '{0}'
+pluginmanager.pluginmanager.unfulfilleddependencies=Plugin with unfulfilled dependencies: '{0}'
+pluginmanager.plugin.initialization=The plugin '{0}' has been initialized.
+pluginmanager.plugin.processing.start=The plugin '{0}' is running.
+pluginmanager.plugin.processing.end=The running of the plugin '{0}' has been stopped.
+pluginmanager.fulfilleddependencies=The plugin '{0}' fulfills all dependencies.
+pluginmanager.unfulfilleddependencies=The plugin '{0}' does not fulfill a dependency on the plugin '{1}'.
+
+applicationmanager.initialization=The application manager has been initialized.
+applicationmanager.registerapplication=The application '{0}' has been created and registered in the application manager.
+applicationmanager.duplicateapplication=The application '{0}' has already been registered in the application manager.
+applicationmanager.application=Application: '{0}'
+applicationmanager.application.initialization=The application'{0}' has been initialized.
+applicationmanager.application.processing.start=The application '{0}' is running.
+applicationmanager.application.processing.end=The running of the application '{0}' has been stopped.
+applicationmanager.application.boot.notfound=The plugin '{0}' is unknown.
+
+modulemanager.initialization=The module manager has been initialized.
+modulemanager.register=The module '{0}' has been assigned to the application '{1}' and registered in the module manager.
+modulemanager.duplicate=The module '{0}' has already been registered in the application '{1}'.
+modulemanager.applicationless=The module '{0}' does not have any information about the application.
+modulemanager.module=Module: '{0}' for application(s) '{1}'
+pluginmanager.module.initialization=The module '{1}' of the application '{0}' has been initialized.
+pluginmanager.module.processing.start=The module '{1}' of the application '{0}' is running.
+pluginmanager.module.processing.end=The running of the module '{1}' of the application '{0}' has been stopped.
+
+resourcemanager.initialization=The resource manager has been initialized.
+resourcemanager.register={0} resource(s) have been assigned to the module '{1}'.
+resourcemanager.modulenotfound=The module '{1}' could not be found, which was specified in the resource '{0}'.
+resourcemanager.moduleless=The resource '{0}' does not have any information about the module.
+resourcemanager.addresource=The resource '{0}' has been registered in the module '{1}'.
+resourcemanager.addresource.duplicate=The resource '{0}' of module '{1}' has already been added.
+resourcemanager.addresource.error=The resource '{0}' of the module '{1}' could not be added.
+resourcemanager.sitemap=Sitemap content resource '{0}' application:
+resourcemanager.wrongtype=The type '{0}' does not implement the interface '{1}'.
+resourcemanager.statuspage=Resource: '{0}' for module '{1}'
+
+responsemanager.initialization=The response manager has been initialized.
+responsemanager.register=Status {0} has been registered in the module '{1}' and assigned to the status page '{2}'.
+responsemanager.duplicat=The status {0} has already been registered in the module '{1}'. Therefore, the status page '{2}' is not used.
+responsemanager.statuscode=A status code has not been assigned to the resource '{1}' for the module '{0}'.
+responsemanager.resource=Status code: '{0}'
+
+sitemapmanager.initialization=The sitemap manager has been initialized.
+sitemapmanager.refresh=The sitemap will be rebuilt.
+sitemapmanager.alreadyassigned=The node of the sitemap '{0}' is already assigned. The resource '{1}' is not included in the sitemap.
+sitemapmanager.addresource=The resource '{0}' has been registered in the sitemap.
+sitemapmanager.addresource.error=Could not add resource '{0}' in the sitemap.
+sitemapmanager.preorder={0} => {1}
+sitemapmanager.sitemap=Sitemap:
+sitemapmanager.merge.error=The two sitemaps '{0}' and '{1}' could not be merged.
+
+sessionmanager.initialization=The session manager has been initialized.
+
+eventmanager.initialization=The event manager has been initialized.
+
+jobmanager.initialization=The schedule manager has been initialized.
+jobmanager.register=The plugin '{0}' is registered in the schedule manager manager.
+jobmanager.job.register=The job '{1}' have been assigned to the module '{0}'.
+jobmanager.moduleless=The job '{0}' does not have any information about the module.
+jobmanager.wrongmodule=The '{1}' job is not part of the module {0}.
+jobmanager.job=Job: '{0}' for module '{1}'
+jobmanager.job.process=The job '{0}' is executed.
+jobmanager.cron.parseerror=Syntax error in the timing of a job. The value '{0}' cannot be processed.
+jobmanager.cron.range=Syntax error in the timing of a job. The value '{0}' is outside the valid range.
+
+resource.variable.duplicate=Variable '{0}' already exists!
+resource.file={0}: File '{1}' has been loaded.
\ No newline at end of file
diff --git a/src/WebExpress/Log.cs b/src/WebExpress/Log.cs
new file mode 100644
index 0000000..87cb420
--- /dev/null
+++ b/src/WebExpress/Log.cs
@@ -0,0 +1,582 @@
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+using WebExpress.Setting;
+
+namespace WebExpress
+{
+ ///
+ /// Class for logging events to your log file
+ ///
+ /// The program writes a variety of information to an event log file. The log
+ /// is stored in the log directory. The name consists of the date and the ending ".log".
+ /// The structure is designed in such a way that the log file can be read and analyzed with a text editor.
+ /// Error messages and notes are made available persistently in the log, so the event log files
+ /// are suitable for error analysis and for checking the correct functioning of the program. The minutes
+ /// are organized in tabular form. In the first column, the primeval time is indicated. The second
+ /// column defines the level of the log entry. The third column lists the function that produced the entry.
+ /// The last column indicates a note or error description.
+ ///
+ ///
+ /// Example:
+ /// 08:26:30 Info Program.Main Startup
+ /// 08:26:30 Info Program.Main --------------------------------------------------
+ /// 08:26:30 Info Program.Main Version: 0.0.0.1
+ /// 08:26:30 Info Program.Main Arguments: -test
+ /// 08:26:30 Info Program.Main Configuration version: V1
+ /// 08:26:30 Info Program.Main Processing: sequentiell
+ ///
+ public class Log : ILogger
+ {
+ ///
+ /// Enumeration defines the different log levels.
+ ///
+ public enum Level { Info, Warning, FatalError, Error, Exception, Debug, Seperartor };
+
+ ///
+ /// Enumerations of the log mode.
+ ///
+ public enum Mode { Off, Append, Override };
+
+ ///
+ /// Returns or sets the encoding.
+ ///
+ public Encoding Encoding { get; set; }
+
+ ///
+ /// Determines whether to display debug output.
+ ///
+ public bool DebugMode { get; private set; } = false;
+
+ ///
+ /// Returns the file name of the log
+ ///
+ public string Filename { get; set; }
+
+ ///
+ /// Returns the number of exceptions.
+ ///
+ public int ExceptionCount { get; protected set; }
+
+ ///
+ /// Returns the number of errors (errors + exceptions).
+ ///
+ public int ErrorCount { get; protected set; }
+
+ ///
+ /// Returns the number of warnings.
+ ///
+ public int WarningCount { get; protected set; }
+
+ ///
+ /// Checks if the log has been opened for writing.
+ ///
+ public bool IsOpen => _workerThread != null;
+
+ ///
+ /// Returns the log mode.
+ ///
+ public Mode LogMode { get; set; }
+
+ ///
+ /// The default instance of the logger.
+ ///
+ public static Log Current { get; } = new Log();
+
+ ///
+ /// The directory where the log is created.
+ ///
+ private string _path;
+
+ ///
+ /// The thread that takes care of the cyclic writing in the log file.
+ ///
+ private Thread _workerThread;
+
+ ///
+ /// Constant that determines the further of the separator rows.
+ ///
+ private const int _seperatorWidth = 260;
+
+ ///
+ /// End worker thread lifecycle.
+ ///
+ private bool _done = false;
+
+ ///
+ /// Unsaved entries queue.
+ ///
+ private readonly Queue _queue = new Queue();
+
+ ///
+ /// Returns the number of characters for log outputs in the console.
+ ///
+ private int Width
+ {
+ get
+ {
+ try
+ {
+ return Console.WindowWidth;
+ }
+ catch
+ {
+ }
+
+ return 250;
+ }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public Log()
+ {
+ Encoding = Encoding.UTF8;
+ FilePattern = "yyyyMMdd";
+ TimePattern = "yyyMMddHHmmss";
+ LogMode = Log.Mode.Append;
+ }
+
+ ///
+ /// Starts logging
+ ///
+ /// The path where the log file is created.
+ /// The file name of the log file.
+ public void Begin(string path, string name)
+ {
+ Filename = Path.Combine(path, name);
+ _path = path;
+
+ // check directory
+ if (!Directory.Exists(_path))
+ {
+ // no log directory exists yet -create >
+ Directory.CreateDirectory(_path);
+ }
+
+ // Delete existing log file when overwrite mode is active
+ if (LogMode == Mode.Override)
+ {
+ try
+ {
+ File.Delete(Filename);
+ }
+ catch
+ {
+ }
+ }
+
+ // create thread
+ _workerThread = new Thread(new ThreadStart(ThreadProc))
+ {
+
+ // Background thread
+ IsBackground = true
+ };
+
+ _workerThread.Start();
+ }
+
+ ///
+ /// Starts logging
+ ///
+ /// The path where the log file is created.
+ public void Begin(string path)
+ {
+ Begin(path, DateTime.Today.ToString(FilePattern) + ".log");
+ }
+
+ ///
+ /// Starts logging
+ ///
+ /// The log settings
+ public void Begin(SettingLogItem settings)
+ {
+ Filename = settings.Filename;
+ LogMode = (Mode)Enum.Parse(typeof(Mode), settings.Modus);
+ Encoding = Encoding.GetEncoding(settings.Encoding);
+ TimePattern = settings.Timepattern;
+ DebugMode = settings.Debug;
+
+ Begin(settings.Path, Filename);
+ }
+
+ ///
+ /// Adds a message to the log.
+ ///
+ /// The Level.
+ /// The log message.
+ /// Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ protected virtual void Add(Level level, string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ foreach (var l in message?.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
+ {
+ lock (_queue)
+ {
+ var item = new LogItem(level, instance, l, TimePattern);
+ switch (level)
+ {
+ case Level.Error:
+ case Level.FatalError:
+ case Level.Exception:
+ Console.ForegroundColor = ConsoleColor.Red;
+ break;
+ case Level.Warning:
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ break;
+ default:
+ break;
+ }
+
+ Console.WriteLine(item.ToString().Length > _seperatorWidth ? item.ToString().Substring(0, _seperatorWidth - 3) + "..." : item.ToString().PadRight(Width, ' '));
+ Console.ResetColor();
+
+ _queue.Enqueue(item);
+ }
+ }
+ }
+
+ ///
+ /// A dividing line with * characters
+ ///
+ public void Seperator()
+ {
+ Seperator('*');
+ }
+
+ ///
+ /// A separator with custom characters
+ ///
+ /// The separator.
+ public void Seperator(char sepChar)
+ {
+ Add(Level.Seperartor, "".PadRight(_seperatorWidth, sepChar));
+ }
+
+ ///
+ /// Logs an info message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void Info(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Info, message, $"{className}.{instance}", line, file);
+ }
+
+ ///
+ /// Logs an info message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ /// Parameter für die Formatierung der Nachricht
+ public void Info(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null, params object[] args)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Info, string.Format(message, args), $"{className}.{instance}", line, file);
+ }
+
+ ///
+ /// Logs a warning message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void Warning(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Warning, message, $"{className}.{instance}", line, file);
+
+ WarningCount++;
+ }
+
+ ///
+ /// Logs a warning message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ /// Parameter für die Formatierung der Nachricht
+ public void Warning(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null, params object[] args)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Warning, string.Format(message, args), $"{className}.{instance}", line, file);
+
+ WarningCount++;
+ }
+
+ ///
+ /// Logs an error message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void Error(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Error, message, $"{className}.{instance}", line, file);
+
+ ErrorCount++;
+ }
+
+ ///
+ /// Logs an error message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ /// Parameter für die Formatierung der Nachricht
+ public void Error(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null, params object[] args)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.Error, string.Format(message, args), $"{className}.{instance}", line, file);
+
+ ErrorCount++;
+ }
+
+ ///
+ /// Logs an error message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void FatalError(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.FatalError, message, $"{className}.{instance}", line, file);
+
+ ErrorCount++;
+ }
+
+ ///
+ /// Logs an error message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ /// Parameter für die Formatierung der Nachricht
+ public void FatalError(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null, params object[] args)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ Add(Level.FatalError, string.Format(message, args), $"{className}.{instance}", line, file);
+
+ ErrorCount++;
+ }
+
+ ///
+ /// Logs an exception message.
+ ///
+ /// The exception
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void Exception(Exception ex, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ lock (_queue)
+ {
+ Add(Level.Exception, ex?.Message.Trim(), $"{className}.{instance}", line, file);
+ Add(Level.Exception, ex?.StackTrace != null ? ex?.StackTrace.Trim() : ex?.Message.Trim(), $"{className}.{instance}", line, file);
+
+ ExceptionCount++;
+ ErrorCount++;
+ }
+ }
+
+ ///
+ /// Logs a debug message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ public void Debug(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ if (DebugMode)
+ {
+ Add(Level.Debug, message, $"{className}.{instance}", line, file);
+ }
+ }
+
+ ///
+ /// Logs a debug message.
+ ///
+ /// The log message.
+ /// >Method/ function that wants to log.
+ /// The line number.
+ /// The source file.
+ /// Parameter für die Formatierung der Nachricht
+ public void Debug(string message, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null, params object[] args)
+ {
+ var methodInfo = new StackTrace().GetFrame(1).GetMethod();
+ var className = methodInfo.ReflectedType.Name;
+
+ if (DebugMode)
+ {
+ Add(Level.Debug, string.Format(message, args), $"{className}.{instance}", line, file);
+ }
+ }
+
+ ///
+ /// Stops logging.
+ ///
+ public void Close()
+ {
+ _done = true;
+
+ // protect file writing from concurrent access
+ lock (_path)
+ {
+ Flush();
+ }
+ }
+
+ ///
+ /// Cleans up the log.
+ ///
+ public void Clear()
+ {
+ ErrorCount = 0;
+ WarningCount = 0;
+ ExceptionCount = 0;
+ }
+
+ ///
+ /// Writes the contents of the queue to the log.
+ ///
+ public void Flush()
+ {
+ var list = new List();
+
+ // lock queue before concurrent access
+ lock (_queue)
+ {
+ list.AddRange(_queue);
+ _queue.Clear();
+ }
+
+ // protect file writing from concurrent access
+ if (list.Count > 0 && LogMode != Mode.Off)
+ {
+ lock (_path)
+ {
+ using var fs = new FileStream(Filename, FileMode.Append);
+ using var w = new StreamWriter(fs, Encoding);
+ foreach (var item in list)
+ {
+ var str = item.ToString();
+ w.WriteLine(str);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Thread Start Function
+ ///
+ private void ThreadProc()
+ {
+ while (!_done)
+ {
+ Thread.Sleep(5000);
+
+ // protect file writing from concurrent access
+ lock (_path)
+ {
+ Flush();
+ }
+ }
+
+ _workerThread = null;
+ }
+
+ ///
+ /// Writes a log entry.
+ ///
+ /// The type of object to write.
+ /// The entry is written at this level.
+ /// Id of the event.
+ /// The entry to write. Can also be an object.
+ /// The exception that applies to this entry.
+ /// Function to create a string message of the state and exception parameters.
+ void ILogger.Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
+ {
+ if (logLevel == LogLevel.Error)
+ {
+ var message = exception?.Message ?? formatter.Invoke(state, exception);
+ Error(message, "Kestrel", null, null);
+ }
+
+ }
+
+ ///
+ /// Verifies that the specified logLevel parameter is enabled.
+ ///
+ /// Level to be checked.
+ /// True in the enabled state, false otherwise.
+ public bool IsEnabled(LogLevel logLevel)
+ {
+ return true;
+ }
+
+ ///
+ /// Formats the message and creates a range.
+ ///
+ /// The type of object to write.
+ /// The ILogger interface in which to create the scope.
+ /// A disposable range object. Can be NULL.
+ public IDisposable BeginScope(TState state)
+ {
+ return null;
+ }
+
+ ///
+ /// Set file name time patterns.
+ ///
+ public string FilePattern { set; get; }
+
+ ///
+ /// Time patternsspecifying log entries.
+ ///
+ public string TimePattern { set; get; }
+ }
+}
diff --git a/src/WebExpress/LogFactory.cs b/src/WebExpress/LogFactory.cs
new file mode 100644
index 0000000..84711e2
--- /dev/null
+++ b/src/WebExpress/LogFactory.cs
@@ -0,0 +1,36 @@
+using Microsoft.Extensions.Logging;
+
+namespace WebExpress
+{
+ public class LogFactory : ILoggerFactory, ILoggerProvider
+ {
+ ///
+ /// Adds an ILoggerProvider to the logging system.
+ ///
+ /// The ILoggerProvider.
+ public void AddProvider(ILoggerProvider provider)
+ {
+
+ }
+
+ ///
+ /// Creates a new ILogger instance.
+ ///
+ /// The category name for messages generated by logging.
+ /// A new ILogger instance.
+ public ILogger CreateLogger(string categoryName)
+ {
+ // use an existing logging instance
+ return Log.Current;
+ }
+
+ ///
+ /// Performs application-specific tasks related to sharing, returning, or
+ /// resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/LogFrame.cs b/src/WebExpress/LogFrame.cs
new file mode 100644
index 0000000..c50fbd6
--- /dev/null
+++ b/src/WebExpress/LogFrame.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace WebExpress
+{
+ ///
+ /// Creates a frame of log entries.
+ ///
+ public class LogFrame : IDisposable
+ {
+ ///
+ /// The status.
+ ///
+ public string Status { get; set; }
+
+ ///
+ /// Method that wants to log.
+ ///
+ protected string Instance { get; set; }
+
+ ///
+ /// The line number.
+ ///
+ protected int Line { get; set; }
+
+ ///
+ /// The source file.
+ ///
+ protected string File { get; set; }
+
+ ///
+ /// The log entry.
+ ///
+ protected Log Log { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The log entry.
+ /// The name.
+ /// An additional heading or zero.
+ /// Method that wants to log.
+ /// The line number.
+ /// The source file.
+ public LogFrame(Log log, string name, string additionalHeading = null, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ Instance = instance;
+ Status = string.Format("{0} abgeschlossen. ", name);
+
+ Log = log;
+ Log.Seperator();
+ Log.Info(string.Format("Beginne mit {0}", name) + (!string.IsNullOrWhiteSpace(additionalHeading) ? " " + additionalHeading : ""), instance, line, file);
+ Log.Info("".PadRight(80, '-'), instance, line, file);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The name.
+ /// The additional heading or zero.
+ /// Method that wants to log.
+ /// The line number.
+ /// The source file.
+ public LogFrame(string name, string additionalHeading = null, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ : this(Log.Current, name, additionalHeading, instance, line, file)
+ {
+ }
+
+ ///
+ /// Release unmanaged resources that were reserved during initialization.
+ ///
+ /// The input data.
+ /// The output data.
+ public virtual void Dispose()
+ {
+ Log.Info("".PadRight(80, '='), Instance, Line, File);
+ Log.Info(Status, Instance, Line, File);
+ }
+ }
+}
diff --git a/src/WebExpress/LogFrameSimple.cs b/src/WebExpress/LogFrameSimple.cs
new file mode 100644
index 0000000..7cb8a19
--- /dev/null
+++ b/src/WebExpress/LogFrameSimple.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace WebExpress
+{
+ ///
+ /// Creates a frame of log entries.
+ ///
+ public class LogFrameSimple : IDisposable
+ {
+ ///
+ /// Method that wants to log.
+ ///
+ protected string Instance { get; set; }
+
+ ///
+ /// The line number.
+ ///
+ protected int Line { get; set; }
+
+ ///
+ /// The source file.
+ ///
+ protected string File { get; set; }
+
+ ///
+ /// The log entry.
+ ///
+ protected Log Log { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The log entry.
+ /// Method that wants to log.
+ /// The line number.
+ /// The source file.
+ public LogFrameSimple(Log log, [CallerMemberName] string instance = null, [CallerLineNumber] int? line = null, [CallerFilePath] string file = null)
+ {
+ Instance = instance;
+ Log = log;
+ Line = line ?? 0;
+ File = file;
+
+ Log.Info("".PadRight(80, '>'), instance, line, file);
+ }
+
+ ///
+ /// Release unmanaged resources that were reserved during initialization.
+ ///
+ /// The input data.
+ /// The output data.
+ public virtual void Dispose()
+ {
+ Log.Info("".PadRight(80, '<'), Instance, Line, File);
+ }
+ }
+}
diff --git a/src/WebExpress/LogItem.cs b/src/WebExpress/LogItem.cs
new file mode 100644
index 0000000..44e681a
--- /dev/null
+++ b/src/WebExpress/LogItem.cs
@@ -0,0 +1,88 @@
+using System;
+using static WebExpress.Log;
+
+namespace WebExpress
+{
+ ///
+ /// Log entry
+ ///
+ internal class LogItem
+ {
+ ///
+ /// Level of the entry.
+ ///
+ private readonly Level m_level;
+
+ ///
+ /// The instance (location).
+ ///
+ private readonly string m_instance;
+
+ ///
+ /// The log message.
+ ///
+ private readonly string m_message;
+
+ ///
+ /// The timestamp.
+ ///
+ private readonly DateTime m_timestamp;
+
+ ///
+ /// Constructor
+ ///
+ /// The level.
+ /// The modul/funktion.
+ /// The log message.
+ public LogItem(Level level, string instance, string message, string timePattern)
+ {
+ m_level = level;
+ m_instance = instance;
+ m_message = message;
+ m_timestamp = DateTime.Now;
+ TimePattern = timePattern;
+ }
+
+ ///
+ /// Converts the value of this instance to a string.
+ ///
+ /// The log entry as a string
+ public override string ToString()
+ {
+ if (m_level != Level.Seperartor)
+ {
+ return m_timestamp.ToString(TimePattern) + " " + m_level.ToString().PadRight(9, ' ') + " " + m_instance.PadRight(19, ' ').Substring(0, 19) + " " + m_message;
+ }
+ else
+ {
+ return m_message;
+ }
+ }
+
+ ///
+ /// Returns the level of the entry.
+ ///
+ public Level Level => m_level;
+
+ ///
+ /// Returns the instance (location).
+ ///
+ public string Instance => m_instance;
+
+ ///
+ /// Returns the message.
+ ///
+ public string Message => m_message;
+
+ ///
+ /// Returns the timestamp.
+ ///
+ public DateTime Timestamp => m_timestamp;
+
+
+ ///
+ /// Returns the or set the time patterns for log entries.
+ ///
+ public string TimePattern { set; get; }
+ };
+}
diff --git a/src/WebExpress/Properties/launchSettings.json b/src/WebExpress/Properties/launchSettings.json
new file mode 100644
index 0000000..9106c1c
--- /dev/null
+++ b/src/WebExpress/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "WebExpress": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:51508;http://localhost:51509"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/Rocket.ico b/src/WebExpress/Rocket.ico
new file mode 100644
index 0000000..c0909c9
Binary files /dev/null and b/src/WebExpress/Rocket.ico differ
diff --git a/src/WebExpress/Setting/ISettingItem.cs b/src/WebExpress/Setting/ISettingItem.cs
new file mode 100644
index 0000000..4ef1571
--- /dev/null
+++ b/src/WebExpress/Setting/ISettingItem.cs
@@ -0,0 +1,6 @@
+namespace WebExpress.Setting
+{
+ public interface ISettingItem
+ {
+ }
+}
diff --git a/src/WebExpress/Setting/SettingLogItem.cs b/src/WebExpress/Setting/SettingLogItem.cs
new file mode 100644
index 0000000..993bcb0
--- /dev/null
+++ b/src/WebExpress/Setting/SettingLogItem.cs
@@ -0,0 +1,54 @@
+using System.Xml.Serialization;
+
+namespace WebExpress.Setting
+{
+ ///
+ /// Class for managing log settings.
+ ///
+ [XmlType("log")]
+ public class SettingLogItem : ISettingItem
+ {
+ ///
+ /// The log mode.
+ ///
+ [XmlAttribute(AttributeName = "modus")]
+ public string Modus { get; set; }
+
+ ///
+ /// Determines whether to display debug output.
+ ///
+ [XmlAttribute(AttributeName = "debug")]
+ public bool Debug { get; set; } = false;
+
+ ///
+ /// The directory where the log is created.
+ ///
+ [XmlAttribute(AttributeName = "path")]
+ public string Path { get; set; }
+
+ ///
+ /// The encoding settings.
+ ///
+ [XmlAttribute(AttributeName = "encoding")]
+ public string Encoding { get; set; }
+
+ ///
+ /// The file name of the log.
+ ///
+ [XmlAttribute(AttributeName = "filename")]
+ public string Filename { get; set; }
+
+ ///
+ /// The format of the timestamp.
+ ///
+ [XmlAttribute(AttributeName = "timepattern")]
+ public string Timepattern { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public SettingLogItem()
+ {
+ }
+ }
+}
diff --git a/src/WebExpress/WebApplication/ApplicationContext.cs b/src/WebExpress/WebApplication/ApplicationContext.cs
new file mode 100644
index 0000000..c48fac4
--- /dev/null
+++ b/src/WebExpress/WebApplication/ApplicationContext.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebApplication
+{
+ public class ApplicationContext : IApplicationContext
+ {
+ ///
+ /// Returns the context of the associated plugin.
+ ///
+ public IPluginContext PluginContext { get; internal set; }
+
+ ///
+ /// Returns the application id.
+ ///
+ public string ApplicationId { get; internal set; }
+
+ ///
+ /// Returns the application name.
+ ///
+ public string ApplicationName { get; internal set; }
+
+ ///
+ /// Returns or sets the description.
+ ///
+ public string Description { get; internal set; }
+
+ ///
+ /// Returns an enumeration of options. Options enable optional resources.
+ ///
+ public IEnumerable Options { get; internal set; }
+
+ ///
+ /// Returns the asset directory. This is mounted in the asset directory of the server.
+ ///
+ public string AssetPath { get; internal set; }
+
+ ///
+ /// Returns the data directory. This is mounted in the data directory of the server.
+ ///
+ public string DataPath { get; internal set; }
+
+ ///
+ /// Returns the context path. This is mounted in the context path of the server.
+ ///
+ public UriResource ContextPath { get; internal set; }
+
+ ///
+ /// Returns the icon uri.
+ ///
+ public UriResource Icon { get; internal set; }
+
+ ///
+ /// Constructor
+ ///
+ public ApplicationContext()
+ {
+ }
+
+ ///
+ /// Conversion of the apllication context into its string representation.
+ ///
+ /// The string that uniquely represents the application.
+ public override string ToString()
+ {
+ return $"Application {ApplicationId}";
+ }
+ }
+}
diff --git a/src/WebExpress/WebApplication/ApplicationDictionary.cs b/src/WebExpress/WebApplication/ApplicationDictionary.cs
new file mode 100644
index 0000000..4f72375
--- /dev/null
+++ b/src/WebExpress/WebApplication/ApplicationDictionary.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebApplication
+{
+ ///
+ /// Key = Plugin context
+ /// Value = { Key = application id, Value = application item }
+ ///
+ internal class ApplicationDictionary : Dictionary>
+ {
+ }
+}
diff --git a/src/WebExpress/WebApplication/ApplicationItem.cs b/src/WebExpress/WebApplication/ApplicationItem.cs
new file mode 100644
index 0000000..e3a77c6
--- /dev/null
+++ b/src/WebExpress/WebApplication/ApplicationItem.cs
@@ -0,0 +1,25 @@
+using System.Threading;
+
+namespace WebExpress.WebApplication
+{
+ ///
+ /// Represents an application entry in the application directory.
+ ///
+ internal class ApplicationItem
+ {
+ ///
+ /// The context associated with the application.
+ ///
+ public IApplicationContext ApplicationContext { get; set; }
+
+ ///
+ /// The application.
+ ///
+ public IApplication Application { get; set; }
+
+ ///
+ /// Thread termination token.
+ ///
+ public CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource();
+ }
+}
diff --git a/src/WebExpress/WebApplication/ApplicationManager.cs b/src/WebExpress/WebApplication/ApplicationManager.cs
new file mode 100644
index 0000000..d0f7fa6
--- /dev/null
+++ b/src/WebExpress/WebApplication/ApplicationManager.cs
@@ -0,0 +1,414 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using WebExpress.Internationalization;
+using WebExpress.WebAttribute;
+using WebExpress.WebComponent;
+using WebExpress.WebPlugin;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebApplication
+{
+ ///
+ /// Management of WebExpress applications.
+ ///
+ public sealed class ApplicationManager : IComponentPlugin, IExecutableElements, ISystemComponent
+ {
+ ///
+ /// An event that fires when an application is added.
+ ///
+ public event EventHandler AddApplication;
+
+ ///
+ /// An event that fires when an application is removed.
+ ///
+ public event EventHandler RemoveApplication;
+
+ ///
+ /// Returns or sets the reference to the context of the host.
+ ///
+ public IHttpServerContext HttpServerContext { get; private set; }
+
+ ///
+ /// Returns or sets the directory where the applications are listed.
+ ///
+ private ApplicationDictionary Dictionary { get; } = new ApplicationDictionary();
+
+ ///
+ /// Returns the stored applications.
+ ///
+ public IEnumerable Applications => Dictionary.Values.SelectMany(x => x.Values).Select(x => x.ApplicationContext);
+
+ ///
+ /// Constructor
+ ///
+ internal ApplicationManager()
+ {
+ ComponentManager.PluginManager.AddPlugin += (sender, pluginContext) =>
+ {
+ Register(pluginContext);
+ };
+
+ ComponentManager.PluginManager.RemovePlugin += (sender, pluginContext) =>
+ {
+ Remove(pluginContext);
+ };
+ }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ public void Initialization(IHttpServerContext context)
+ {
+ HttpServerContext = context;
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:applicationmanager.initialization")
+ );
+ }
+
+ ///
+ /// Discovers and registers applications from the specified plugin.
+ ///
+ /// A context of a plugin whose applications are to be registered.
+ public void Register(IPluginContext pluginContext)
+ {
+ // the plugin has already been registered
+ if (Dictionary.ContainsKey(pluginContext))
+ {
+ return;
+ }
+
+ Dictionary.Add(pluginContext, new Dictionary());
+
+ var assembly = pluginContext.Assembly;
+ var pluginDict = Dictionary[pluginContext];
+
+ foreach (var type in assembly.GetExportedTypes().Where
+ (
+ x => x.IsClass &&
+ x.IsSealed &&
+ x.IsPublic &&
+ x.GetInterface(typeof(IApplication).Name) != null
+ ))
+ {
+ var id = type.FullName?.ToLower();
+ var name = type.Name;
+ var icon = string.Empty;
+ var description = string.Empty;
+ var contextPath = string.Empty;
+ var assetPath = Path.DirectorySeparatorChar.ToString();
+ var dataPath = Path.DirectorySeparatorChar.ToString();
+ var options = new List();
+
+ // determining attributes
+ foreach (var customAttribute in type.CustomAttributes
+ .Where(x => x.AttributeType.GetInterfaces().Contains(typeof(IApplicationAttribute))))
+ {
+ if (customAttribute.AttributeType == typeof(NameAttribute))
+ {
+ name = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(IconAttribute))
+ {
+ icon = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(DescriptionAttribute))
+ {
+ description = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(ContextPathAttribute))
+ {
+ contextPath = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(AssetPathAttribute))
+ {
+ assetPath = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(DataPathAttribute))
+ {
+ dataPath = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ }
+ else if (customAttribute.AttributeType == typeof(OptionAttribute))
+ {
+ var value = customAttribute.ConstructorArguments.FirstOrDefault().Value.ToString().ToLower().Trim();
+ options.Add(value);
+ }
+ else if (customAttribute.AttributeType.Name == typeof(WebExOptionAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(WebExOptionAttribute<>).Namespace)
+ {
+ var value = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower();
+ options.Add(value);
+ }
+ else if (customAttribute.AttributeType.Name == typeof(WebExOptionAttribute<,>).Name && customAttribute.AttributeType.Namespace == typeof(WebExOptionAttribute<,>).Namespace)
+ {
+ var firstValue = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower();
+ var secoundValue = customAttribute.AttributeType.GenericTypeArguments.LastOrDefault()?.FullName?.ToLower();
+
+ options.Add($"{firstValue}.{secoundValue}");
+ }
+ }
+
+ // creating application context
+ var applicationContext = new ApplicationContext
+ {
+ PluginContext = pluginContext,
+ ApplicationId = id,
+ ApplicationName = name,
+ Description = description,
+ Options = options,
+ AssetPath = Path.Combine(HttpServerContext.AssetPath, assetPath),
+ DataPath = Path.Combine(HttpServerContext.DataPath, dataPath),
+ Icon = UriResource.Combine(HttpServerContext.ContextPath, contextPath, icon),
+ ContextPath = UriResource.Combine(HttpServerContext.ContextPath, contextPath)
+ };
+
+ // create application
+ var applicationInstance = Activator.CreateInstance(type) as IApplication;
+
+ if (!pluginDict.ContainsKey(id))
+ {
+ pluginDict.Add(id, new ApplicationItem()
+ {
+ ApplicationContext = applicationContext,
+ Application = applicationInstance
+ });
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:applicationmanager.register", id)
+ );
+
+ // raises the AddApplication event
+ OnAddApplication(applicationContext);
+ }
+ else
+ {
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N("webexpress:applicationmanager.duplicate", id)
+ );
+ }
+ }
+ }
+
+ ///
+ /// Discovers and registers applications from the specified plugin.
+ ///
+ /// A list with plugin contexts that contain the applications.
+ public void Register(IEnumerable pluginContexts)
+ {
+ foreach (var pluginContext in pluginContexts)
+ {
+ Register(pluginContext);
+ }
+ }
+
+ ///
+ /// Determines the application contexts for a given application id.
+ ///
+ /// The application id.
+ /// The context of the application or null.
+ public IApplicationContext GetApplcation(string applicationId)
+ {
+ if (string.IsNullOrWhiteSpace(applicationId)) return null;
+
+ var items = Dictionary.Values
+ .Where(x => x.ContainsKey(applicationId.ToLower()))
+ .Select(x => x[applicationId.ToLower()])
+ .FirstOrDefault();
+
+ if (items != null)
+ {
+ return items.ApplicationContext;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Determines the application contexts for the given application ids.
+ ///
+ /// The applications ids. Can contain regular expressions or * for all.
+ /// The contexts of the applications as an enumeration.
+ public IEnumerable GetApplcations(IEnumerable applicationIds)
+ {
+ var list = new List();
+
+ foreach (var applicationId in applicationIds)
+ {
+ if (applicationId == "*")
+ {
+ list.AddRange(Applications);
+ }
+ else
+ {
+ list.AddRange
+ (
+ Applications.Where
+ (
+ x =>
+ x.ApplicationId.Equals(applicationId, StringComparison.OrdinalIgnoreCase) ||
+ Regex.Match(x.ApplicationId, applicationId).Success
+ )
+ );
+ }
+ }
+
+ return list.Distinct();
+ }
+
+ ///
+ /// Determines the application contexts for the given plugin.
+ ///
+ /// The context of the plugin.
+ /// The contexts of the applications as an enumeration.
+ public IEnumerable GetApplcations(IPluginContext pluginContext)
+ {
+ if (!Dictionary.ContainsKey(pluginContext))
+ {
+ return new List();
+ }
+
+ return Dictionary[pluginContext].Values.Select(x => x.ApplicationContext);
+ }
+
+ ///
+ /// Boots the applications.
+ ///
+ /// The context of the plugin that contains the applications.
+ public void Boot(IPluginContext pluginContext)
+ {
+ if (pluginContext == null)
+ {
+ return;
+ }
+
+ if (!Dictionary.ContainsKey(pluginContext))
+ {
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:applicationmanager.application.boot.notfound",
+ pluginContext.PluginId
+ )
+ );
+
+ return;
+ }
+
+ foreach (var applicationItem in Dictionary[pluginContext]?.Values ?? Enumerable.Empty())
+ {
+ var token = applicationItem.CancellationTokenSource.Token;
+
+ // Initialize application
+ applicationItem.Application.Initialization(applicationItem.ApplicationContext);
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:applicationmanager.application.initialization",
+ applicationItem.ApplicationContext.ApplicationId
+ )
+ );
+
+ // Run the application concurrently
+ Task.Run(() =>
+ {
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:applicationmanager.application.processing.start",
+ applicationItem.ApplicationContext.ApplicationId)
+ );
+
+ applicationItem.Application.Run();
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:applicationmanager.application.processing.end",
+ applicationItem.ApplicationContext.ApplicationId
+ )
+ );
+
+ token.ThrowIfCancellationRequested();
+ }, token);
+ }
+ }
+
+ ///
+ /// Shutting down applications.
+ ///
+ /// The context of the plugin that contains the applications.
+ public void ShutDown(IPluginContext pluginContext)
+ {
+ foreach (var applicationItem in Dictionary[pluginContext]?.Values ?? Enumerable.Empty())
+ {
+ applicationItem.CancellationTokenSource.Cancel();
+ }
+ }
+
+ ///
+ /// Removes all applications associated with the specified plugin context.
+ ///
+ /// The context of the plugin that contains the applications to remove.
+ public void Remove(IPluginContext pluginContext)
+ {
+ if (!Dictionary.ContainsKey(pluginContext))
+ {
+ return;
+ }
+
+ foreach (var applicationContext in Dictionary[pluginContext])
+ {
+ OnRemoveApplication(applicationContext.Value.ApplicationContext);
+ }
+
+ Dictionary.Remove(pluginContext);
+ }
+
+ ///
+ /// Raises the AddApplication event.
+ ///
+ /// The application context.
+ private void OnAddApplication(IApplicationContext applicationContext)
+ {
+ AddApplication?.Invoke(this, applicationContext);
+ }
+
+ ///
+ /// Raises the RemoveApplication event.
+ ///
+ /// The application context.
+ private void OnRemoveApplication(IApplicationContext applicationContext)
+ {
+ RemoveApplication?.Invoke(this, applicationContext);
+ }
+
+ ///
+ /// Information about the component is collected and prepared for output in the log.
+ ///
+ /// The context of the plugin.
+ /// A list of log entries.
+ /// The shaft deep.
+ public void PrepareForLog(IPluginContext pluginContext, IList output, int deep)
+ {
+ foreach (var applicationContext in GetApplcations(pluginContext))
+ {
+ output.Add
+ (
+ string.Empty.PadRight(deep) +
+ InternationalizationManager.I18N("webexpress:applicationmanager.application", applicationContext.ApplicationId)
+ );
+ }
+ }
+ }
+}
diff --git a/src/WebExpress/WebApplication/IApplication.cs b/src/WebExpress/WebApplication/IApplication.cs
new file mode 100644
index 0000000..ebb59e0
--- /dev/null
+++ b/src/WebExpress/WebApplication/IApplication.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace WebExpress.WebApplication
+{
+ ///
+ /// This interface represents an application.
+ ///
+ public interface IApplication : IDisposable
+ {
+ ///
+ /// Initialization of the application .
+ ///
+ /// The context.
+ void Initialization(IApplicationContext context);
+
+ ///
+ /// Called when the application starts working. The call is concurrent.
+ ///
+ void Run();
+ }
+}
diff --git a/src/WebExpress/WebApplication/IApplicationContext.cs b/src/WebExpress/WebApplication/IApplicationContext.cs
new file mode 100644
index 0000000..55710e9
--- /dev/null
+++ b/src/WebExpress/WebApplication/IApplicationContext.cs
@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebApplication
+{
+ ///
+ /// The application context.
+ ///
+ public interface IApplicationContext
+ {
+ ///
+ /// Provides the context of the associated plugin.
+ ///
+ IPluginContext PluginContext { get; }
+
+ ///
+ /// Returns the application id.
+ ///
+ string ApplicationId { get; }
+
+ ///
+ /// Returns the application name.
+ ///
+ string ApplicationName { get; }
+
+ ///
+ /// Provides the description.
+ ///
+ string Description { get; }
+
+ ///
+ /// Returns an enumeration of options. Options enable optional resources.
+ ///
+ IEnumerable Options { get; }
+
+ ///
+ /// Returns the asset directory. This is mounted in the asset directory of the server.
+ ///
+ string AssetPath { get; }
+
+ ///
+ /// Returns the data directory. This is mounted in the data directory of the server.
+ ///
+ string DataPath { get; }
+
+ ///
+ /// Returns the context path. This is mounted in the context path of the server.
+ ///
+ UriResource ContextPath { get; }
+
+ ///
+ /// Returns the icon uri.
+ ///
+ UriResource Icon { get; }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ApplicationAttribute.cs b/src/WebExpress/WebAttribute/ApplicationAttribute.cs
new file mode 100644
index 0000000..814e0c0
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ApplicationAttribute.cs
@@ -0,0 +1,31 @@
+using System;
+using WebExpress.WebApplication;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Application assignment attribute of the application ID.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class ApplicationAttribute : Attribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// A specific ApplicationId, regular expression, or * for any application.
+ public ApplicationAttribute(string applicationId)
+ {
+
+ }
+ }
+
+ ///
+ /// An application expression attribute, which is determined by the type.
+ ///
+ /// The type of the application.
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class ApplicationAttribute : Attribute, IModuleAttribute where T : class, IApplication
+ {
+
+ }
+}
diff --git a/src/WebExpress/WebAttribute/AssetPathAttribute.cs b/src/WebExpress/WebAttribute/AssetPathAttribute.cs
new file mode 100644
index 0000000..f7942ed
--- /dev/null
+++ b/src/WebExpress/WebAttribute/AssetPathAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class AssetPathAttribute : System.Attribute, IApplicationAttribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The path for assets.
+ public AssetPathAttribute(string assetPath)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/CacheAttribute.cs b/src/WebExpress/WebAttribute/CacheAttribute.cs
new file mode 100644
index 0000000..c9771b0
--- /dev/null
+++ b/src/WebExpress/WebAttribute/CacheAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Indicates that a page or component can be reused
+ ///
+ [AttributeUsage(AttributeTargets.Class)]
+ public class CacheAttribute : System.Attribute, IResourceAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ public CacheAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ConditionAttribute.cs b/src/WebExpress/WebAttribute/ConditionAttribute.cs
new file mode 100644
index 0000000..a28e9a2
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ConditionAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+using WebExpress.WebCondition;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Activation of options (e.g. WebEx.WebApp.Setting.SystemInformation for displaying system information).
+ ///
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ConditionAttribute : Attribute, IResourceAttribute where T : class, ICondition
+ {
+ ///
+ /// Constructor
+ ///
+ public ConditionAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ContextPathAttribute.cs b/src/WebExpress/WebAttribute/ContextPathAttribute.cs
new file mode 100644
index 0000000..c37be5c
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ContextPathAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
+ public class ContextPathAttribute : Attribute, IApplicationAttribute, IModuleAttribute, IResourceAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The context path.
+ public ContextPathAttribute(string contetxPath)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/DataPathAttribute.cs b/src/WebExpress/WebAttribute/DataPathAttribute.cs
new file mode 100644
index 0000000..8fac4ab
--- /dev/null
+++ b/src/WebExpress/WebAttribute/DataPathAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class DataPathAttribute : System.Attribute, IApplicationAttribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The path for the data.
+ public DataPathAttribute(string dataPath)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/DefaultAttribute.cs b/src/WebExpress/WebAttribute/DefaultAttribute.cs
new file mode 100644
index 0000000..5023d08
--- /dev/null
+++ b/src/WebExpress/WebAttribute/DefaultAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Indicates that a status page ist default
+ ///
+ [AttributeUsage(AttributeTargets.Class)]
+ public class DefaultAttribute : Attribute, IStatusPageAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ public DefaultAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/DependencyAttribute.cs b/src/WebExpress/WebAttribute/DependencyAttribute.cs
new file mode 100644
index 0000000..3a91320
--- /dev/null
+++ b/src/WebExpress/WebAttribute/DependencyAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Marks a plugin as dependent on another plugin.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class DependencyAttribute : System.Attribute, IPluginAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The Id of the plugin to which there is a dependency.
+ public DependencyAttribute(string dependency)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/DescriptionAttribute.cs b/src/WebExpress/WebAttribute/DescriptionAttribute.cs
new file mode 100644
index 0000000..70694de
--- /dev/null
+++ b/src/WebExpress/WebAttribute/DescriptionAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class DescriptionAttribute : System.Attribute, IPluginAttribute, IApplicationAttribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The description.
+ public DescriptionAttribute(string description)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IApplicationAttribute.cs b/src/WebExpress/WebAttribute/IApplicationAttribute.cs
new file mode 100644
index 0000000..69dc939
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IApplicationAttribute.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Interface of a application assignment attribute.
+ ///
+ public interface IApplicationAttribute
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IModuleAttribute.cs b/src/WebExpress/WebAttribute/IModuleAttribute.cs
new file mode 100644
index 0000000..46d40e5
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IModuleAttribute.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Interface of a module assignment attribute.
+ ///
+ public interface IModuleAttribute
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IPluginAttribute.cs b/src/WebExpress/WebAttribute/IPluginAttribute.cs
new file mode 100644
index 0000000..773c8af
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IPluginAttribute.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Identifies a class as a plug-in component.
+ ///
+ public interface IPluginAttribute
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IResourceAttribute.cs b/src/WebExpress/WebAttribute/IResourceAttribute.cs
new file mode 100644
index 0000000..1c1ed0b
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IResourceAttribute.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Interface of a resource assignment attribute.
+ ///
+ public interface IResourceAttribute
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ISegmentAttribute.cs b/src/WebExpress/WebAttribute/ISegmentAttribute.cs
new file mode 100644
index 0000000..7ed925d
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ISegmentAttribute.cs
@@ -0,0 +1,13 @@
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ public interface ISegmentAttribute
+ {
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ IUriPathSegment ToPathSegment();
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IStatusPageAttribute.cs b/src/WebExpress/WebAttribute/IStatusPageAttribute.cs
new file mode 100644
index 0000000..c8e16f2
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IStatusPageAttribute.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Identifies a class as a status page attribute.
+ ///
+ public interface IStatusPageAttribute
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IconAttribute.cs b/src/WebExpress/WebAttribute/IconAttribute.cs
new file mode 100644
index 0000000..157c1aa
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IconAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class IconAttribute : System.Attribute, IPluginAttribute, IApplicationAttribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The icon.
+ public IconAttribute(string icon)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/IncludeSubPathsAttribute.cs b/src/WebExpress/WebAttribute/IncludeSubPathsAttribute.cs
new file mode 100644
index 0000000..f72ddfa
--- /dev/null
+++ b/src/WebExpress/WebAttribute/IncludeSubPathsAttribute.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Determines whether all resources below the specified path (including segment) are also processed.
+ ///
+ public class IncludeSubPathsAttribute : System.Attribute, IResourceAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// All subpaths are included.
+ public IncludeSubPathsAttribute(bool includeSubPaths)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/JobAttribute.cs b/src/WebExpress/WebAttribute/JobAttribute.cs
new file mode 100644
index 0000000..b5dbe52
--- /dev/null
+++ b/src/WebExpress/WebAttribute/JobAttribute.cs
@@ -0,0 +1,18 @@
+namespace WebExpress.WebAttribute
+{
+ public class JobAttribute : System.Attribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The minute 0-59 or * for any. Comma-separated values or ranges (-) are also possible.
+ /// The hour 0-23 or * for arbitrary. Comma-separated values or ranges (-) are also possible.
+ /// The day 1-31 or * for any. Comma-separated values or ranges (-) are also possible.
+ /// The month 1-12 or * for any. Comma-separated values or ranges (-) are also possible.
+ /// The weekday 0-6 (Sunday-Saturday) or * for any. Comma-separated values or ranges (-) are also possible.
+ public JobAttribute(string minute = "*", string hour = "*", string day = "*", string month = "*", string weekday = "*")
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ModuleAttribute.cs b/src/WebExpress/WebAttribute/ModuleAttribute.cs
new file mode 100644
index 0000000..7822288
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ModuleAttribute.cs
@@ -0,0 +1,21 @@
+using System;
+using WebExpress.WebModule;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Specifying a module.
+ ///
+ /// The type of the module.
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class ModuleAttribute : Attribute, IResourceAttribute, IModuleAttribute where T : class, IModule
+ {
+ ///
+ /// Constructor
+ ///
+ public ModuleAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/NameAttribute.cs b/src/WebExpress/WebAttribute/NameAttribute.cs
new file mode 100644
index 0000000..b3c858d
--- /dev/null
+++ b/src/WebExpress/WebAttribute/NameAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class NameAttribute : System.Attribute, IPluginAttribute, IApplicationAttribute, IModuleAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// Der Name
+ public NameAttribute(string name)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/OptionAttribute.cs b/src/WebExpress/WebAttribute/OptionAttribute.cs
new file mode 100644
index 0000000..276a706
--- /dev/null
+++ b/src/WebExpress/WebAttribute/OptionAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+using WebExpress.WebModule;
+using WebExpress.WebResource;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Activation of options (e.g. 'webexpress.webapp.settinglog' or 'webexpress.webapp.*').
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class OptionAttribute : Attribute, IApplicationAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The option to activate.
+ public OptionAttribute(string option)
+ {
+
+ }
+ }
+
+ ///
+ /// Activation of options (e.g. 'webexpress.webapp.settinglog' or 'webexpress.webapp.*').
+ ///
+ /// The module or resource class.
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class WebExOptionAttribute : Attribute, IApplicationAttribute where M : class, IModule
+ {
+
+ }
+
+ ///
+ /// Activation of options (e.g. 'webexpress.webapp.settinglog' or 'webexpress.webapp.*').
+ /// The module or resource class.
+ /// The resource or resource class.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class WebExOptionAttribute : Attribute, IApplicationAttribute where M : class, IModule where R : class, IResource
+ {
+ }
+}
diff --git a/src/WebExpress/WebAttribute/OptionalAttribute.cs b/src/WebExpress/WebAttribute/OptionalAttribute.cs
new file mode 100644
index 0000000..ad320f0
--- /dev/null
+++ b/src/WebExpress/WebAttribute/OptionalAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Marks a ressorce as optional. This becomes active when the option is specified in the application.
+ ///
+ [AttributeUsage(AttributeTargets.Class)]
+ public class OptionalAttribute : Attribute, IResourceAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ public OptionalAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ParentAttribute.cs b/src/WebExpress/WebAttribute/ParentAttribute.cs
new file mode 100644
index 0000000..9f0a332
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ParentAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+using WebExpress.WebResource;
+
+namespace WebExpress.WebAttribute
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class ParentAttribute : Attribute, IResourceAttribute where T : class, IResource
+ {
+ ///
+ /// Constructor
+ ///
+ public ParentAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/ScopeAttribute.cs b/src/WebExpress/WebAttribute/ScopeAttribute.cs
new file mode 100644
index 0000000..d80a049
--- /dev/null
+++ b/src/WebExpress/WebAttribute/ScopeAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+using WebExpress.WebScope;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// The range in which the component is valid.
+ ///
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
+ public class ScopeAttribute : Attribute, IResourceAttribute where T : class, IScope
+ {
+ ///
+ /// Constructor
+ ///
+ public ScopeAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentAttribute.cs b/src/WebExpress/WebAttribute/SegmentAttribute.cs
new file mode 100644
index 0000000..3a70053
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// A static path segment.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class SegmentAttribute : Attribute, IResourceAttribute, ISegmentAttribute
+ {
+ ///
+ /// Returns or set the segment of the uri path.
+ ///
+ private string Segment { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The segment of the uri path.
+ /// The display string.
+ public SegmentAttribute(string segment, string display = null)
+ {
+ Segment = segment;
+ Display = display;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ return new UriPathSegmentConstant(Segment, Display) { };
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentDoubleAttribute.cs b/src/WebExpress/WebAttribute/SegmentDoubleAttribute.cs
new file mode 100644
index 0000000..349cc6d
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentDoubleAttribute.cs
@@ -0,0 +1,50 @@
+using System;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ public class SegmentDoubleAttribute : Attribute, IResourceAttribute, ISegmentAttribute
+ {
+ ///
+ /// Returns or sets the name of the variable.
+ ///
+ private string VariableName { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The name of the variable.
+ /// The display string.
+ public SegmentDoubleAttribute(string variableName, string display)
+ {
+ VariableName = variableName;
+ Display = display;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ //var expression = @"^[+-]?(\d*,\d+|\d+(,\d*)?)( +[eE][+-]?\d+)?$";
+
+ //var callBackDisplay = new Func((segment, moduleId, culture) =>
+ //{
+ // return null;
+ //});
+
+ //var callBackValiables = new Func>(segment =>
+ //{
+ // return null;
+ //});
+
+ return new UriPathSegmentVariableDouble(VariableName, Display);
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentGuidAttribute.cs b/src/WebExpress/WebAttribute/SegmentGuidAttribute.cs
new file mode 100644
index 0000000..adc9faf
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentGuidAttribute.cs
@@ -0,0 +1,50 @@
+using System;
+using WebExpress.WebMessage;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// A dynamic path segment of type guid.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class SegmentGuidAttribute : Attribute, IResourceAttribute, ISegmentAttribute where T : Parameter
+ {
+ ///
+ /// Returns or sets the name of the variable.
+ ///
+ private string VariableName { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Returns or sets the display format.
+ ///
+ private UriPathSegmentVariableGuid.Format DisplayFormat { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The type of the variable.
+ /// The display string.
+ /// The display format.
+ public SegmentGuidAttribute(string display, UriPathSegmentVariableGuid.Format displayFormat = UriPathSegmentVariableGuid.Format.Simple)
+ {
+ VariableName = (Activator.CreateInstance(typeof(T)) as Parameter)?.Key?.ToLower();
+ Display = display;
+ DisplayFormat = displayFormat;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ return new UriPathSegmentVariableGuid(VariableName, Display, DisplayFormat);
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentIntAttribute.cs b/src/WebExpress/WebAttribute/SegmentIntAttribute.cs
new file mode 100644
index 0000000..52129d6
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentIntAttribute.cs
@@ -0,0 +1,38 @@
+using System;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ public class SegmentIntAttribute : Attribute, IResourceAttribute, ISegmentAttribute
+ {
+ ///
+ /// Returns or sets the name of the variable.
+ ///
+ private string VariableName { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The name of the variable.
+ /// The display string.
+ public SegmentIntAttribute(string variableName, string display)
+ {
+ VariableName = variableName;
+ Display = display;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ return new UriPathSegmentVariableInt(VariableName, Display);
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentStringAttribute.cs b/src/WebExpress/WebAttribute/SegmentStringAttribute.cs
new file mode 100644
index 0000000..0232e46
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentStringAttribute.cs
@@ -0,0 +1,50 @@
+using System;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ public class SegmentStringAttribute : Attribute, IResourceAttribute, ISegmentAttribute
+ {
+ ///
+ /// Returns or sets the name of the variable.
+ ///
+ private string VariableName { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The name of the variable.
+ /// The display string.
+ public SegmentStringAttribute(string variableName, string display)
+ {
+ VariableName = variableName;
+ Display = display;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ //var expression = "^[^\"]*$";
+
+ //var callBackDisplay = new Func((segment, moduleId, culture) =>
+ //{
+ // return null;
+ //});
+
+ //var callBackValiables = new Func>(segment =>
+ //{
+ // return null;
+ //});
+
+ return new UriPathSegmentVariableString(VariableName, Display);
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SegmentUIntAttribute.cs b/src/WebExpress/WebAttribute/SegmentUIntAttribute.cs
new file mode 100644
index 0000000..d6c6dfc
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SegmentUIntAttribute.cs
@@ -0,0 +1,55 @@
+using System;
+using WebExpress.WebUri;
+
+namespace WebExpress.WebAttribute
+{
+ public class SegmentUIntAttribute : Attribute, IResourceAttribute, ISegmentAttribute
+ {
+ ///
+ /// Returns or sets the name of the variable.
+ ///
+ private string VariableName { get; set; }
+
+ ///
+ /// Returns or sets the display string.
+ ///
+ private string Display { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The name of the variable.
+ /// The display string.
+ public SegmentUIntAttribute(string variableName, string display)
+ {
+ VariableName = variableName;
+ Display = display;
+ }
+
+ ///
+ /// Conversion to a path segment.
+ ///
+ /// The path segment.
+ public IUriPathSegment ToPathSegment()
+ {
+ //var expression = @"^\d$";
+
+ //var callBackDisplay = new Func((segment, moduleId, culture) =>
+ //{
+ // return Display;
+ //});
+
+ //var callBackValiables = new Func>(segment =>
+ //{
+ // var dict = new Dictionary
+ // {
+ // { VariableName, segment }
+ // };
+
+ // return dict;
+ //});
+
+ return new UriPathSegmentVariableUInt(VariableName, Display);
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/StatusCodeAttribute.cs b/src/WebExpress/WebAttribute/StatusCodeAttribute.cs
new file mode 100644
index 0000000..ec9c926
--- /dev/null
+++ b/src/WebExpress/WebAttribute/StatusCodeAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class StatusCodeAttribute : System.Attribute, IApplicationAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The status code.
+ public StatusCodeAttribute(int status)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/SystemPluginAttribute.cs b/src/WebExpress/WebAttribute/SystemPluginAttribute.cs
new file mode 100644
index 0000000..7354721
--- /dev/null
+++ b/src/WebExpress/WebAttribute/SystemPluginAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace WebExpress.WebAttribute
+{
+ ///
+ /// Marks an assembly as systemically relevant.
+ ///
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public class SystemPluginAttribute : Attribute
+ {
+ ///
+ /// Constructor
+ ///
+ public SystemPluginAttribute()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebAttribute/TitleAttribute.cs b/src/WebExpress/WebAttribute/TitleAttribute.cs
new file mode 100644
index 0000000..830bb2f
--- /dev/null
+++ b/src/WebExpress/WebAttribute/TitleAttribute.cs
@@ -0,0 +1,14 @@
+namespace WebExpress.WebAttribute
+{
+ public class TitleAttribute : System.Attribute, IResourceAttribute
+ {
+ ///
+ /// Constructor
+ ///
+ /// The display text.
+ public TitleAttribute(string display)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebComponent/ComponentDictionary.cs b/src/WebExpress/WebComponent/ComponentDictionary.cs
new file mode 100644
index 0000000..99c0da5
--- /dev/null
+++ b/src/WebExpress/WebComponent/ComponentDictionary.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Internal management of components.
+ /// key = plugin
+ /// value = component item
+ ///
+ public class ComponentDictionary : Dictionary>
+ {
+
+ }
+}
diff --git a/src/WebExpress/WebComponent/ComponentItem.cs b/src/WebExpress/WebComponent/ComponentItem.cs
new file mode 100644
index 0000000..e5f1d98
--- /dev/null
+++ b/src/WebExpress/WebComponent/ComponentItem.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace WebExpress.WebComponent
+{
+ public class ComponentItem
+ {
+ ///
+ /// Returns or set the class type for a component.
+ ///
+ public Type ComponentClass { get; internal set; }
+
+ ///
+ /// Returns the component id.
+ ///
+ public string ComponentId { get; internal set; }
+
+ ///
+ /// Returns the component instance or null if not already created.
+ ///
+ public IComponent ComponentInstance { get; internal set; }
+
+ ///
+ /// Constructor
+ ///
+ internal ComponentItem()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebComponent/ComponentManager.cs b/src/WebExpress/WebComponent/ComponentManager.cs
new file mode 100644
index 0000000..69e7c1c
--- /dev/null
+++ b/src/WebExpress/WebComponent/ComponentManager.cs
@@ -0,0 +1,488 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using WebExpress.Internationalization;
+using WebExpress.WebApplication;
+using WebExpress.WebEvent;
+using WebExpress.WebJob;
+using WebExpress.WebModule;
+using WebExpress.WebPackage;
+using WebExpress.WebPlugin;
+using WebExpress.WebResource;
+using WebExpress.WebSession;
+using WebExpress.WebSitemap;
+using WebExpress.WebStatusPage;
+using WebExpress.WebTask;
+
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Central management of components.
+ ///
+ public static class ComponentManager
+ {
+ ///
+ /// An event that fires when an component is added.
+ ///
+ public static event EventHandler AddComponent;
+
+ ///
+ /// An event that fires when an component is removed.
+ ///
+ public static event EventHandler RemoveComponent;
+
+ ///
+ /// Returns the reference to the context of the host.
+ ///
+ public static IHttpServerContext HttpServerContext { get; private set; }
+
+ ///
+ /// Returns the directory where the components are listed.
+ ///
+ private static ComponentDictionary Dictionary { get; } = new ComponentDictionary();
+
+ ///
+ /// Returns all registered components.
+ ///
+ public static IEnumerable Components => new IComponent[]
+ {
+ PackageManager,
+ PluginManager,
+ ApplicationManager,
+ ModuleManager,
+ EventManager,
+ JobManager,
+ ResponseManager,
+ SitemapManager,
+ InternationalizationManager,
+ SessionManager,
+ TaskManager
+ }.Concat(Dictionary.Values.SelectMany(x => x).Select(x => x.ComponentInstance));
+
+ ///
+ /// Returns the package manager.
+ ///
+ /// The instance of the package manager or null.
+ public static PackageManager PackageManager { get; private set; }
+
+ ///
+ /// Returns the plugin manager.
+ ///
+ /// The instance of the plugin manager or null.
+ public static PluginManager PluginManager { get; private set; }
+
+ ///
+ /// Returns the application manager.
+ ///
+ /// The instance of the application manager or null.
+ public static ApplicationManager ApplicationManager { get; private set; }
+
+ ///
+ /// Returns the module manager.
+ ///
+ /// The instance of the module manager or null.
+ public static ModuleManager ModuleManager { get; private set; }
+
+ ///
+ /// Returns the event manager.
+ ///
+ /// The instance of the event manager or null.
+ public static EventManager EventManager { get; private set; }
+
+ ///
+ /// Returns the job manager.
+ ///
+ /// The instance of the job manager or null.
+ public static JobManager JobManager { get; private set; }
+
+ ///
+ /// Returns the response manager.
+ ///
+ /// The instance of the response manager or null.
+ public static ResponseManager ResponseManager { get; private set; }
+
+ ///
+ /// Returns the resource manager.
+ ///
+ /// The instance of the resource manager or null.
+ public static ResourceManager ResourceManager { get; private set; }
+
+ ///
+ /// Returns the sitemap manager.
+ ///
+ /// The instance of the sitemap manager or null.
+ public static SitemapManager SitemapManager { get; private set; }
+
+ ///
+ /// Returns the internationalization manager.
+ ///
+ /// The instance of the internationalization manager or null.
+ public static InternationalizationManager InternationalizationManager { get; private set; }
+
+ ///
+ /// Returns the session manager.
+ ///
+ /// The instance of the session manager or null.
+ public static SessionManager SessionManager { get; private set; }
+
+ ///
+ /// Returns the task manager.
+ ///
+ /// The instance of the task manager manager or null.
+ public static TaskManager TaskManager { get; private set; }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ internal static void Initialization(IHttpServerContext httpServerContext)
+ {
+ HttpServerContext = httpServerContext;
+
+ InternationalizationManager.Register(typeof(HttpServer).Assembly, "webexpress");
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.initialization")
+ );
+
+ // order is relevant
+ PackageManager = CreateInstance(typeof(PackageManager)) as PackageManager;
+ PluginManager = CreateInstance(typeof(PluginManager)) as PluginManager;
+ InternationalizationManager = CreateInstance(typeof(InternationalizationManager)) as InternationalizationManager;
+ ApplicationManager = CreateInstance(typeof(ApplicationManager)) as ApplicationManager;
+ ModuleManager = CreateInstance(typeof(ModuleManager)) as ModuleManager;
+ ResourceManager = CreateInstance(typeof(ResourceManager)) as ResourceManager;
+ ResponseManager = CreateInstance(typeof(ResponseManager)) as ResponseManager;
+ EventManager = CreateInstance(typeof(EventManager)) as EventManager;
+ JobManager = CreateInstance(typeof(JobManager)) as JobManager;
+ SitemapManager = CreateInstance(typeof(SitemapManager)) as SitemapManager;
+ SessionManager = CreateInstance(typeof(SessionManager)) as SessionManager;
+ TaskManager = CreateInstance(typeof(TaskManager)) as TaskManager;
+
+ PluginManager.AddPlugin += (sender, pluginContext) =>
+ {
+ Register(pluginContext);
+ };
+
+ PluginManager.RemovePlugin += (sender, pluginContext) =>
+ {
+ Remove(pluginContext);
+ };
+ }
+
+ ///
+ /// Creates and initializes a component.
+ ///
+ /// The component class.
+ /// The instance of the create and initialized component.
+ private static IComponent CreateInstance(Type componentType)
+ {
+ if (componentType == null)
+ {
+ return null;
+ }
+ else if (!componentType.GetInterfaces().Where(x => x == typeof(IComponent)).Any())
+ {
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:componentmanager.wrongtype",
+ componentType?.FullName, typeof(IComponent).FullName
+ )
+ );
+
+ return null;
+ }
+
+ try
+ {
+ var flags = BindingFlags.NonPublic | BindingFlags.Instance;
+ var component = componentType?.Assembly.CreateInstance
+ (
+ componentType?.FullName,
+ false,
+ flags,
+ null,
+ null,
+ null,
+ null
+ ) as IComponent;
+
+ //var component = Activator.CreateInstance(componentType, flags) as IComponent;
+
+ component.Initialization(HttpServerContext);
+
+ return component;
+ }
+ catch (Exception ex)
+ {
+ HttpServerContext.Log.Exception(ex);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns a component based on its id.
+ ///
+ /// The id.
+ /// The instance of the component or null.
+ public static IComponent GetComponent(string id)
+ {
+ return Dictionary.Values
+ .SelectMany(x => x)
+ .Where(x => x.ComponentId.Equals(id, StringComparison.OrdinalIgnoreCase))
+ .Select(x => x.ComponentInstance)
+ .FirstOrDefault();
+ }
+
+ ///
+ /// Returns a component based on its type.
+ ///
+ /// The component class.
+ /// The instance of the component or null.
+ public static T GetComponent() where T : IComponent
+ {
+ return (T)Dictionary.Values
+ .SelectMany(x => x)
+ .Where(x => x.ComponentClass == typeof(T))
+ .Select(x => x.ComponentInstance)
+ .FirstOrDefault();
+ }
+
+ ///
+ /// Discovers and registers the components from the specified plugin.
+ ///
+ /// A plugin context that contain the components.
+ public static void Register(IPluginContext pluginContext)
+ {
+ // the plugin has already been registered
+ if (Dictionary.ContainsKey(pluginContext))
+ {
+ return;
+ }
+
+ var assembly = pluginContext.Assembly;
+
+ Dictionary.Add(pluginContext, new List());
+ var componentItems = Dictionary[pluginContext];
+
+ foreach (var type in assembly.GetExportedTypes().Where(x => x.IsClass && x.IsSealed && x.GetInterface(typeof(IComponent).Name) != null))
+ {
+ var id = type.FullName?.ToLower();
+
+ // determining attributes
+ var componentInstance = CreateInstance(type);
+
+ if (!componentItems.Where(x => x.ComponentId.Equals(id, StringComparison.OrdinalIgnoreCase)).Any())
+ {
+ componentItems.Add(new ComponentItem()
+ {
+ ComponentClass = type,
+ ComponentId = id,
+ ComponentInstance = componentInstance
+ });
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.register", id)
+ );
+
+ // raises the AddComponent event
+ OnAddComponent(componentInstance);
+ }
+ else
+ {
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.duplicate", id)
+ );
+ }
+ }
+ }
+
+ ///
+ /// Discovers and registers the components from the specified plugins.
+ ///
+ /// A list with plugin contexts that contain the components.
+ public static void Register(IEnumerable pluginContexts)
+ {
+ foreach (var pluinContext in pluginContexts)
+ {
+ Register(pluinContext);
+ }
+ }
+
+ ///
+ /// Boots the components.
+ ///
+ /// The plugin context.
+ internal static void BootComponent(IPluginContext pluginContext)
+ {
+ PluginManager.Boot(pluginContext);
+ ApplicationManager.Boot(pluginContext);
+ ModuleManager.Boot(pluginContext);
+
+ foreach (var component in Dictionary.Values
+ .Where(x => x is IExecutableElements)
+ .Select(x => x as IExecutableElements))
+ {
+ component.Boot(pluginContext);
+ }
+ }
+
+ ///
+ /// Boots the components.
+ ///
+ /// A enumeration of plugin contexts.
+ internal static void BootComponent(IEnumerable pluginContexts)
+ {
+ foreach (var pluginContext in pluginContexts)
+ {
+ BootComponent(pluginContext);
+ }
+ }
+
+ ///
+ /// Starts the component.
+ ///
+ internal static void Execute()
+ {
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.execute")
+ );
+
+ PackageManager.Execute();
+ JobManager.Execute();
+ }
+
+ ///
+ /// Shutting down the component manager.
+ ///
+ public static void ShutDown()
+ {
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.shutdown")
+ );
+ }
+
+ ///
+ /// Shutting down the component.
+ ///
+ /// The plugin context.
+ public static void ShutDownComponent(IPluginContext pluginContext)
+ {
+ PluginManager.ShutDown(pluginContext);
+ ApplicationManager.ShutDown(pluginContext);
+ ModuleManager.ShutDown(pluginContext);
+
+ foreach (var component in Dictionary.Values
+ .Where(x => x is IExecutableElements)
+ .Select(x => x as IExecutableElements))
+ {
+ component.ShutDown(pluginContext);
+ }
+ }
+
+ ///
+ /// Removes all components associated with the specified plugin context.
+ ///
+ /// The context of the plugin that contains the applications to remove.
+ public static void Remove(IPluginContext pluginContext)
+ {
+ if (Dictionary.ContainsKey(pluginContext))
+ {
+ return;
+ }
+
+ var componentItems = Dictionary[pluginContext];
+
+ if (!componentItems.Any())
+ {
+ return;
+ }
+
+ foreach (var componentItem in componentItems)
+ {
+ OnRemoveComponent(componentItem.ComponentInstance);
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N("webexpress:componentmanager.remove")
+ );
+ }
+
+ ModuleManager.Remove(pluginContext);
+ ApplicationManager.Remove(pluginContext);
+ PluginManager.Remove(pluginContext);
+
+ Dictionary.Remove(pluginContext);
+ }
+
+ ///
+ /// Raises the AddComponent event.
+ ///
+ /// The component.
+ private static void OnAddComponent(IComponent component)
+ {
+ AddComponent?.Invoke(null, component);
+ }
+
+ ///
+ /// Raises the RemoveComponent event.
+ ///
+ /// The component.
+ private static void OnRemoveComponent(IComponent component)
+ {
+ RemoveComponent?.Invoke(null, component);
+ }
+
+ ///
+ /// Output of the components to the log.
+ ///
+ public static void LogStatus()
+ {
+ using var frame = new LogFrameSimple(HttpServerContext.Log);
+ var output = new List
+ {
+ InternationalizationManager.I18N("webexpress:componentmanager.component")
+ };
+
+ foreach (var pluginContext in PluginManager.Plugins)
+ {
+ output.Add
+ (
+ string.Empty.PadRight(2) +
+ InternationalizationManager.I18N("webexpress:pluginmanager.plugin", pluginContext.PluginId)
+ );
+
+ ApplicationManager.PrepareForLog(pluginContext, output, 4);
+ ModuleManager.PrepareForLog(pluginContext, output, 4);
+ ResourceManager.PrepareForLog(pluginContext, output, 4);
+ ResponseManager.PrepareForLog(pluginContext, output, 4);
+ JobManager.PrepareForLog(pluginContext, output, 4);
+ }
+
+ foreach (var item in Dictionary)
+ {
+ foreach (var component in item.Value)
+ {
+ output.Add
+ (
+ string.Empty.PadRight(2) +
+ InternationalizationManager.I18N("webexpress:pluginmanager.plugin", item.Key.PluginId)
+ );
+
+ component.ComponentInstance?.PrepareForLog(item.Key, output, 4);
+ }
+ }
+
+ HttpServerContext.Log.Info(string.Join(Environment.NewLine, output));
+ }
+ }
+}
diff --git a/src/WebExpress/WebComponent/IComponent.cs b/src/WebExpress/WebComponent/IComponent.cs
new file mode 100644
index 0000000..6ca4d05
--- /dev/null
+++ b/src/WebExpress/WebComponent/IComponent.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Interface of the manager classes.
+ ///
+ public interface IComponent
+ {
+ ///
+ /// Returns the reference to the context of the host.
+ ///
+ static IHttpServerContext HttpServerContext { get; }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ void Initialization(IHttpServerContext context);
+
+ ///
+ /// Information about the component is collected and prepared for output in the log.
+ ///
+ /// The context of the plugin.
+ /// A list of log entries.
+ /// The shaft deep.
+ void PrepareForLog(IPluginContext pluginContext, IList output, int deep);
+ }
+}
diff --git a/src/WebExpress/WebComponent/IComponentPlugin.cs b/src/WebExpress/WebComponent/IComponentPlugin.cs
new file mode 100644
index 0000000..b86304e
--- /dev/null
+++ b/src/WebExpress/WebComponent/IComponentPlugin.cs
@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Interface of the manager classes.
+ ///
+ public interface IComponentPlugin : IComponent
+ {
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A context of a plugin whose elements are to be registered.
+ void Register(IPluginContext pluginContext);
+
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A list with plugin contexts that contain the elements.
+ void Register(IEnumerable pluginContexts);
+
+ ///
+ /// Removes all elemets associated with the specified plugin context.
+ ///
+ /// The context of the plugin that contains the elemets to remove.
+ void Remove(IPluginContext pluginContext);
+ }
+}
diff --git a/src/WebExpress/WebComponent/IExecutableElements.cs b/src/WebExpress/WebComponent/IExecutableElements.cs
new file mode 100644
index 0000000..a298abb
--- /dev/null
+++ b/src/WebExpress/WebComponent/IExecutableElements.cs
@@ -0,0 +1,28 @@
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Indicates that a manager manages executable elements.
+ ///
+ public interface IExecutableElements
+ {
+ ///
+ /// Boots the executable elements of a plugin.
+ ///
+ /// The context of the plugin containing the elements.
+ internal void Boot(IPluginContext pluginContext)
+ {
+
+ }
+
+ ///
+ /// Terminate the executable elements of a plugin.
+ ///
+ /// The context of the plugin containing the elements.
+ public void ShutDown(IPluginContext pluginContext)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebComponent/ISystemComponent.cs b/src/WebExpress/WebComponent/ISystemComponent.cs
new file mode 100644
index 0000000..5e686b6
--- /dev/null
+++ b/src/WebExpress/WebComponent/ISystemComponent.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebComponent
+{
+ ///
+ /// Marks a manager as systemically relevant.
+ ///
+ internal interface ISystemComponent
+ {
+ }
+}
diff --git a/src/WebExpress/WebCondition/ICondition.cs b/src/WebExpress/WebCondition/ICondition.cs
new file mode 100644
index 0000000..348ddf0
--- /dev/null
+++ b/src/WebExpress/WebCondition/ICondition.cs
@@ -0,0 +1,17 @@
+using WebExpress.WebMessage;
+
+namespace WebExpress.WebCondition
+{
+ ///
+ /// Stellt eine Bedingiung dar, die erfüllt sein muss
+ ///
+ public interface ICondition
+ {
+ ///
+ /// Die Bedingung
+ ///
+ /// The request.
+ /// true wenn die Bedingung erfüllt ist, false sonst
+ bool Fulfillment(Request request);
+ }
+}
diff --git a/src/WebExpress/WebEvent/EventDictionary.cs b/src/WebExpress/WebEvent/EventDictionary.cs
new file mode 100644
index 0000000..a579885
--- /dev/null
+++ b/src/WebExpress/WebEvent/EventDictionary.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using WebExpress.WebEvent;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebJob
+{
+ ///
+ /// key = plugin context
+ /// value = ressource items
+ ///
+ internal class EventDictionary : Dictionary>
+ {
+ }
+}
diff --git a/src/WebExpress/WebEvent/EventManager.cs b/src/WebExpress/WebEvent/EventManager.cs
new file mode 100644
index 0000000..1446b8c
--- /dev/null
+++ b/src/WebExpress/WebEvent/EventManager.cs
@@ -0,0 +1,174 @@
+using System.Collections.Generic;
+using System.Linq;
+using WebExpress.Internationalization;
+using WebExpress.WebComponent;
+using WebExpress.WebJob;
+using WebExpress.WebModule;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebEvent
+{
+ ///
+ /// The event manager.
+ ///
+ public sealed class EventManager : IComponentPlugin, ISystemComponent
+ {
+ ///
+ /// Returns or sets the reference to the context of the host.
+ ///
+ public IHttpServerContext HttpServerContext { get; private set; }
+
+ ///
+ /// Returns the directory where the events are listed.
+ ///
+ private EventDictionary Dictionary { get; } = new EventDictionary();
+
+ ///
+ /// Constructor
+ ///
+ internal EventManager()
+ {
+ ComponentManager.PluginManager.AddPlugin += (sender, pluginContext) =>
+ {
+ Register(pluginContext);
+ };
+
+ ComponentManager.PluginManager.RemovePlugin += (sender, pluginContext) =>
+ {
+ Remove(pluginContext);
+ };
+
+ ComponentManager.ModuleManager.AddModule += (sender, moduleContext) =>
+ {
+ AssignToModule(moduleContext);
+ };
+
+ ComponentManager.ModuleManager.RemoveModule += (sender, moduleContext) =>
+ {
+ DetachFromModule(moduleContext);
+ };
+ }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ public void Initialization(IHttpServerContext context)
+ {
+ HttpServerContext = context;
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:eventmanager.initialization"
+ )
+ );
+ }
+
+ ///
+ /// Discovers and registers event handlers from the specified plugin.
+ ///
+ /// A context of a plugin whose event handlers are to be registered.
+ public void Register(IPluginContext pluginContext)
+ {
+ var assembly = pluginContext?.Assembly;
+
+ foreach (var eventHandlerType in assembly.GetTypes().Where
+ (
+ x => x.IsClass == true &&
+ x.IsSealed &&
+ x.IsPublic &&
+ x.GetInterface(typeof(IEventHandler).Name) != null
+ ))
+ {
+
+ }
+ }
+
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A list with plugin contexts that contain the jobs.
+ public void Register(IEnumerable pluginContexts)
+ {
+ foreach (var pluginContext in pluginContexts)
+ {
+ Register(pluginContext);
+ }
+ }
+
+ ///
+ /// Assign existing event to the module.
+ ///
+ /// The context of the module.
+ private void AssignToModule(IModuleContext moduleContext)
+ {
+ //foreach (var scheduleItem in Dictionary.Values.SelectMany(x => x))
+ //{
+ // if (scheduleItem.moduleId.Equals(moduleContext?.ModuleId))
+ // {
+ // scheduleItem.AddModule(moduleContext);
+ // }
+ //}
+ }
+
+ ///
+ /// Remove an existing modules to the event.
+ ///
+ /// The context of the module.
+ private void DetachFromModule(IModuleContext moduleContext)
+ {
+ //foreach (var scheduleItem in Dictionary.Values.SelectMany(x => x))
+ //{
+ // if (scheduleItem.moduleId.Equals(moduleContext?.ModuleId))
+ // {
+ // scheduleItem.DetachModule(moduleContext);
+ // }
+ //}
+ }
+
+ ///
+ /// Removes all jobs associated with the specified plugin context.
+ ///
+ /// The context of the plugin that contains the event to remove.
+ public void Remove(IPluginContext pluginContext)
+ {
+ //// the plugin has not been registered in the manager
+ //if (!Dictionary.ContainsKey(pluginContext))
+ //{
+ // return;
+ //}
+
+ //foreach (var scheduleItem in Dictionary[pluginContext])
+ //{
+ // scheduleItem.Dispose();
+ //}
+
+ //Dictionary.Remove(pluginContext);
+ }
+
+ ///
+ /// Information about the component is collected and prepared for output in the event.
+ ///
+ /// The context of the plugin.
+ /// A list of log entries.
+ /// The shaft deep.
+ public void PrepareForLog(IPluginContext pluginContext, IList output, int deep)
+ {
+ //foreach (var scheduleItem in GetScheduleItems(pluginContext))
+ //{
+ // output.Add
+ // (
+ // string.Empty.PadRight(deep) +
+ // InternationalizationManager.I18N
+ // (
+ // "webexpress:eventmanager.job",
+ // scheduleItem.JobId,
+ // scheduleItem.ModuleContext
+ // )
+ // );
+ //}
+ }
+ }
+}
diff --git a/src/WebExpress/WebEvent/IEventContext.cs b/src/WebExpress/WebEvent/IEventContext.cs
new file mode 100644
index 0000000..7008149
--- /dev/null
+++ b/src/WebExpress/WebEvent/IEventContext.cs
@@ -0,0 +1,18 @@
+using WebExpress.WebModule;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebEvent
+{
+ public interface IEventContext
+ {
+ ///
+ /// Returns the associated plugin context.
+ ///
+ IPluginContext PluginContext { get; }
+
+ ///
+ /// Returns the corresponding module context.
+ ///
+ IModuleContext ModuleContext { get; }
+ }
+}
diff --git a/src/WebExpress/WebEvent/IEventHandler.cs b/src/WebExpress/WebEvent/IEventHandler.cs
new file mode 100644
index 0000000..4abe972
--- /dev/null
+++ b/src/WebExpress/WebEvent/IEventHandler.cs
@@ -0,0 +1,6 @@
+namespace WebExpress.WebEvent
+{
+ public interface IEventHandler
+ {
+ }
+}
diff --git a/src/WebExpress/WebEx.cs b/src/WebExpress/WebEx.cs
new file mode 100644
index 0000000..1d5f6ab
--- /dev/null
+++ b/src/WebExpress/WebEx.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Xml.Serialization;
+using WebExpress.Config;
+using WebExpress.WebComponent;
+using WebExpress.WebUri;
+using static WebExpress.Internationalization.InternationalizationManager;
+
+namespace WebExpress
+{
+ public class WebEx
+ {
+ ///
+ /// Returns or sets the name of the web server.
+ ///
+ public string Name { get; set; } = "WebExpress";
+
+ ///
+ /// The http(s) server.
+ ///
+ private HttpServer HttpServer { get; set; }
+
+ ///
+ /// Returns the program version.
+ ///
+ public static string Version => Assembly.GetExecutingAssembly().GetName().Version.ToString();
+
+ ///
+ /// Entry point of application.
+ ///
+ /// Call arguments.
+ public static int Main(string[] args)
+ {
+ var app = new WebEx()
+ {
+ Name = Assembly.GetExecutingAssembly().GetName().Name
+ };
+
+ return app.Execution(args);
+ }
+
+ ///
+ /// Running the application.
+ ///
+ /// Call arguments.
+ public int Execution(string[] args)
+ {
+ // prepare call arguments
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "help", ShortName = "h" });
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "config", ShortName = "c" });
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "port", ShortName = "p" });
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "spec", ShortName = "s" });
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "output", ShortName = "o" });
+ ArgumentParser.Current.Register(new ArgumentParserCommand() { FullName = "target", ShortName = "t" });
+
+ // parsing call arguments
+ var argumentDict = ArgumentParser.Current.Parse(args);
+
+ if (argumentDict.ContainsKey("help"))
+ {
+ Console.WriteLine(Name + " [-port number | -config dateiname | -help]");
+ Console.WriteLine("Version: " + Version);
+
+ return 0;
+ }
+
+ // package builder
+ if (argumentDict.ContainsKey("spec") || argumentDict.ContainsKey("output"))
+ {
+ if (!argumentDict.ContainsKey("spec"))
+ {
+ Console.WriteLine("*** PackageBuilder: The spec file (-s) was not specified.");
+
+ return 1;
+ }
+
+ if (!argumentDict.ContainsKey("config"))
+ {
+ Console.WriteLine("*** PackageBuilder: The config (-c) was not specified.");
+
+ return 1;
+ }
+
+ if (!argumentDict.ContainsKey("target"))
+ {
+ Console.WriteLine("*** PackageBuilder: The target framework (-t) was not specified.");
+
+ return 1;
+ }
+
+ if (!argumentDict.ContainsKey("output"))
+ {
+ Console.WriteLine("*** PackageBuilder: The output directory (-o) was not specified.");
+
+ return 1;
+ }
+
+ WebPackage.PackageBuilder.Create(argumentDict["spec"], argumentDict["config"], argumentDict["target"], argumentDict["output"]);
+
+ return 0;
+ }
+
+ // configuration
+ if (!argumentDict.ContainsKey("config"))
+ {
+ // check if there is a file called config.xml
+ if (!File.Exists(Path.Combine(Path.Combine(Environment.CurrentDirectory, "config"), "webexpress.config.xml")))
+ {
+ Console.WriteLine("No configuration file was specified. Usage: " + Name + " -config filename");
+
+ return 1;
+ }
+
+ argumentDict.Add("config", "webexpress.config.xml");
+ }
+
+ // initialization of the web server
+ Initialization(ArgumentParser.Current.GetValidArguments(args), Path.Combine(Path.Combine(Environment.CurrentDirectory, "config"), argumentDict["config"]));
+
+ // start the manager
+ ComponentManager.Execute();
+
+ // starting the web server
+ Start();
+
+ // finish
+ Exit();
+
+ return 0;
+ }
+
+ ///
+ /// Called when the application is to be terminated using Ctrl+C.
+ ///
+ /// The trigger of the event.
+ /// The event argument.
+ private void OnCancel(object sender, ConsoleCancelEventArgs e)
+ {
+ Exit();
+ }
+
+ ///
+ /// Initialization
+ ///
+ /// The valid arguments.
+ /// The configuration file.
+ private void Initialization(string args, string configFile)
+ {
+ // Config laden
+ using var reader = new FileStream(configFile, FileMode.Open);
+ var serializer = new XmlSerializer(typeof(HttpServerConfig));
+ var config = serializer.Deserialize(reader) as HttpServerConfig;
+ var log = new Log();
+
+ var culture = CultureInfo.CurrentCulture;
+
+ try
+ {
+ culture = new CultureInfo(config.Culture);
+
+ CultureInfo.CurrentCulture = culture;
+ }
+ catch
+ {
+
+ }
+
+ var packageBase = string.IsNullOrWhiteSpace(config.PackageBase) ?
+ Environment.CurrentDirectory : Path.IsPathRooted(config.PackageBase) ?
+ config.PackageBase :
+ Path.Combine(Environment.CurrentDirectory, config.PackageBase);
+
+ var assetBase = string.IsNullOrWhiteSpace(config.AssetBase) ?
+ Environment.CurrentDirectory : Path.IsPathRooted(config.AssetBase) ?
+ config.AssetBase :
+ Path.Combine(Environment.CurrentDirectory, config.AssetBase);
+
+ var dataBase = string.IsNullOrWhiteSpace(config.DataBase) ?
+ Environment.CurrentDirectory : Path.IsPathRooted(config.DataBase) ?
+ config.DataBase :
+ Path.Combine(Environment.CurrentDirectory, config.DataBase);
+
+ var context = new HttpServerContext
+ (
+ config.Uri,
+ config.Endpoints,
+ Path.GetFullPath(packageBase),
+ Path.GetFullPath(assetBase),
+ Path.GetFullPath(dataBase),
+ Path.GetDirectoryName(configFile),
+ new UriResource(config.ContextPath),
+ culture,
+ log,
+ null
+ );
+
+ HttpServer = new HttpServer(context)
+ {
+ Config = config
+ };
+
+ // start logging
+ HttpServer.HttpServerContext.Log.Begin(config.Log);
+
+ // log program start
+ HttpServer.HttpServerContext.Log.Seperator('/');
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.startup"));
+ HttpServer.HttpServerContext.Log.Info(message: "".PadRight(80, '-'));
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.version"), args: Version);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.arguments"), args: args);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.workingdirectory"), args: Environment.CurrentDirectory);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.packagebase"), args: config.PackageBase);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.assetbase"), args: config.AssetBase);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.database"), args: config.DataBase);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.configurationdirectory"), args: Path.GetDirectoryName(configFile));
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.configuration"), args: Path.GetFileName(configFile));
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.logdirectory"), args: Path.GetDirectoryName(HttpServer.HttpServerContext.Log.Filename));
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.log"), args: Path.GetFileName(HttpServer.HttpServerContext.Log.Filename));
+ foreach (var v in config.Endpoints)
+ {
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.uri"), args: v.Uri);
+ }
+
+ HttpServer.HttpServerContext.Log.Seperator('=');
+
+ if (!Directory.Exists(config.PackageBase))
+ {
+ Directory.CreateDirectory(config.PackageBase);
+ }
+
+ if (!Directory.Exists(config.AssetBase))
+ {
+ Directory.CreateDirectory(config.AssetBase);
+ }
+
+ if (!Directory.Exists(config.DataBase))
+ {
+ Directory.CreateDirectory(config.DataBase);
+ }
+
+ Console.CancelKeyPress += OnCancel;
+ }
+
+ ///
+ /// Start the web server.
+ ///
+ private void Start()
+ {
+ HttpServer.Start();
+
+ Thread.CurrentThread.Join();
+ }
+
+ ///
+ /// Quits the application.
+ ///
+ private void Exit()
+ {
+ HttpServer.Stop();
+
+ // end of program log
+ HttpServer.HttpServerContext.Log.Seperator('=');
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.errors"), args: HttpServer.HttpServerContext.Log.ErrorCount);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.warnings"), args: HttpServer.HttpServerContext.Log.WarningCount);
+ HttpServer.HttpServerContext.Log.Info(message: I18N("webexpress:app.done"));
+ HttpServer.HttpServerContext.Log.Seperator('/');
+
+ // stop logging
+ HttpServer.HttpServerContext.Log.Close();
+ }
+ }
+}
diff --git a/src/WebExpress/WebExpress.csproj b/src/WebExpress/WebExpress.csproj
new file mode 100644
index 0000000..ce8ec0d
--- /dev/null
+++ b/src/WebExpress/WebExpress.csproj
@@ -0,0 +1,59 @@
+
+
+
+ Library
+ WebExpress
+ 0.0.3.0
+ 0.0.3.0
+ net7.0
+ any
+ https://github.com/ReneSchwarzer/WebExpress.git
+ Rene_Schwarzer@hotmail.de
+ MIT
+ Rene_Schwarzer@hotmail.de
+ true
+ True
+ Core library of the WebExpress web server.
+ 0.0.3-alpha
+ https://github.com/ReneSchwarzer/WebExpress
+ icon.png
+ README.md
+ git
+ webexpress
+ True
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
+
+
+ True
+ \
+
+
+
+
diff --git a/src/WebExpress/WebHtml/Css.cs b/src/WebExpress/WebHtml/Css.cs
new file mode 100644
index 0000000..233e9a1
--- /dev/null
+++ b/src/WebExpress/WebHtml/Css.cs
@@ -0,0 +1,28 @@
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ public static class Css
+ {
+ ///
+ /// Verbindet die angebenen CSS-Klassen zu einem String
+ ///
+ /// Die einzelnen CSS-Klassen
+ /// Die Css-Klassen als String
+ public static string Concatenate(params string[] items)
+ {
+ return string.Join(' ', items.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct());
+ }
+
+ ///
+ /// Entfernt die angegebenen CSS-Klassen aus dem Gesammtsring
+ ///
+ /// Die in einem gemeinsamen String verbundenen CSS-Klassen
+ /// Die zu entfernenden CSS-Klassen
+ /// Die Css-Klassen als String
+ public static string Remove(string css, params string[] remove)
+ {
+ return string.Join(' ', css.Split(' ').Where(x => !remove.Contains(x)));
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/Favicon.cs b/src/WebExpress/WebHtml/Favicon.cs
new file mode 100644
index 0000000..65e89c7
--- /dev/null
+++ b/src/WebExpress/WebHtml/Favicon.cs
@@ -0,0 +1,80 @@
+namespace WebExpress.WebHtml
+{
+ public class Favicon
+ {
+ ///
+ /// Returns or sets the uri.
+ ///
+ public string Url { get; set; }
+
+ ///
+ /// Returns or sets the media type.
+ ///
+ public TypeFavicon Mediatype { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The uri.
+ /// The media type.
+ public Favicon(string url, TypeFavicon mediatype)
+ {
+ Url = url;
+ Mediatype = mediatype;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The uri.
+ /// The media type.
+ public Favicon(string url)
+ {
+ Url = url;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The uri.
+ /// The media type.
+ public Favicon(string url, string mediatype)
+ {
+ Url = url;
+
+ switch (mediatype)
+ {
+ case "image/x-icon":
+ Mediatype = TypeFavicon.ICON;
+ break;
+ case "image/jpg":
+ Mediatype = TypeFavicon.JPG;
+ break;
+ case "image/png":
+ Mediatype = TypeFavicon.PNG;
+ break;
+ case "image/svg+xml":
+ Mediatype = TypeFavicon.SVG;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// Returns the media type.
+ ///
+ /// The media type.
+ public string GetMediatyp()
+ {
+ return Mediatype switch
+ {
+ TypeFavicon.ICON => "image/x-icon",
+ TypeFavicon.JPG => "image/jpg",
+ TypeFavicon.PNG => "image/png",
+ TypeFavicon.SVG => "image/svg+xml",
+ _ => "",
+ };
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HTMLElementExtension.cs b/src/WebExpress/WebHtml/HTMLElementExtension.cs
new file mode 100644
index 0000000..d3162cc
--- /dev/null
+++ b/src/WebExpress/WebHtml/HTMLElementExtension.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Extension methods for HTMLEelements.
+ ///
+ public static class HTMLElementExtension
+ {
+ ///
+ /// Adds a css class.
+ ///
+ /// The HTML element to extend.
+ /// The class to add.
+ /// The HTML element extended by the checkout.
+ public static IHtmlNode AddClass(this IHtmlNode html, string cssClass)
+ {
+ if (html is HtmlElement)
+ {
+ var element = html as HtmlElement;
+
+ var list = new List(element.Class.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)).Select(x => x.ToLower()).ToList();
+
+ if (!list.Contains(cssClass.ToLower()))
+ {
+ list.Add(cssClass.ToLower());
+ }
+
+ var css = string.Join(' ', list);
+
+ element.Class = css;
+ }
+
+ return html;
+ }
+
+ ///
+ /// Removes a css class.
+ ///
+ /// The HTML element.
+ /// The class to remove.
+ /// The HTML element reduced by the checkout.
+ public static IHtmlNode RemoveClass(this IHtmlNode html, string cssClass)
+ {
+ if (cssClass == null) return html;
+
+ if (html is HtmlElement)
+ {
+ var element = html as HtmlElement;
+
+ var list = new List(element.Class.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)).Select(x => x.ToLower()).ToList();
+
+ if (list.Contains(cssClass.ToLower()))
+ {
+ list.Remove(cssClass.ToLower());
+ }
+
+ var css = string.Join(' ', list);
+
+ element.Class = css;
+ }
+
+ return html;
+ }
+
+ ///
+ /// Adds a style.
+ ///
+ /// The HTML element to extend.
+ /// The class to add.
+ /// The HTML element extended by the checkout.
+ public static IHtmlNode AddStyle(this IHtmlNode html, string cssStyle)
+ {
+ if (html is HtmlElement)
+ {
+ var element = html as HtmlElement;
+
+ var list = new List(element.Style.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)).Select(x => x.ToLower()).ToList();
+
+ if (!list.Contains(cssStyle.ToLower()))
+ {
+ list.Add(cssStyle.ToLower());
+ }
+
+ var css = string.Join(' ', list);
+
+ element.Style = css;
+ }
+
+ return html;
+ }
+
+ ///
+ /// Removes a style.
+ ///
+ /// The HTML element.
+ /// Der Style, welcher entfernt werden soll
+ /// The HTML element reduced by the checkout.
+ public static IHtmlNode RemoveStyle(this IHtmlNode html, string cssStyle)
+ {
+ if (html is HtmlElement)
+ {
+ var element = html as HtmlElement;
+
+ var list = new List(element.Style.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)).Select(x => x.ToLower()).ToList();
+
+ if (list.Contains(cssStyle?.ToLower()))
+ {
+ list.Remove(cssStyle.ToLower());
+ }
+
+ var css = string.Join(' ', list);
+
+ element.Style = css;
+ }
+
+ return html;
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlAttribute.cs b/src/WebExpress/WebHtml/HtmlAttribute.cs
new file mode 100644
index 0000000..6ca999a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlAttribute.cs
@@ -0,0 +1,58 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlAttribute : IHtmlAttribute
+ {
+ ///
+ /// Returns or sets the name. des Attributes
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Returns or sets the value.
+ ///
+ public string Value { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlAttribute()
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Der Name
+ public HtmlAttribute(string name)
+ {
+ Name = name;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Der Name
+ /// The value.
+ public HtmlAttribute(string name, string value)
+ {
+ Name = name;
+ Value = value;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Name);
+ builder.Append("=\"");
+ builder.Append(Value);
+ builder.Append("\"");
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlAttributeNoneValue.cs b/src/WebExpress/WebHtml/HtmlAttributeNoneValue.cs
new file mode 100644
index 0000000..ee8b3cf
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlAttributeNoneValue.cs
@@ -0,0 +1,43 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Ein Attribut ohne wert
+ /// z.B. required in input
+ ///
+ public class HtmlAttributeNoneValue : IHtmlAttribute
+ {
+ ///
+ /// Returns or sets the name. des Attributes
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlAttributeNoneValue()
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// Der Name
+ public HtmlAttributeNoneValue(string name)
+ {
+ Name = name;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Name);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlComment.cs b/src/WebExpress/WebHtml/HtmlComment.cs
new file mode 100644
index 0000000..4bbfc7f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlComment.cs
@@ -0,0 +1,41 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlComment : IHtmlNode
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlComment()
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The text.
+ public HtmlComment(string text)
+ {
+ Text = text;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append("");
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElement.cs b/src/WebExpress/WebHtml/HtmlElement.cs
new file mode 100644
index 0000000..5fb350c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElement.cs
@@ -0,0 +1,400 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlElement : IHtmlNode
+ {
+ ///
+ /// Returns or sets the name. des Attributes
+ ///
+ protected string ElementName { get; set; }
+
+ ///
+ /// Liefert oder setzt die Attribute
+ ///
+ protected List Attributes { get; private set; }
+
+ ///
+ /// Liefert oder setzt die Attribute
+ ///
+ protected List Elements { get; private set; }
+
+ ///
+ /// Returns or sets Returns or sets the id.
+ ///
+ public string Id
+ {
+ get => GetAttribute("id");
+ set => SetAttribute("id", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Css-Klasse
+ ///
+ public string Class
+ {
+ get => GetAttribute("class");
+ set => SetAttribute("class", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Css-Style
+ ///
+ public string Style
+ {
+ get => GetAttribute("style");
+ set => SetAttribute("style", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Rolle
+ ///
+ public string Role
+ {
+ get => GetAttribute("role");
+ set => SetAttribute("role", value);
+ }
+
+ ///
+ /// Liefert oder setzt das HTML5 Data-Attribut
+ ///
+ public string DataToggle
+ {
+ get => GetAttribute("data-toggle");
+ set => SetAttribute("data-toggle", value);
+ }
+
+ ///
+ /// Liefert oder setzt das HTML5 Data-Attribut
+ ///
+ public string DataProvide
+ {
+ get => GetAttribute("data-provide");
+ set => SetAttribute("data-provide", value);
+ }
+
+ ///
+ /// Liefert oder setzt die OnClick-Attribut
+ ///
+ public string OnClick
+ {
+ get => GetAttribute("onclick");
+ set => SetAttribute("onclick", value);
+ }
+
+ ///
+ /// Bestimmt, ob das Element inline ist
+ ///
+ public bool Inline { get; set; }
+
+ ///
+ /// Bestimmt ob das Element einen End-Tag benötigt
+ /// z.B.: true = false =
+ ///
+ public bool CloseTag { get; protected set; }
+
+ ///
+ /// Konstruktr
+ ///
+ /// Der Name des Elements
+ public HtmlElement(string name, bool closeTag = true)
+ {
+ ElementName = name;
+ Attributes = new List();
+ Elements = new List();
+ CloseTag = closeTag;
+ }
+
+ ///
+ /// Konstruktr
+ ///
+ /// Der Name des Elements
+ public HtmlElement(string name, bool closeTag, params IHtml[] nodes)
+ : this(name, closeTag)
+ {
+ foreach (var v in nodes)
+ {
+ if (v is HtmlAttribute)
+ {
+ Attributes.Add(v as HtmlAttribute);
+ }
+ else if (v is HtmlElement)
+ {
+ Elements.Add(v as HtmlElement);
+ }
+ else if (v is HtmlText)
+ {
+ Elements.Add(v as HtmlText);
+ }
+ }
+ }
+
+ ///
+ /// Liefert den Wert eines Attributs
+ ///
+ /// Der Attributname
+ /// Der Wert des Attributes
+ protected string GetAttribute(string name)
+ {
+ var a = Attributes.Where(x => x.Name == name).FirstOrDefault();
+
+ if (a != null)
+ {
+ return a is HtmlAttribute ? (a as HtmlAttribute).Value : string.Empty;
+ }
+
+ return string.Empty;
+ }
+
+ ///
+ /// Prüft ob ein Attribut gesetzt ist
+ ///
+ /// Der Attributname
+ /// true wenn Attribut vorhanden, false sonst
+ protected bool HasAttribute(string name)
+ {
+ var a = Attributes.Where(x => x.Name == name).FirstOrDefault();
+
+ return (a != null);
+ }
+
+ ///
+ /// Setzt den Wert eines Attributs
+ ///
+ /// Der Attributname
+ /// Der Wert des Attributes
+ protected void SetAttribute(string name, string value)
+ {
+ var a = Attributes.Where(x => x.Name == name).FirstOrDefault();
+
+ if (a != null)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ Attributes.Remove(a);
+ }
+ else if (a is HtmlAttribute)
+ {
+ (a as HtmlAttribute).Value = value;
+ }
+ }
+ else
+ {
+ if (!string.IsNullOrWhiteSpace(value))
+ {
+ Attributes.Add(new HtmlAttribute(name, value));
+ }
+ }
+ }
+
+ ///
+ /// Setzt den Wert eines Attributs
+ ///
+ /// Der Attributname
+ protected void SetAttribute(string name)
+ {
+ var a = Attributes.Where(x => x.Name == name).FirstOrDefault();
+
+ if (a == null)
+ {
+ Attributes.Add(new HtmlAttributeNoneValue(name));
+ }
+ }
+
+ ///
+ /// Entfernt ein Attribut
+ ///
+ /// Der Attributname
+ protected void RemoveAttribute(string name)
+ {
+ var a = Attributes.Where(x => x.Name == name).FirstOrDefault();
+
+ if (a != null)
+ {
+ Attributes.Remove(a);
+ }
+ }
+
+ ///
+ /// Liefert ein Element anhand seines Namens
+ ///
+ /// Der Elementname
+ /// Das Element
+ protected HtmlElement GetElement(string name)
+ {
+ var a = Elements.Where(x => x is HtmlElement && (x as HtmlElement).ElementName == name).FirstOrDefault();
+
+ return a as HtmlElement;
+ }
+
+ ///
+ /// Setzt ein Element anhand seines Namens
+ ///
+ /// Das Element
+ protected void SetElement(HtmlElement element)
+ {
+ if (element != null)
+ {
+ var a = Elements.Where(x => x is HtmlElement && (x as HtmlElement).ElementName == element.ElementName);
+
+ foreach (var v in a)
+ {
+ Elements.Remove(v);
+ }
+
+ Elements.Add(element);
+ }
+ }
+
+ ///
+ /// Liefert den Text
+ ///
+ /// The text.
+ protected string GetText()
+ {
+ var a = Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value);
+
+ return string.Join(" ", a);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ ToPreString(builder, deep);
+
+ var closeTag = false;
+ var nl = true;
+
+ if (Elements.Count == 1 && Elements.First() is HtmlText)
+ {
+ closeTag = true;
+ nl = false;
+
+ Elements.First().ToString(builder, 0);
+ }
+ else if (Elements.Count > 0)
+ {
+ closeTag = true;
+ var count = builder.Length;
+
+ foreach (var v in Elements.Where(x => x != null))
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ if (count == builder.Length)
+ {
+ nl = false;
+ }
+ }
+ else if (Elements.Count == 0)
+ {
+ nl = false;
+ }
+
+ if (closeTag || CloseTag)
+ {
+ ToPostString(builder, deep, nl);
+ }
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ protected virtual void ToPreString(StringBuilder builder, int deep)
+ {
+ if (!Inline)
+ {
+ builder.AppendLine();
+ builder.Append(string.Empty.PadRight(deep));
+ }
+
+ builder.Append("<");
+ builder.Append(ElementName);
+ foreach (var v in Attributes)
+ {
+ builder.Append(" ");
+ v.ToString(builder, 0);
+ }
+ builder.Append(">");
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ /// Abschlustag auf neuer Zeile beginnen
+ protected virtual void ToPostString(StringBuilder builder, int deep, bool nl = true)
+ {
+ if (!Inline && nl)
+ {
+ builder.AppendLine();
+ builder.Append(string.Empty.PadRight(deep));
+ }
+
+ builder.Append("");
+ builder.Append(ElementName);
+ builder.Append(">");
+ }
+
+ ///
+ /// Setzt den Wert eines Attributs
+ ///
+ /// Der Attributname
+ /// Der Wert des Attributes
+ public void AddUserAttribute(string name, string value)
+ {
+ SetAttribute(name, value);
+ }
+
+ ///
+ /// Liefert den Wert eines Attributs
+ ///
+ /// Der Attributname
+ /// Der Wert des Attributes
+ public string GetUserAttribute(string name)
+ {
+ return GetAttribute(name);
+ }
+
+ ///
+ /// Prüft ob ein Attribut gesetzt ist
+ ///
+ /// Der Attributname
+ /// true wenn Attribut vorhanden, false sonst
+ public bool HasUserAttribute(string name)
+ {
+ return HasAttribute(name);
+ }
+
+ ///
+ /// Entfernt ein Attribut
+ ///
+ /// Der Attributname
+ protected void RemoveUserAttribute(string name)
+ {
+ RemoveAttribute(name);
+ }
+
+ ///
+ /// In String konvertieren
+ ///
+ /// Das Objekt als String
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ ToString(builder, 0);
+
+ return builder.ToString();
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEditDel.cs b/src/WebExpress/WebHtml/HtmlElementEditDel.cs
new file mode 100644
index 0000000..f069323
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEditDel.cs
@@ -0,0 +1,78 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen aus dem Dokument entfernten Teil.
+ ///
+ public class HtmlElementEditDel : HtmlElement, IHtmlElementEdit
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join(string.Empty, Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt die URI einer Quelle, die die Änderung ausgelöst hat (z.B. eine Ticketnummer in einem Bugtrack-System).
+ ///
+ public string Cite
+ {
+ get => GetAttribute("cite");
+ set => SetAttribute("cite", value);
+ }
+
+ ///
+ /// Liefert oder setzt die indiziert das Datum und die Uhrzeit, wann The text. geändert wurde.
+ /// Wenn der Wert nicht als Datum mit optionaler Zeitangabe erkannt werden kann, hat dieses Element keinen Bezug zur Zeit.
+ ///
+ public string DateTime
+ {
+ get => GetAttribute("datetime");
+ set => SetAttribute("datetime", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEditDel()
+ : base("del")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEditDel(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEditDel(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEditIns.cs b/src/WebExpress/WebHtml/HtmlElementEditIns.cs
new file mode 100644
index 0000000..370a405
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEditIns.cs
@@ -0,0 +1,78 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen zum Dokument hinzugefügten Teil.
+ ///
+ public class HtmlElementEditIns : HtmlElement, IHtmlElementEdit
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt die URI einer Quelle, die die Änderung ausgelöst hat (z.B. eine Ticketnummer in einem Bugtrack-System).
+ ///
+ public string Cite
+ {
+ get => GetAttribute("cite");
+ set => SetAttribute("cite", value);
+ }
+
+ ///
+ /// Liefert oder setzt die indiziert das Datum und die Uhrzeit, wann The text. geändert wurde.
+ /// Wenn der Wert nicht als Datum mit optionaler Zeitangabe erkannt werden kann, hat dieses Element keinen Bezug zur Zeit.
+ ///
+ public string DateTime
+ {
+ get => GetAttribute("datetime");
+ set => SetAttribute("datetime", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEditIns()
+ : base("ins")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEditIns(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEditIns(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedEmbed.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedEmbed.cs
new file mode 100644
index 0000000..7dc7cc7
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedEmbed.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Einbindungspunkt für externe Ressourcen. Dies sind typischerweise keine
+ /// HTML-Inhalte, sondern beispielsweise eine Applikation oder interaktiver Inhalt,
+ /// der mit Hilfe eines Plugins (anstatt nativ durch das Benutzerprogramms) dargestellt wird.
+ ///
+ public class HtmlElementEmbeddedEmbed : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedEmbed()
+ : base("embed")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedEmbed(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedEmbed(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedIframe.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedIframe.cs
new file mode 100644
index 0000000..f8bfa7c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedIframe.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert einen Rahmen, mit dem ein HTML-Dokument in seinem eigenen Kontext in das aktuelle Dokument eingebettet werden kann.
+ ///
+ public class HtmlElementEmbeddedIframe : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedIframe()
+ : base("iframe")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedIframe(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedIframe(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedObject.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedObject.cs
new file mode 100644
index 0000000..0fe5b31
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedObject.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für allgemeinen externen Inhalt, der je nach Kontext als Bild,
+ /// "verschachtelter Browsing-Kontext" (s. iframe), oder externer Inhalt
+ /// (der mit Hilfe eines Plugins darsgestellt wird) betrachtet wird.
+ ///
+ public class HtmlElementEmbeddedObject : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedObject()
+ : base("object")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedObject(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedObject(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedParam.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedParam.cs
new file mode 100644
index 0000000..9335468
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedParam.cs
@@ -0,0 +1,18 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert Parameter für ein Plugin, das für die Darstellung eines
+ /// mit
+ public class HtmlElementEmbeddedParam : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedParam()
+ : base("param", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedPicture.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedPicture.cs
new file mode 100644
index 0000000..7eac29f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedPicture.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ ///
+ ///
+ public class HtmlElementEmbeddedPicture : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedPicture()
+ : base("picture")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedPicture(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementEmbeddedPicture(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementEmbeddedSource.cs b/src/WebExpress/WebHtml/HtmlElementEmbeddedSource.cs
new file mode 100644
index 0000000..9fdbef3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementEmbeddedSource.cs
@@ -0,0 +1,18 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Ermöglicht es Autoren, alternative Medienressourcen (z.B. verschiedene Audio- oder Videoformate)
+ /// für Medienelemente wie
+ public class HtmlElementEmbeddedSource : HtmlElement, IHtmlElementEmbedded
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementEmbeddedSource()
+ : base("source", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFieldButton.cs b/src/WebExpress/WebHtml/HtmlElementFieldButton.cs
new file mode 100644
index 0000000..96c756c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFieldButton.cs
@@ -0,0 +1,134 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Html-Element Button.
+ ///
+ public class HtmlElementFieldButton : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets a value.
+ ///
+ public string Value
+ {
+ get => GetAttribute("value");
+ set => SetAttribute("value", value);
+ }
+
+ ///
+ /// Returns or sets whether the button is disabled.
+ ///
+ public bool Disabled
+ {
+ get => HasAttribute("disabled");
+ set { if (value) { SetAttribute("disabled"); } else { RemoveAttribute("disabled"); } }
+ }
+
+ ///
+ /// Returns or sets the identification name of the form element to which it is associated.
+ ///
+ public string Form
+ {
+ get => GetAttribute("form");
+ set => SetAttribute("form", value);
+ }
+
+ ///
+ /// Returns or sets the type of button (button, submit, reset).
+ ///
+ public string Type
+ {
+ get => GetAttribute("type");
+ set => SetAttribute("type", value);
+ }
+
+ ///
+ /// Returns or sets the tooltip.
+ ///
+ public string Title
+ {
+ get => GetAttribute("title");
+ set => SetAttribute("title", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFieldButton()
+ : base("button")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldButton(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldButton(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldButton(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ //if (Type == "submit" || Type == "reset")
+ //{
+ // ElementName = "input";
+ //}
+
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFieldInput.cs b/src/WebExpress/WebHtml/HtmlElementFieldInput.cs
new file mode 100644
index 0000000..96d4a3f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFieldInput.cs
@@ -0,0 +1,211 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für ein Feld für Benutzereingaben eines bestimmten Typs. Der Typ (Radiobutton, Ankreuzfeld, Texteingabe, etc.) wird anhand des type-Attributs angegeben.
+ ///
+ public class HtmlElementFieldInput : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+ ///
+ /// Liefert oder setzt den Mindestwert
+ ///
+ public string Type
+ {
+ get => GetAttribute("type");
+ set => SetAttribute("type", value);
+ }
+
+ ///
+ /// Returns or sets the value. des Eingabefeldes
+ ///
+ public string Value
+ {
+ get => GetAttribute("value");
+ set => SetAttribute("value", value?.Replace("'", "'")?.Replace("\"", """));
+ }
+
+ ///
+ /// Liefert oder setzt die Zeichenlänge bei text, search, tel, url, email, oder password
+ /// Falls kein Wert angegeben wird, wird der Standardwert 20 verwendet.
+ ///
+ public string Size
+ {
+ get => GetAttribute("size");
+ set => SetAttribute("size", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob das Felf schreibgeschützt ist
+ ///
+ public string Readonly
+ {
+ get => GetAttribute("readonly");
+ set => SetAttribute("readonly", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob das Eingabefeld verwendet werden kann
+ ///
+ public bool Disabled
+ {
+ get => HasAttribute("disabled");
+ set { if (value) { SetAttribute("disabled"); } else { RemoveAttribute("disabled"); } }
+ }
+
+ ///
+ /// Liefert oder setzt den Mindestwert
+ ///
+ public string Min
+ {
+ get => GetAttribute("min");
+ set => SetAttribute("min", value);
+ }
+
+ ///
+ /// Liefert oder setzt den Maximalenwert
+ ///
+ public string Max
+ {
+ get => GetAttribute("max");
+ set => SetAttribute("max", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Schrittweite bei numerische, Datums- oder Zeitangaben
+ ///
+ public string Step
+ {
+ get => GetAttribute("step");
+ set => SetAttribute("step", value);
+ }
+
+ ///
+ /// Returns or sets the name. einer Liste (datalist)
+ ///
+ public string List
+ {
+ get => GetAttribute("list");
+ set => SetAttribute("list", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob mehrfacheingaben von Datei-Uploads und Emaileingaben möglich sind
+ ///
+ public string Multiple
+ {
+ get => GetAttribute("multiple");
+ set => SetAttribute("multiple", value);
+ }
+
+ ///
+ /// Returns or sets the minimum length.
+ ///
+ public string MinLength
+ {
+ get => GetAttribute("minlength");
+ set => SetAttribute("minlength", value);
+ }
+
+ ///
+ /// Returns or sets the maximum length.
+ ///
+ public string MaxLength
+ {
+ get => GetAttribute("maxlength");
+ set => SetAttribute("maxlength", value);
+ }
+
+ ///
+ /// Returns or sets whether inputs are enforced.
+ ///
+ public bool Required
+ {
+ get => HasAttribute("required");
+ set { if (value) { SetAttribute("required"); } else { RemoveAttribute("required"); } }
+ }
+
+ ///
+ /// Liefert oder setzt ob eine Auswahl erfolt (nur bei Radio- und Check)
+ ///
+ public bool Checked
+ {
+ get => HasAttribute("checked");
+ set { if (value) { SetAttribute("checked"); } else { RemoveAttribute("checked"); } }
+ }
+
+ ///
+ /// Returns or sets a search pattern that checks the content.
+ ///
+ public string Pattern
+ {
+ get => GetAttribute("pattern");
+ set => SetAttribute("pattern", value);
+ }
+
+ ///
+ /// Returns or sets a placeholder text.
+ ///
+ public string Placeholder
+ {
+ get => GetAttribute("placeholder");
+ set => SetAttribute("placeholder", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Eingabemethode (hilft mobilen Geräten, die richtige Tastatur-(belegung) zu wählen)
+ ///
+ public string Inputmode
+ {
+ get => GetAttribute("inputmode");
+ set => SetAttribute("inputmode", value);
+ }
+
+ ///
+ /// Returns or sets the identification name of the form element to which it is associated.
+ ///
+ public string Form
+ {
+ get => GetAttribute("form");
+ set => SetAttribute("form", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFieldInput()
+ : base("input")
+ {
+ CloseTag = false;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldInput(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFieldLabel.cs b/src/WebExpress/WebHtml/HtmlElementFieldLabel.cs
new file mode 100644
index 0000000..c8cf593
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFieldLabel.cs
@@ -0,0 +1,70 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet die Beschriftung für ein Formular-Kontrollelement (z.B. Texteingabefelder).
+ ///
+ ///
+ ///
+ public class HtmlElementFieldLabel : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string For
+ {
+ get => GetAttribute("for");
+ set => SetAttribute("for", value);
+ }
+
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join(string.Empty, Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.RemoveAll(x => x is HtmlText); Elements.Insert(0, new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFieldLabel()
+ : base("label")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldLabel(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldLabel(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFieldLegend.cs b/src/WebExpress/WebHtml/HtmlElementFieldLegend.cs
new file mode 100644
index 0000000..b00e32f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFieldLegend.cs
@@ -0,0 +1,37 @@
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eine Beschriftung für ein
+ public class HtmlElementFieldLegend : HtmlElement
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFieldLegend()
+ : base("legend")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldLegend(string text)
+ : this()
+ {
+ Text = text;
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFieldSelect.cs b/src/WebExpress/WebHtml/HtmlElementFieldSelect.cs
new file mode 100644
index 0000000..3306181
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFieldSelect.cs
@@ -0,0 +1,94 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Kontrollelement, mit dem aus einer Reihe von Optionen ausgewählt werden kann.
+ ///
+ ///
+ public class HtmlElementFieldSelect : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Anzahl der gleichzeitig sichtbaren Elemente der Auswahlliste
+ ///
+ public string Size
+ {
+ get => GetAttribute("size");
+ set => SetAttribute("size", value);
+ }
+
+ ///
+ /// Returns or sets the identification name of the form element to which it is associated.
+ ///
+ public string Form
+ {
+ get => GetAttribute("form");
+ set => SetAttribute("form", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob das Eingabefeld verwendet werden kann
+ ///
+ public bool Disabled
+ {
+ get => HasAttribute("disabled");
+ set { if (value) { SetAttribute("disabled"); } else { RemoveAttribute("disabled"); } }
+ }
+
+ ///
+ /// Returns or sets the OnChange attribute.
+ ///
+ public string OnChange
+ {
+ get => GetAttribute("onchange");
+ set => SetAttribute("onchange", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFieldSelect()
+ : base("select")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFieldSelect(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormDatalist.cs b/src/WebExpress/WebHtml/HtmlElementFormDatalist.cs
new file mode 100644
index 0000000..058e757
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormDatalist.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Sammlung vordefinierter Optionen für andere Kontrollelemente.
+ ///
+ public class HtmlElementFormDatalist : HtmlElement, IHtmlElementForm
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormDatalist()
+ : base("datalist")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormDatalist(string text)
+ : this()
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormDatalist(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormFieldset.cs b/src/WebExpress/WebHtml/HtmlElementFormFieldset.cs
new file mode 100644
index 0000000..8c2d024
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormFieldset.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Gruppe von Kontrollelementen.
+ ///
+ public class HtmlElementFormFieldset : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+
+ ///
+ /// Liefert oder setzt die Label-Eigenschaft
+ ///
+ public bool Disable
+ {
+ get => HasAttribute("disabled");
+ set { if (value) { SetAttribute("disabled"); } else { RemoveAttribute("disabled"); } }
+ }
+
+ ///
+ /// Returns or sets the identification name of the form element to which it is associated.
+ ///
+ public string Form
+ {
+ get => GetAttribute("form");
+ set => SetAttribute("form", value);
+ }
+
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormFieldset()
+ : base("fieldset")
+ {
+ CloseTag = false;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormFieldset(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormForm.cs b/src/WebExpress/WebHtml/HtmlElementFormForm.cs
new file mode 100644
index 0000000..f637d5c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormForm.cs
@@ -0,0 +1,109 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einFormular. Formulare bestehen typischerweise aus einer Reihe
+ /// von Kontrollelementen, deren Werte zur weiteren Verarbeitung an einen
+ /// Server übertragen werden.
+ ///
+ public class HtmlElementFormForm : HtmlElement, IHtmlElementForm
+ {
+ ///
+ /// Returns or sets the name of the form.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Zeichenkodierung
+ ///
+ public string AcceptCharset
+ {
+ get => GetAttribute("accept-charset");
+ set => SetAttribute("accept-charset", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Zeichenkodierung
+ ///
+ public TypeEnctype Enctype
+ {
+ get => TypeEnctypeExtensions.Convert(GetAttribute("enctype"));
+ set => SetAttribute("enctype", value.Convert());
+ }
+ ///
+ /// Liefert oder setzt den Methode Post oder get
+ ///
+ public string Method
+ {
+ get => GetAttribute("method");
+ set => SetAttribute("method", value);
+ }
+
+ ///
+ /// Liefert oder setzt die URL
+ ///
+ public string Action
+ {
+ get => GetAttribute("action");
+ set => SetAttribute("action", value);
+ }
+
+ ///
+ /// Liefert oder setzt das Zielfenster
+ ///
+ public string Target
+ {
+ get => GetAttribute("target");
+ set => SetAttribute("target", value);
+ }
+
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormForm()
+ : base("form")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormForm(string text)
+ : this()
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormForm(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormKeygen.cs b/src/WebExpress/WebHtml/HtmlElementFormKeygen.cs
new file mode 100644
index 0000000..80fad74
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormKeygen.cs
@@ -0,0 +1,39 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für ein Kontrollelement zur Erzeugung einesPaares aus öffentlichem und privaten Schlüssel und zum Versenden des öffentlichen Schlüssels.
+ ///
+ public class HtmlElementFormKeygen : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormKeygen()
+ : base("keygen")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormKeygen(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormMeter.cs b/src/WebExpress/WebHtml/HtmlElementFormMeter.cs
new file mode 100644
index 0000000..564ebef
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormMeter.cs
@@ -0,0 +1,102 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Messskala (oder deren Teilwerte) innerhalb eines bekannten Bereichs.
+ ///
+ public class HtmlElementFormMeter : HtmlElement, IHtmlElementForm
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join(string.Empty, Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Returns or sets the value.
+ ///
+ public string Value
+ {
+ get => GetAttribute("value");
+ set => SetAttribute("value", value);
+ }
+
+ ///
+ /// Liefert oder setzt die untere Grenze der Skala
+ ///
+ public string Min
+ {
+ get => GetAttribute("min");
+ set => SetAttribute("min", value);
+ }
+
+ ///
+ /// Liefert oder setzt die obere Grenze der Skala
+ ///
+ public string Max
+ {
+ get => GetAttribute("max");
+ set => SetAttribute("max", value);
+ }
+
+ ///
+ /// Liefert oder setzt die obere Grenze des "Niedrig"-Bereichs der Skala
+ ///
+ public string Low
+ {
+ get => GetAttribute("low");
+ set => SetAttribute("low", value);
+ }
+
+ ///
+ /// Liefert oder setzt die untere Grenze des "Hoch"-Bereichs der Skala
+ ///
+ public string High
+ {
+ get => GetAttribute("high");
+ set => SetAttribute("high", value);
+ }
+
+ ///
+ /// Liefert oder setzt den optimaler Wert der Skala
+ ///
+ public string Optimum
+ {
+ get => GetAttribute("optimum");
+ set => SetAttribute("optimum", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormMeter()
+ : base("meter")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormMeter(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormOptgroup.cs b/src/WebExpress/WebHtml/HtmlElementFormOptgroup.cs
new file mode 100644
index 0000000..2da7647
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormOptgroup.cs
@@ -0,0 +1,60 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Reihe logisch gruppierter Auswahloptionen.
+ ///
+ ///
+ public class HtmlElementFormOptgroup : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the label.
+ ///
+ public string Label
+ {
+ get => GetAttribute("label");
+ set => SetAttribute("label", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormOptgroup()
+ : base("optgroup")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormOptgroup(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormOption.cs b/src/WebExpress/WebHtml/HtmlElementFormOption.cs
new file mode 100644
index 0000000..7484cc9
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormOption.cs
@@ -0,0 +1,71 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Auswahloption innerhalb eines
+ public class HtmlElementFormOption : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Returns or sets a value.
+ ///
+ public string Value
+ {
+ get => GetAttribute("value");
+ set => SetAttribute("value", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob das Felf ausgewählt ist
+ ///
+ public bool Selected
+ {
+ get => HasAttribute("selected");
+ set { if (value) { SetAttribute("selected"); } else { RemoveAttribute("selected"); } }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormOption()
+ : base("option")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormOption(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormOutput.cs b/src/WebExpress/WebHtml/HtmlElementFormOutput.cs
new file mode 100644
index 0000000..917c00b
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormOutput.cs
@@ -0,0 +1,39 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert das Ergebnis einer Berechnung.
+ ///
+ public class HtmlElementFormOutput : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormOutput()
+ : base("output")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormOutput(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormProgress.cs b/src/WebExpress/WebHtml/HtmlElementFormProgress.cs
new file mode 100644
index 0000000..fcb2a89
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormProgress.cs
@@ -0,0 +1,75 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Ein Element zurFortschrittsanzeige einer bestimmten Aufgabe.
+ ///
+ public class HtmlElementFormProgress : HtmlElement, IHtmlElementForm
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Returns or sets the value.
+ ///
+ public string Value
+ {
+ get => GetAttribute("value");
+ set => SetAttribute("value", value);
+ }
+
+ ///
+ /// Liefert oder setzt die untere Grenze der Skala
+ ///
+ public string Min
+ {
+ get => GetAttribute("min");
+ set => SetAttribute("min", value);
+ }
+
+ ///
+ /// Liefert oder setzt die obere Grenze der Skala
+ ///
+ public string Max
+ {
+ get => GetAttribute("max");
+ set => SetAttribute("max", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormProgress()
+ : base("progress")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormProgress(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementFormTextarea.cs b/src/WebExpress/WebHtml/HtmlElementFormTextarea.cs
new file mode 100644
index 0000000..7f1f5d7
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementFormTextarea.cs
@@ -0,0 +1,149 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert ein Element für mehrzeilige Texteingaben.
+ ///
+ public class HtmlElementFormTextarea : HtmlElement, IHtmlFormularItem
+ {
+ ///
+ /// Returns or sets the name of the input field.
+ ///
+ public string Name
+ {
+ get => GetAttribute("name");
+ set => SetAttribute("name", value);
+ }
+
+ ///
+ /// Returns or sets the value. des Eingabefeldes
+ ///
+ public string Value
+ {
+ get => string.Join(string.Empty, Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt die Anzahl der anzegeigten Zeilen
+ ///
+ public string Rows
+ {
+ get => GetAttribute("rows");
+ set => SetAttribute("rows", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Anzahl der anzegeigten Spalten
+ ///
+ public string Cols
+ {
+ get => GetAttribute("cols");
+ set => SetAttribute("cols", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob The text. umgebrochen werden soll
+ /// Mögliche Werte sind: hard, soft
+ ///
+ public string Wrap
+ {
+ get => GetAttribute("wrap");
+ set => SetAttribute("wrap", value);
+ }
+
+ ///
+ /// Liefert oder setzt ob das Felf schreibgeschützt ist
+ ///
+ public string Readonly
+ {
+ get => GetAttribute("readonly");
+ set => SetAttribute("readonly", value);
+ }
+
+ ///
+ /// Returns or sets the minimum length.
+ ///
+ public string MinLength
+ {
+ get => GetAttribute("minlength");
+ set => SetAttribute("minlength", value);
+ }
+
+ ///
+ /// Returns or sets the maximum length.
+ ///
+ public string MaxLength
+ {
+ get => GetAttribute("maxlength");
+ set => SetAttribute("maxlength", value);
+ }
+
+ ///
+ /// Returns or sets whether inputs are enforced.
+ ///
+ public bool Required
+ {
+ get => HasAttribute("required");
+ set { if (value) { SetAttribute("required"); } else { RemoveAttribute("required"); } }
+ }
+
+ ///
+ /// Returns or sets a placeholder text.
+ ///
+ public string Placeholder
+ {
+ get => GetAttribute("placeholder");
+ set => SetAttribute("placeholder", value);
+ }
+
+ ///
+ /// Returns or sets a search pattern that checks the content.
+ ///
+ public string Pattern
+ {
+ get => GetAttribute("pattern");
+ set => SetAttribute("pattern", value);
+ }
+
+ ///
+ /// Returns or sets the identification name of the form element to which it is associated.
+ ///
+ public string Form
+ {
+ get => GetAttribute("form");
+ set => SetAttribute("form", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementFormTextarea()
+ : base("textarea")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementFormTextarea(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementInteractiveCommand.cs b/src/WebExpress/WebHtml/HtmlElementInteractiveCommand.cs
new file mode 100644
index 0000000..5951cf2
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementInteractiveCommand.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet einenBefehl, welcher vom Benutzer aufgerufen werden kann.
+ ///
+ public class HtmlElementInteractiveCommand : HtmlElement, IHtmlElementInteractive
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementInteractiveCommand()
+ : base("command")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveCommand(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveCommand(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementInteractiveDetails.cs b/src/WebExpress/WebHtml/HtmlElementInteractiveDetails.cs
new file mode 100644
index 0000000..f7c2bac
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementInteractiveDetails.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert ein Kontrollelement, mit dem der Benutzerzusätzliche Informationen oder Kontrolle erhalten kann.
+ ///
+ public class HtmlElementInteractiveDetails : HtmlElement, IHtmlElementInteractive
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementInteractiveDetails()
+ : base("details")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveDetails(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveDetails(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementInteractiveMenu.cs b/src/WebExpress/WebHtml/HtmlElementInteractiveMenu.cs
new file mode 100644
index 0000000..e0eb856
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementInteractiveMenu.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eineListe mit Befehlen.
+ ///
+ public class HtmlElementInteractiveMenu : HtmlElement, IHtmlElementInteractive
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementInteractiveMenu()
+ : base("menu")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveMenu(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveMenu(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementInteractiveSummary.cs b/src/WebExpress/WebHtml/HtmlElementInteractiveSummary.cs
new file mode 100644
index 0000000..b51dbc7
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementInteractiveSummary.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eineZusammenfassung oder eineLegende für ein bestimmte -Element.
+ ///
+ public class HtmlElementInteractiveSummary : HtmlElement, IHtmlElementInteractive
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementInteractiveSummary()
+ : base("summary")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveSummary(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementInteractiveSummary(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataBase.cs b/src/WebExpress/WebHtml/HtmlElementMetadataBase.cs
new file mode 100644
index 0000000..b477c36
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataBase.cs
@@ -0,0 +1,46 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Stellt die Basis für relative Verweise da.
+ ///
+ public class HtmlElementMetadataBase : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// Liefert oder setzt die Ziel-Url
+ ///
+ public string Href
+ {
+ get => GetAttribute("href");
+ set
+ {
+ var url = value;
+
+ if (!string.IsNullOrWhiteSpace(url) && !url.EndsWith("/"))
+ {
+ url += url + "/";
+ }
+
+ SetAttribute("href", url);
+ }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataBase()
+ : base("base")
+ {
+ CloseTag = false;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The uri.
+ public HtmlElementMetadataBase(string url)
+ : this()
+ {
+ Href = url;
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataHead.cs b/src/WebExpress/WebHtml/HtmlElementMetadataHead.cs
new file mode 100644
index 0000000..d617974
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataHead.cs
@@ -0,0 +1,216 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet eine Sammlung von Metadaten des Dokuments. Hierzu gehören auch Links zu oder Definitionen von Skripts und Stylesheets.
+ ///
+ public class HtmlElementMetadataHead : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// Returns or sets the title.
+ ///
+ public string Title
+ {
+ get => ElementTitle.Title;
+ set => ElementTitle.Title = value;
+ }
+
+ ///
+ /// Liefert oder setzt das TitelElement
+ ///
+ private HtmlElementMetadataTitle ElementTitle { get; set; }
+
+ ///
+ /// Returns or sets the title.
+ ///
+ public string Base
+ {
+ get => ElementBase.Href;
+ set => ElementBase.Href = value;
+ }
+
+ ///
+ /// Liefert oder setzt das TitelElement
+ ///
+ private HtmlElementMetadataBase ElementBase { get; set; }
+
+ ///
+ /// Liefert oder setzt das Favicon
+ ///
+ public IEnumerable Favicons
+ {
+ get => (from x in ElementFavicons select new Favicon(x.Href, x.Type)).ToList();
+ set
+ {
+ ElementFavicons.Clear();
+ ElementFavicons.AddRange
+ (
+ from x in value
+ select new HtmlElementMetadataLink()
+ {
+ Href = x.Url,
+ Rel = "icon",
+ Type = x.Mediatype != TypeFavicon.Default ? x.GetMediatyp() : ""
+ });
+ }
+ }
+
+ ///
+ /// Liefert oder setzt den Favicon-Link
+ ///
+ private List ElementFavicons { get; set; }
+
+ ///
+ /// Liefert oder setzt das internes Stylesheet
+ ///
+ public IEnumerable Styles
+ {
+ get => (from x in ElementStyles select x.Code).ToList();
+ set { ElementStyles.Clear(); ElementStyles.AddRange(from x in value select new HtmlElementMetadataStyle(x)); }
+ }
+
+ ///
+ /// Liefert oder setzt die Style-Elemente
+ ///
+ private List ElementStyles { get; set; }
+
+ ///
+ /// Liefert oder setzt die Scripte
+ ///
+ public IEnumerable Scripts
+ {
+ get => (from x in ElementScripts select x.Code).ToList();
+ set { ElementScripts.Clear(); ElementScripts.AddRange(from x in value select new HtmlElementScriptingScript(x)); }
+ }
+
+ ///
+ /// Liefert oder setzt die Script-Elemente
+ ///
+ private List ElementScripts { get; set; }
+
+ ///
+ /// Liefert oder setzt das text/javascript
+ ///
+ public IEnumerable ScriptLinks
+ {
+ get => (from x in ElementScriptLinks select x.Src).ToList();
+ set
+ {
+ ElementScriptLinks.Clear(); ElementScriptLinks.AddRange(from x in value
+ select new HtmlElementScriptingScript() { Language = "javascript", Src = x, Type = "text/javascript" });
+ }
+ }
+
+ ///
+ /// Liefert oder setzt die externen Scripts
+ ///
+ private List ElementScriptLinks { get; set; }
+
+ ///
+ /// Liefert oder setzt das internes Stylesheet
+ ///
+ public IEnumerable CssLinks
+ {
+ get => (from x in ElementCssLinks select x.Href).ToList();
+ set
+ {
+ ElementCssLinks.Clear(); ElementCssLinks.AddRange(from x in value
+ select new HtmlElementMetadataLink() { Rel = "stylesheet", Href = x, Type = "text/css" });
+ }
+ }
+
+ ///
+ /// Liefert oder setzt den Css-Link
+ ///
+ private List ElementCssLinks { get; set; }
+
+ ///
+ /// Liefert oder setzt die Metadaten
+ ///
+ public IEnumerable> Meta
+ {
+ get => (from x in ElementMeta select new KeyValuePair(x.Key, x.Value)).ToList();
+ set
+ {
+ ElementMeta.Clear(); ElementMeta.AddRange(from x in value
+ select new HtmlElementMetadataMeta(x.Key, x.Value));
+ }
+ }
+
+ ///
+ /// Liefert oder setzt die Metadaten-Elemente
+ ///
+ private List ElementMeta { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataHead()
+ : base("head")
+ {
+ ElementTitle = new HtmlElementMetadataTitle();
+ ElementBase = new HtmlElementMetadataBase();
+ ElementFavicons = new List();
+ ElementStyles = new List();
+ ElementScripts = new List();
+ ElementScriptLinks = new List();
+ ElementCssLinks = new List();
+ ElementMeta = new List();
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ ToPreString(builder, deep);
+
+ if (!string.IsNullOrWhiteSpace(Title))
+ {
+ ElementTitle.ToString(builder, deep + 1);
+ }
+
+ if (!string.IsNullOrWhiteSpace(Base))
+ {
+ //ElementBase.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementFavicons)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementStyles)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementScriptLinks)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementScripts)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementCssLinks)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementMeta)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ ToPostString(builder, deep, true);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataLink.cs b/src/WebExpress/WebHtml/HtmlElementMetadataLink.cs
new file mode 100644
index 0000000..005e954
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataLink.cs
@@ -0,0 +1,43 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Wird verwendet, um externe JavaScript- und CSS-Dateien in das aktuelle HTML-Dokument einzubinden.
+ ///
+ public class HtmlElementMetadataLink : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// Liefert oder setzt die Url
+ ///
+ public string Href
+ {
+ get => GetAttribute("href");
+ set => SetAttribute("href", value);
+ }
+
+ ///
+ /// Returns or sets the type.
+ ///
+ public string Rel
+ {
+ get => GetAttribute("rel");
+ set => SetAttribute("rel", value);
+ }
+
+ ///
+ /// Returns or sets the type.
+ ///
+ public string Type
+ {
+ get => GetAttribute("type");
+ set => SetAttribute("type", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataLink()
+ : base("link", false)
+ {
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataMeta.cs b/src/WebExpress/WebHtml/HtmlElementMetadataMeta.cs
new file mode 100644
index 0000000..1e9045e
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataMeta.cs
@@ -0,0 +1,70 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Wird für die Definition von Metadaten verwenden, die mit keinem anderen HTML-Element definiert werden können.
+ ///
+ public class HtmlElementMetadataMeta : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// Liefert oder setzt den Attributnamen
+ ///
+ public string Key { get; set; }
+
+ ///
+ /// Returns or sets the value.
+ ///
+ public string Value
+ {
+ get => GetAttribute(Key);
+ set => SetAttribute(Key, value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataMeta()
+ : base("meta")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataMeta(string key)
+ : this()
+ {
+ Key = key;
+ SetAttribute(Key, "");
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataMeta(string key, string value)
+ : this()
+ {
+ Key = key;
+ SetAttribute(Key, value);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ builder.AppendLine();
+ builder.Append(string.Empty.PadRight(deep));
+ builder.Append("<");
+ builder.Append(ElementName);
+ builder.Append(" ");
+ builder.Append(Key);
+ builder.Append("='");
+ builder.Append(Value);
+ builder.Append("'>");
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataStyle.cs b/src/WebExpress/WebHtml/HtmlElementMetadataStyle.cs
new file mode 100644
index 0000000..3e64576
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataStyle.cs
@@ -0,0 +1,59 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definition eines internen CSS-Stylesheets.
+ ///
+ public class HtmlElementMetadataStyle : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataStyle()
+ : base("style")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The text.
+ public HtmlElementMetadataStyle(string code)
+ : this()
+ {
+ Code = code;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(string.Empty.PadRight(deep));
+ builder.Append("<");
+ builder.Append(ElementName);
+ builder.Append(">");
+
+ if (!string.IsNullOrWhiteSpace(Code))
+ {
+ builder.Append("\n");
+ builder.Append(Code);
+ builder.Append("\n");
+ }
+ builder.Append(string.Empty.PadRight(deep));
+ builder.Append("");
+ builder.Append(ElementName);
+ builder.Append(">");
+ builder.Append("\n");
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMetadataTitle.cs b/src/WebExpress/WebHtml/HtmlElementMetadataTitle.cs
new file mode 100644
index 0000000..2b6ce3f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMetadataTitle.cs
@@ -0,0 +1,55 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Defines the title of a document that appears in the browser's title bar in the
+ /// tab of that page. May contain text only. Any tags contained are not interpreted.
+ ///
+ public class HtmlElementMetadataTitle : HtmlElement, IHtmlElementMetadata
+ {
+ ///
+ /// The title.
+ ///
+ public string Title { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMetadataTitle()
+ : base("title")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The title.
+ public HtmlElementMetadataTitle(string title)
+ : this()
+ {
+ Title = title;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ builder.AppendLine();
+ builder.Append(string.Empty.PadRight(deep));
+ builder.Append("<");
+ builder.Append(ElementName);
+ builder.Append(">");
+
+ builder.Append(Title);
+
+ builder.Append("");
+ builder.Append(ElementName);
+ builder.Append(">");
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaArea.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaArea.cs
new file mode 100644
index 0000000..cffdb0b
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaArea.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert in Verbindung mit dem
+ public class HtmlElementMultimediaArea : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaArea()
+ : base("area", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaAudio.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaAudio.cs
new file mode 100644
index 0000000..2291d34
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaAudio.cs
@@ -0,0 +1,26 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine Tondatei oder einen Audiostream.
+ ///
+ public class HtmlElementMultimediaAudio : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Liefert oder setzt die Audio-Url
+ ///
+ public string Src
+ {
+ get => GetAttribute("src");
+ set => SetAttribute("src", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaAudio()
+ : base("audio", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaImg.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaImg.cs
new file mode 100644
index 0000000..4e02770
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaImg.cs
@@ -0,0 +1,73 @@
+using System;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für ein Bild.
+ ///
+ public class HtmlElementMultimediaImg : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Liefert oder setzt den alternativen Text, wenn das Bild nicht angezeigt werden kann
+ ///
+ public string Alt
+ {
+ get => GetAttribute("alt");
+ set => SetAttribute("alt", value);
+ }
+
+ ///
+ /// Returns or sets the tooltip.
+ ///
+ public string Title
+ {
+ get => GetAttribute("title");
+ set => SetAttribute("title", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Bild-Url
+ ///
+ public string Src
+ {
+ get => GetAttribute("src");
+ set => SetAttribute("src", value);
+ }
+
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Width
+ {
+ get => Convert.ToInt32(GetAttribute("width"));
+ set => SetAttribute("width", value.ToString());
+ }
+
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Height
+ {
+ get => Convert.ToInt32(GetAttribute("height"));
+ set => SetAttribute("height", value.ToString());
+ }
+
+ ///
+ /// Liefert oder setzt das Ziel
+ ///
+ public string Target
+ {
+ get => GetAttribute("target");
+ set => SetAttribute("target", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaImg()
+ : base("img", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaMap.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaMap.cs
new file mode 100644
index 0000000..ea85d91
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaMap.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert in Verbindung mit dem -Element eine Image Map.
+ ///
+ public class HtmlElementMultimediaMap : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaMap()
+ : base("map", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaMath.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaMath.cs
new file mode 100644
index 0000000..5784196
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaMath.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine mathematische Formel.
+ ///
+ public class HtmlElementMultimediaMath : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaMath()
+ : base("math")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementMultimediaMath(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementMultimediaMath(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaSvg.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaSvg.cs
new file mode 100644
index 0000000..67ef171
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaSvg.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert eine eingebettete Vektorgrafik.
+ ///
+ public class HtmlElementMultimediaSvg : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Width
+ {
+ get => Convert.ToInt32(GetAttribute("width"));
+ set => SetAttribute("width", value.ToString());
+ }
+
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Height
+ {
+ get => Convert.ToInt32(GetAttribute("height"));
+ set => SetAttribute("height", value.ToString());
+ }
+
+ ///
+ /// Liefert oder setzt das Ziel
+ ///
+ public string Target
+ {
+ get => GetAttribute("target");
+ set => SetAttribute("target", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaSvg()
+ : base("svg")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementMultimediaSvg(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementMultimediaSvg(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaTrack.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaTrack.cs
new file mode 100644
index 0000000..5cdd82c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaTrack.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Hiermit können zusätzliche Medienspuren (z.B. Untertitel) für Elemente wie
+ public class HtmlElementMultimediaTrack : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaTrack()
+ : base("track", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementMultimediaVideo.cs b/src/WebExpress/WebHtml/HtmlElementMultimediaVideo.cs
new file mode 100644
index 0000000..774d7f5
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementMultimediaVideo.cs
@@ -0,0 +1,26 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Videodatei und die dazugehörigen Audiodateien, sowie die für das Abspielen nötigen Kontrollelemente.
+ ///
+ public class HtmlElementMultimediaVideo : HtmlElement, IHtmlElementMultimedia
+ {
+ ///
+ /// Liefert oder setzt die Video-Url
+ ///
+ public string Src
+ {
+ get => GetAttribute("src");
+ set => SetAttribute("src", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementMultimediaVideo()
+ : base("video", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementRootHtml.cs b/src/WebExpress/WebHtml/HtmlElementRootHtml.cs
new file mode 100644
index 0000000..d3549eb
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementRootHtml.cs
@@ -0,0 +1,64 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für den Wurzelknoten eines HTML- oder XHTML-Dokuments. Alle weiteren Elemente müssen Nachkommen dieses Elements sein.
+ ///
+ public class HtmlElementRootHtml : HtmlElement, IHtmlElementRoot
+ {
+ ///
+ /// Liefert oder setzt den Kopf
+ ///
+ public HtmlElementMetadataHead Head { get; private set; }
+
+ ///
+ /// Liefert oder setzt den Body
+ ///
+ public HtmlElementSectionBody Body { get; private set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementRootHtml()
+ : base("html")
+ {
+ Head = new HtmlElementMetadataHead();
+ Body = new HtmlElementSectionBody();
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append("<");
+ builder.Append(ElementName);
+ builder.Append(">");
+
+ Head.ToString(builder, deep + 1);
+ Body.ToString(builder, deep + 1);
+
+ builder.AppendLine();
+ builder.Append("");
+ builder.Append(ElementName);
+ builder.Append(">");
+ builder.Append("\n");
+ }
+
+ ///
+ /// In String konvertieren
+ ///
+ /// Das Objekt als String
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ builder.AppendLine("");
+ ToString(builder, 0);
+
+ return builder.ToString();
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementScriptingCanvas.cs b/src/WebExpress/WebHtml/HtmlElementScriptingCanvas.cs
new file mode 100644
index 0000000..6f3c47a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementScriptingCanvas.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Bitmap-Bereich, der von Skripts verwendet werden kann, um beispielsweise Diagramme, Spielegraphiken oder andere visuellen Effekte dynamisch darzustellen.
+ ///
+ public class HtmlElementScriptingCanvas : HtmlElement, IHtmlElementScripting
+ {
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Width
+ {
+ get => Convert.ToInt32(GetAttribute("width"));
+ set => SetAttribute("width", value.ToString());
+ }
+
+ ///
+ /// Returns or sets the width.
+ ///
+ public int Height
+ {
+ get => Convert.ToInt32(GetAttribute("height"));
+ set => SetAttribute("height", value.ToString());
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementScriptingCanvas()
+ : base("canvas", false)
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementScriptingNoscript.cs b/src/WebExpress/WebHtml/HtmlElementScriptingNoscript.cs
new file mode 100644
index 0000000..d6f05c5
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementScriptingNoscript.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert alternative Inhalte, die angezeigt werden sollen, wenn der Browser kein Skripting unterstützt.
+ ///
+ public class HtmlElementScriptingNoscript : HtmlElement, IHtmlElementScripting
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementScriptingNoscript()
+ : base("span")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementScriptingNoscript(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementScriptingNoscript(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementScriptingScript.cs b/src/WebExpress/WebHtml/HtmlElementScriptingScript.cs
new file mode 100644
index 0000000..fdc91f7
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementScriptingScript.cs
@@ -0,0 +1,82 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert entweder ein internes Skript oder einen Link auf ein externes Skript. Als Programmiersprache wird JavaScript verwendet.
+ ///
+ public class HtmlElementScriptingScript : HtmlElement, IHtmlElementScripting
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// Liefert oder setzt die Scriptsprache
+ ///
+ public string Language
+ {
+ get => GetAttribute("language");
+ set => SetAttribute("language", value);
+ }
+
+ ///
+ /// Liefert oder setzt den Medientyp
+ ///
+ public string Type
+ {
+ get => GetAttribute("type");
+ set => SetAttribute("type", value);
+ }
+
+ ///
+ /// Liefert oder setzt den Link auf die Scriptdatei
+ ///
+ public string Src
+ {
+ get => GetAttribute("src");
+ set => SetAttribute("src", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementScriptingScript()
+ : base("script")
+ {
+ Type = "text/javascript";
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The text.
+ public HtmlElementScriptingScript(string code)
+ : this()
+ {
+ Code = code;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ ToPreString(builder, deep);
+
+ if (!string.IsNullOrWhiteSpace(Code))
+ {
+#if DEBUG
+ builder.Append(Code);
+#else
+ builder.Append(Code.Replace("\r", "").Replace("\n", ""));
+#endif
+ }
+
+ ToPostString(builder, deep, false);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionAddress.cs b/src/WebExpress/WebHtml/HtmlElementSectionAddress.cs
new file mode 100644
index 0000000..3be06f3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionAddress.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert einen Abschnitt mit Kontaktinformationen.
+ ///
+ public class HtmlElementSectionAddress : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionAddress()
+ : base("address")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionAddress(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionAddress(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionArticle.cs b/src/WebExpress/WebHtml/HtmlElementSectionArticle.cs
new file mode 100644
index 0000000..49f3ad4
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionArticle.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eigenständigen Inhalt, der unabhängig von den übrigen Inhalten sein kann.
+ ///
+ public class HtmlElementSectionArticle : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionArticle()
+ : base("article")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionArticle(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionArticle(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionAside.cs b/src/WebExpress/WebHtml/HtmlElementSectionAside.cs
new file mode 100644
index 0000000..dcdf0b3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionAside.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Randbemerkung. Der übrige Inhalt sollte auch verständlich sein, wenn dieses Element entfernt wird.
+ ///
+ public class HtmlElementSectionAside : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionAside()
+ : base("aside")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionAside(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionAside(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionBody.cs b/src/WebExpress/WebHtml/HtmlElementSectionBody.cs
new file mode 100644
index 0000000..dc18d99
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionBody.cs
@@ -0,0 +1,92 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für den Hauptinhalt eines HTML-Dokuments. Jedes Dokument kann nur ein -Element enthalten.
+ ///
+ public class HtmlElementSectionBody : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Liefert oder setzt die Script-Elemente
+ ///
+ public List Scripts { get; set; }
+
+ ///
+ /// Liefert oder setzt das text/javascript
+ ///
+ public List ScriptLinks
+ {
+ get => (from x in ElementScriptLinks select x.Src).ToList();
+ set
+ {
+ ElementScriptLinks.Clear();
+ ElementScriptLinks.AddRange(from x in value
+ select new HtmlElementScriptingScript()
+ {
+ Language = "javascript",
+ Src = x,
+ Type = "text/javascript"
+ });
+ }
+ }
+
+ ///
+ /// Liefert oder setzt die externen Scripts
+ ///
+ private List ElementScriptLinks { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionBody()
+ : base("body")
+ {
+ ElementScriptLinks = new List();
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionBody(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ ToPreString(builder, deep);
+
+ foreach (var v in Elements.Where(x => x != null))
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var v in ElementScriptLinks)
+ {
+ v.ToString(builder, deep + 1);
+ }
+
+ foreach (var script in Scripts)
+ {
+ new HtmlElementScriptingScript(script).ToString(builder, deep + 1);
+ }
+
+ ToPostString(builder, deep, true);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionFooter.cs b/src/WebExpress/WebHtml/HtmlElementSectionFooter.cs
new file mode 100644
index 0000000..aadc1dc
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionFooter.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert den Fußteil einer Seite oder eines Abschnitts. Er enthält oft Copyright-Hinweise, einen Link auf das Impressum oder Kontaktadressen.
+ ///
+ public class HtmlElementSectionFooter : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionFooter()
+ : base("footer")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionFooter(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionFooter(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionFooter(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH1.cs b/src/WebExpress/WebHtml/HtmlElementSectionH1.cs
new file mode 100644
index 0000000..816c3ae
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH1.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine Überschrift der obersten Ebene
+ ///
+ public class HtmlElementSectionH1 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH1()
+ : base("h1")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH1(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH1(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH2.cs b/src/WebExpress/WebHtml/HtmlElementSectionH2.cs
new file mode 100644
index 0000000..ec480df
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH2.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eine Überschrift der zweiten Ebene
+ ///
+ public class HtmlElementSectionH2 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH2()
+ : base("h2")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH2(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH2(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH3.cs b/src/WebExpress/WebHtml/HtmlElementSectionH3.cs
new file mode 100644
index 0000000..294d8dd
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH3.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eine Überschrift der dritten Ebene
+ ///
+ public class HtmlElementSectionH3 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH3()
+ : base("h3")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH3(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH3(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH4.cs b/src/WebExpress/WebHtml/HtmlElementSectionH4.cs
new file mode 100644
index 0000000..981653a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH4.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eine Überschrift der vierten Ebene
+ ///
+ public class HtmlElementSectionH4 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH4()
+ : base("h4")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH4(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH4(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH5.cs b/src/WebExpress/WebHtml/HtmlElementSectionH5.cs
new file mode 100644
index 0000000..09c7986
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH5.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eine Überschrift der fünften Ebene
+ ///
+ public class HtmlElementSectionH5 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH5()
+ : base("h5")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH5(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH5(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionH6.cs b/src/WebExpress/WebHtml/HtmlElementSectionH6.cs
new file mode 100644
index 0000000..b215ceb
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionH6.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt eine Überschrift der untersten Ebene
+ ///
+ public class HtmlElementSectionH6 : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionH6()
+ : base("h6")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH6(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionH6(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionHeader.cs b/src/WebExpress/WebHtml/HtmlElementSectionHeader.cs
new file mode 100644
index 0000000..1517cc3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionHeader.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert den Kopfteil einer Seite oder eines Abschnitts. Er enthält oft ein Logo, den Titel der Website und die Seitennavigation.
+ ///
+ public class HtmlElementSectionHeader : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionHeader()
+ : base("header")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionHeader(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionHeader(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionMain.cs b/src/WebExpress/WebHtml/HtmlElementSectionMain.cs
new file mode 100644
index 0000000..df75678
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionMain.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Definiert den Hauptinhalt der Seite. Es ist nur ein Element pro Seite zulässig.
+ ///
+ public class HtmlElementSectionMain : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionMain()
+ : base("main")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionMain(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionMain(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionNav.cs b/src/WebExpress/WebHtml/HtmlElementSectionNav.cs
new file mode 100644
index 0000000..067b26b
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionNav.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Das Element nav beschreibt eine Aufzählungsliste von Navigationslinks.
+ ///
+ public class HtmlElementSectionNav : HtmlElement
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionNav()
+ : base("nav")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionNav(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionNav(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementSectionSection.cs b/src/WebExpress/WebHtml/HtmlElementSectionSection.cs
new file mode 100644
index 0000000..d89825f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementSectionSection.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Beschreibt einen Abschnitt eines Dokuments.
+ ///
+ public class HtmlElementSectionSection : HtmlElement, IHtmlElementSection
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementSectionSection()
+ : base("section")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionSection(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementSectionSection(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableCaption.cs b/src/WebExpress/WebHtml/HtmlElementTableCaption.cs
new file mode 100644
index 0000000..12e066c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableCaption.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet die Beschriftung (Titel) einer Tabelle.
+ ///
+ public class HtmlElementTableCaption : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableCaption()
+ : base("caption")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableCaption(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableCaption(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableCol.cs b/src/WebExpress/WebHtml/HtmlElementTableCol.cs
new file mode 100644
index 0000000..d706e70
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableCol.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Tabellenspalte.
+ ///
+ public class HtmlElementTableCol : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableCol()
+ : base("col")
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableColgroup.cs b/src/WebExpress/WebHtml/HtmlElementTableColgroup.cs
new file mode 100644
index 0000000..bf43af3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableColgroup.cs
@@ -0,0 +1,17 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Gruppe aus einer oder mehreren Tabellenspalten.
+ ///
+ public class HtmlElementTableColgroup : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableColgroup()
+ : base("colgroup")
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTable.cs b/src/WebExpress/WebHtml/HtmlElementTableTable.cs
new file mode 100644
index 0000000..98ecca4
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTable.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine Tabelle, d.h. Daten mit mehr als einer Dimension.
+ ///
+ public class HtmlElementTableTable : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Liefert oder setzt die Spalten
+ ///
+ public HtmlElementTableTr Columns { get; set; }
+
+ ///
+ /// Liefert oder setzt die Zeilen
+ ///
+ public List Rows { get; private set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTable()
+ : base("table")
+ {
+ Columns = new HtmlElementTableTr();
+ Rows = new List();
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ ToPreString(builder, deep);
+
+ var column = new HtmlElementTableThead(Columns);
+ column.ToString(builder, deep + 1);
+
+ var body = new HtmlElementTableTbody(Rows);
+ body.ToString(builder, deep + 1);
+
+ ToPostString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTbody.cs b/src/WebExpress/WebHtml/HtmlElementTableTbody.cs
new file mode 100644
index 0000000..e5e976f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTbody.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für die Spalten, die die eigentlichen Daten einer Tabelle enthalten.
+ ///
+ public class HtmlElementTableTbody : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTbody()
+ : base("tbody")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTbody(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTbody(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTd.cs b/src/WebExpress/WebHtml/HtmlElementTableTd.cs
new file mode 100644
index 0000000..668ea22
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTd.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eine einzelne Tabellenzelle.
+ ///
+ public class HtmlElementTableTd : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTd()
+ : base("td")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTd(IHtmlNode node)
+ : this()
+ {
+ Elements.Add(node);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTd(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTd(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTfoot.cs b/src/WebExpress/WebHtml/HtmlElementTableTfoot.cs
new file mode 100644
index 0000000..2100abe
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTfoot.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert die Gruppe der Tabellenzeilen, die die Zusammenfassungen der Tabellenspalten enthalten.
+ ///
+ public class HtmlElementTableTfoot : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTfoot()
+ : base("tfoot")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTfoot(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTfoot(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTh.cs b/src/WebExpress/WebHtml/HtmlElementTableTh.cs
new file mode 100644
index 0000000..85d1869
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTh.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eine Tabellenzelle mit einer Beschriftung.
+ ///
+ public class HtmlElementTableTh : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTh()
+ : base("th")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTh(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTh(List nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableThead.cs b/src/WebExpress/WebHtml/HtmlElementTableThead.cs
new file mode 100644
index 0000000..ee922f4
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableThead.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert die Gruppe der Tabellenzeilen, die die Beschriftungen der Tabellenspalten enthalten.
+ ///
+ public class HtmlElementTableThead : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableThead()
+ : base("thead")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableThead(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableThead(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTableTr.cs b/src/WebExpress/WebHtml/HtmlElementTableTr.cs
new file mode 100644
index 0000000..2fcce9a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTableTr.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Zeile mit Tabellenzellen.
+ ///
+ public class HtmlElementTableTr : HtmlElement, IHtmlElementTable
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTableTr()
+ : base("tr")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTr(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTableTr(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentBlockquote.cs b/src/WebExpress/WebHtml/HtmlElementTextContentBlockquote.cs
new file mode 100644
index 0000000..8a8b483
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentBlockquote.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert ein Zitat.
+ ///
+ public class HtmlElementTextContentBlockquote : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentBlockquote()
+ : base("blockquote")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentBlockquote(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentBlockquote(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentDd.cs b/src/WebExpress/WebHtml/HtmlElementTextContentDd.cs
new file mode 100644
index 0000000..73a8a15
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentDd.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert die Definition des oder der Begriffe, die in den direkt vorangehenden -Element angegeben wurden.
+ ///
+ public class HtmlElementTextContentDd : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentDd()
+ : base("dd")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDd(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDd(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentDiv.cs b/src/WebExpress/WebHtml/HtmlElementTextContentDiv.cs
new file mode 100644
index 0000000..17484cb
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentDiv.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet ein allgemeines Container-Element ohne spezielle semantische Bedeutung.
+ ///
+ public class HtmlElementTextContentDiv : HtmlElement
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentDiv()
+ : base("div")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDiv(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDiv(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentDl.cs b/src/WebExpress/WebHtml/HtmlElementTextContentDl.cs
new file mode 100644
index 0000000..f72ab6f
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentDl.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eine Definitionsliste aus Begriffen und den dazugehörigen Definitionen.
+ ///
+ public class HtmlElementTextContentDl : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentDl()
+ : base("dl")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDl(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDl(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentDt.cs b/src/WebExpress/WebHtml/HtmlElementTextContentDt.cs
new file mode 100644
index 0000000..bf72e71
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentDt.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet einen Begriff der im folgenden -Element beschrieben wird.
+ ///
+ public class HtmlElementTextContentDt : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentDt()
+ : base("dt")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDt(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentDt(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentFigcaption.cs b/src/WebExpress/WebHtml/HtmlElementTextContentFigcaption.cs
new file mode 100644
index 0000000..97c4d2c
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentFigcaption.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert die Beschriftung einer Abbildung.
+ ///
+ public class HtmlElementTextContentFigcaption : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentFigcaption()
+ : base("figcaption")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentFigcaption(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentFigcaption(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentFigure.cs b/src/WebExpress/WebHtml/HtmlElementTextContentFigure.cs
new file mode 100644
index 0000000..3a245fa
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentFigure.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet eine Abbildung, die einen Teil des Dokuments illustriert.
+ ///
+ public class HtmlElementTextContentFigure : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentFigure()
+ : base("figure")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentFigure(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentFigure(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentHr.cs b/src/WebExpress/WebHtml/HtmlElementTextContentHr.cs
new file mode 100644
index 0000000..cfbb4e3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentHr.cs
@@ -0,0 +1,29 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet einen thematischen Bruch zwischen Absätzen eines Abschnitts, Artikels oder anderem längeren Inhalt.
+ ///
+ public class HtmlElementTextContentHr : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentHr()
+ : base("hr", false)
+ {
+
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentLi.cs b/src/WebExpress/WebHtml/HtmlElementTextContentLi.cs
new file mode 100644
index 0000000..75caa0d
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentLi.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Das Element li beschreibt ein Element einer ungeordneten oder geordneten Liste
+ ///
+ public class HtmlElementTextContentLi : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentLi()
+ : base("li")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentLi(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentLi(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentOl.cs b/src/WebExpress/WebHtml/HtmlElementTextContentOl.cs
new file mode 100644
index 0000000..e076a4d
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentOl.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Das Element ul beschreibt eine Aufzählungsliste, also eine Liste, bei der die Reihenfolge der Elemente eine Rolle spielt.
+ /// ol steht dabei für ordered list, geordnete, sortierte Liste.
+ ///
+ public class HtmlElementTextContentOl : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentOl()
+ : base("ol")
+ {
+ Elements = new List();
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentOl(params HtmlElementTextContentLi[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.Elements.Clear();
+ base.Elements.AddRange(Elements);
+
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentP.cs b/src/WebExpress/WebHtml/HtmlElementTextContentP.cs
new file mode 100644
index 0000000..e7fa8a6
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentP.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert den Inhalt als Absatz.
+ ///
+ public class HtmlElementTextContentP : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentP()
+ : base("p")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentP(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentP(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentPre.cs b/src/WebExpress/WebHtml/HtmlElementTextContentPre.cs
new file mode 100644
index 0000000..0c9704a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentPre.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert den Inhalt dieses Elements als vorformatiert und das dieses Format erhalten bleiben soll.
+ ///
+ public class HtmlElementTextContentPre : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentPre()
+ : base("pre")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentPre(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentPre(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextContentUl.cs b/src/WebExpress/WebHtml/HtmlElementTextContentUl.cs
new file mode 100644
index 0000000..5ace8d8
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextContentUl.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Das Element ul beschreibt eine Aufzählungsliste, also eine Liste, bei der die Reihenfolge der Elemente nur eine
+ /// untergeordnete oder keine Rolle spielt. ul steht dabei für unordered list, ungeordnete, unsortierte Liste.
+ ///
+ public class HtmlElementTextContentUl : HtmlElement, IHtmlElementTextContent
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextContentUl()
+ : base("ul")
+ {
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentUl(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextContentUl(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsA.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsA.cs
new file mode 100644
index 0000000..0cade4a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsA.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// ezeichnet einen Hyperlink, welcher auf eine andere Ressource verweist.
+ ///
+ public class HtmlElementTextSemanticsA : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt den alternativen Text
+ ///
+ public string Alt
+ {
+ get => GetAttribute("alt");
+ set => SetAttribute("alt", value);
+ }
+
+ ///
+ /// Returns or sets the tooltip.
+ ///
+ public string Title
+ {
+ get => GetAttribute("title");
+ set => SetAttribute("title", value);
+ }
+
+ ///
+ /// Liefert oder setzt die Ziel-Url
+ ///
+ public string Href
+ {
+ get => GetAttribute("href");
+ set => SetAttribute("href", value);
+ }
+
+ ///
+ /// Liefert oder setzt das Ziel
+ ///
+ public TypeTarget Target
+ {
+ get => (TypeTarget)Enum.Parse(typeof(TypeTarget), GetAttribute("target"));
+ set => SetAttribute("target", value.ToStringValue());
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsA()
+ : base("a")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsA(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsA(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsA(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsAbbr.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsAbbr.cs
new file mode 100644
index 0000000..1447fc3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsAbbr.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine Abkürzung oder ein Akronym.
+ ///
+ public class HtmlElementTextSemanticsAbbr : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsAbbr()
+ : base("abbr")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsAbbr(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsAbbr(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsB.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsB.cs
new file mode 100644
index 0000000..c78a972
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsB.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise fettgedruckt dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies kann beispielsweise ein Schlüsselwort oder ein Produktname in einer Produktbewertung sein.
+ ///
+ public class HtmlElementTextSemanticsB : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsB()
+ : base("b")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsB(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsB(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdi.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdi.cs
new file mode 100644
index 0000000..f609078
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdi.cs
@@ -0,0 +1,68 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert Text, der vom umgebenden Inhalt zum Zweck der bidirektionalen Formatierung isoliert werden soll. Hiermit kann ein Textabschnitt mit einer unterschiedlichen oder unbekannten Textrichtung gekennzeichnet werden.
+ ///
+ public class HtmlElementTextSemanticsBdi : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt die Schreibrichtung
+ ///
+ public string Dir
+ {
+ get => GetAttribute("dir");
+ set => SetAttribute("dir", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsBdi()
+ : base("bdi")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsBdi(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsBdi(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdo.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdo.cs
new file mode 100644
index 0000000..a7d4810
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBdo.cs
@@ -0,0 +1,68 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kann verwendet werden, um die Textrichtung der enthaltenen Kindelemente zu steuern. Hiermit kann der Unicode BiDi-Algorithmus explizit überschrieben werden.
+ ///
+ public class HtmlElementTextSemanticsBdo : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Liefert oder setzt die Schreibrichtung
+ ///
+ public string Dir
+ {
+ get => GetAttribute("dir");
+ set => SetAttribute("dir", value);
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsBdo()
+ : base("bdo")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsBdo(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsBdo(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsBr.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBr.cs
new file mode 100644
index 0000000..58af098
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsBr.cs
@@ -0,0 +1,16 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet einen Zeilenumbruch.
+ ///
+ public class HtmlElementTextSemanticsBr : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsBr()
+ : base("br", false)
+ {
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsCite.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsCite.cs
new file mode 100644
index 0000000..5d94043
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsCite.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert den Titel eines Werks.
+ ///
+ public class HtmlElementTextSemanticsCite : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsCite()
+ : base("cite")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsCite(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsCite(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsCite(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsCode.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsCode.cs
new file mode 100644
index 0000000..df87492
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsCode.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert ein Programmiercode.
+ ///
+ public class HtmlElementTextSemanticsCode : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsCode()
+ : base("code")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsCode(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsCode(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsData.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsData.cs
new file mode 100644
index 0000000..ec4101a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsData.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Verbindet seinen Inhalt mit einem maschinenlesbaren Equivalent, angegeben im value-Attribut. (Dieses Element wird nur in der WHATWG-Version des HTML-Standards definiert, nicht aber in der W3C-Version von HTML5).
+ ///
+ public class HtmlElementTextSemanticsData : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Returns or sets the value.
+ ///
+ public string Value
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsData()
+ : base("data")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsData(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsData(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsDfn.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsDfn.cs
new file mode 100644
index 0000000..5d6591b
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsDfn.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Begriff, dessen Definition im nächstgelegenen Nachkommen-Element enthalten ist.
+ ///
+ public class HtmlElementTextSemanticsDfn : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsDfn()
+ : base("dfn")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsDfn(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsDfn(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsEm.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsEm.cs
new file mode 100644
index 0000000..c8aa749
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsEm.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen hervorgehobenen Text.
+ ///
+ public class HtmlElementTextSemanticsEm : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsEm()
+ : base("em")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsEm(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsEm(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsI.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsI.cs
new file mode 100644
index 0000000..b6c39c7
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsI.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise kursiv dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies kann beispielsweise eine taxonomische Bezeichnung, ein technischer Begriff, ein idiomatischer Ausdruck, ein Gedanke oder der Name eines Schiffes sein.
+ ///
+ public class HtmlElementTextSemanticsI : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsI()
+ : base("i")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsI(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsI(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsKdb.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsKdb.cs
new file mode 100644
index 0000000..eb6d201
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsKdb.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert eine Benutzereingabe, oftmals, aber nicht unbedingt, auf der Tastatur. Kann auch für andere Eingaben, beispielsweise transkribierte Sprachbefehle stehen.
+ ///
+ public class HtmlElementTextSemanticsKdb : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsKdb()
+ : base("kdb")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsKdb(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsKdb(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsMark.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsMark.cs
new file mode 100644
index 0000000..088e235
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsMark.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für Text, der aus Referenzgründen hervorgehoben wird, d.h. der in anderem Kontext von Bedeutung ist.
+ ///
+ public class HtmlElementTextSemanticsMark : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsMark()
+ : base("mark")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsMark(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsMark(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsQ.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsQ.cs
new file mode 100644
index 0000000..ccd64f6
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsQ.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet ein Kurzzitat. Für längere Zitate sollte verwendet werden.
+ ///
+ public class HtmlElementTextSemanticsQ : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsQ()
+ : base("q")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsQ(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsQ(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsRp.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRp.cs
new file mode 100644
index 0000000..28aee5b
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRp.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Wird zusammen mit dem Element verwendet, um Ruby-Text mit Klammern zu umgeben, die angezeigt werden, wenn das Benutzerprogramm (Browser) keine Ruby-Annotationen unterstützt.
+ ///
+ public class HtmlElementTextSemanticsRp : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsRp()
+ : base("rp")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRp(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRp(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsRt.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRt.cs
new file mode 100644
index 0000000..fea7c14
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRt.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet den Text einer Ruby-Annotation.
+ ///
+ public class HtmlElementTextSemanticsRt : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsRt()
+ : base("rt")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRt(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRt(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsRuby.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRuby.cs
new file mode 100644
index 0000000..05e290a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsRuby.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Bezeichnet einen Textteil mit Ruby-Annotationen. Dies sind kurze Aussprachetipps und andere Hinweise, die hauptsächlich für ostasiatische Typografie verwendet werden.
+ ///
+ public class HtmlElementTextSemanticsRuby : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsRuby()
+ : base("ruby")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRuby(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsRuby(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsS.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsS.cs
new file mode 100644
index 0000000..ea40c09
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsS.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Wird für Inhalte verwendet, dienicht länger relevant oder akkurat sind. Wird meist durchgestrichen dargestellt.
+ ///
+ public class HtmlElementTextSemanticsS : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsS()
+ : base("s")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsS(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsS(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsSamp.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSamp.cs
new file mode 100644
index 0000000..be44723
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSamp.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert die Ausgabe eines Programms oder eines Computers.
+ ///
+ public class HtmlElementTextSemanticsSamp : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsSamp()
+ : base("samp")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSamp(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSamp(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsSmall.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSmall.cs
new file mode 100644
index 0000000..611ffb6
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSmall.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für das "Kleingedruckte" eines Dokuments, wie Ausschlussklauseln, Copyright-Hinweise oder andere Dinge, die für das Verständnis des Dokuments nicht unbedingt nötig sind.
+ ///
+ public class HtmlElementTextSemanticsSmall : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsSmall()
+ : base("small")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSmall(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSmall(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsSpan.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSpan.cs
new file mode 100644
index 0000000..0a30831
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSpan.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen allgemeinen Textabschnitt.
+ ///
+ public class HtmlElementTextSemanticsSpan : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsSpan()
+ : base("span")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSpan(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSpan(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsStrong.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsStrong.cs
new file mode 100644
index 0000000..8569bb3
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsStrong.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen besonders wichtigen (stark hervorgehobenen) Text.
+ ///
+ public class HtmlElementTextSemanticsStrong : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsStrong()
+ : base("strong")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsStrong(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsStrong(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsSub.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSub.cs
new file mode 100644
index 0000000..f250e35
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSub.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen tiefgestellten Text.
+ ///
+ public class HtmlElementTextSemanticsSub : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsSub()
+ : base("sub")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSub(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSub(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsSup.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSup.cs
new file mode 100644
index 0000000..635ae26
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsSup.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Markiert einen hochgestellten Text.
+ ///
+ public class HtmlElementTextSemanticsSup : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsSup()
+ : base("sup")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSup(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsSup(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsTime.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsTime.cs
new file mode 100644
index 0000000..aa32c4d
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsTime.cs
@@ -0,0 +1,49 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Wert, der Datum und Uhrzeit angibt
+ ///
+ public class HtmlElementTextSemanticsTime : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Liefert oder setzt das Datum und die Uhrzeit
+ ///
+ public string Time
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsTime()
+ : base("time")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsTime(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsU.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsU.cs
new file mode 100644
index 0000000..07a7b8a
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsU.cs
@@ -0,0 +1,59 @@
+using System.Linq;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für einen Textabschnitt, der vom übrigen Inhalt abgesetzt und üblicherweise unterstrichen dargestellt wird, ohne für eine spezielle Betonung oder Wichtigkeit zu stehen. Dies könnte beispielsweise ein Eigenname auf in chinesischer Sprache sein oder ein Textabschnitt, der häufig falsch buchstabiert wird.
+ ///
+ public class HtmlElementTextSemanticsU : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Text
+ {
+ get => string.Join("", Elements.Where(x => x is HtmlText).Select(x => (x as HtmlText).Value));
+ set { Elements.Clear(); Elements.Add(new HtmlText(value)); }
+ }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsU()
+ : base("u")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsU(string text)
+ : this()
+ {
+ Text = text;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsU(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public override void ToString(StringBuilder builder, int deep)
+ {
+ base.ToString(builder, deep);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsVar.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsVar.cs
new file mode 100644
index 0000000..294c309
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsVar.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Steht für eine Variable. Dies kann ein tatsächlicher mathematischer Ausdruck oder Programmierungskontext sein, ein Identifier für eine Konstante, ein Symbol für eine physikalische Größe, ein Funktionsparameter oder einfach ein Platzhalter.
+ ///
+ public class HtmlElementTextSemanticsVar : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsVar()
+ : base("var")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsVar(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementTextSemanticsVar(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementTextSemanticsWbr.cs b/src/WebExpress/WebHtml/HtmlElementTextSemanticsWbr.cs
new file mode 100644
index 0000000..7202f89
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementTextSemanticsWbr.cs
@@ -0,0 +1,16 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Hiermit kann die Gelegenheit für einen Zeilenumbruch gekennzeichnet werden, mit dem die Lesbarkeit verbessert werden kann, wenn The text. auf mehrere Zeilen verteilt wird.
+ ///
+ public class HtmlElementTextSemanticsWbr : HtmlElement, IHtmlElementTextSemantics
+ {
+ ///
+ /// Constructor
+ ///
+ public HtmlElementTextSemanticsWbr()
+ : base("wbr", false)
+ {
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementWebComponentsSlot.cs b/src/WebExpress/WebHtml/HtmlElementWebComponentsSlot.cs
new file mode 100644
index 0000000..87957af
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementWebComponentsSlot.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet einen Platzhalter
+ ///
+ public class HtmlElementWebFragmentsSlot : HtmlElement, IHtmlElementWebFragments
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementWebFragmentsSlot()
+ : base("slot")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementWebFragmentsSlot(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementWebFragmentsSlot(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlElementWebComponentsTemplate.cs b/src/WebExpress/WebHtml/HtmlElementWebComponentsTemplate.cs
new file mode 100644
index 0000000..acbf519
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlElementWebComponentsTemplate.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet Html, welches nicht gerendert wird
+ ///
+ public class HtmlElementWebFragmentsTemplate : HtmlElement, IHtmlElementWebFragments
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public new List Elements => base.Elements;
+
+ ///
+ /// Constructor
+ ///
+ public HtmlElementWebFragmentsTemplate()
+ : base("template")
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementWebFragmentsTemplate(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlElementWebFragmentsTemplate(IEnumerable nodes)
+ : this()
+ {
+ base.Elements.AddRange(nodes);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlEmpty.cs b/src/WebExpress/WebHtml/HtmlEmpty.cs
new file mode 100644
index 0000000..f242fe2
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlEmpty.cs
@@ -0,0 +1,30 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlEmpty : IHtmlNode
+ {
+ ///
+ /// Liefert oder setzt die Text
+ ///
+ public string Value { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlEmpty()
+ {
+
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Value);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlList.cs b/src/WebExpress/WebHtml/HtmlList.cs
new file mode 100644
index 0000000..76a35a6
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlList.cs
@@ -0,0 +1,82 @@
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Liste von HTML-Elementen
+ ///
+ public class HtmlList : IHtmlNode
+ {
+ ///
+ /// Returns the elements.
+ ///
+ public List Elements { get; private set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlList()
+ {
+ Elements = new List();
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlList(params IHtmlNode[] nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The first content of the html element.
+ /// The following contents of the html elements.
+ public HtmlList(IHtmlNode firstNode, params IHtmlNode[] followingNodes)
+ : this()
+ {
+ Elements.Add(firstNode);
+ Elements.AddRange(followingNodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The content of the html element.
+ public HtmlList(IEnumerable nodes)
+ : this()
+ {
+ Elements.AddRange(nodes);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The first content of the html element.
+ /// The following contents of the html elements.
+ public HtmlList(IHtmlNode firstNode, IEnumerable followingNodes)
+ : this()
+ {
+ Elements.Add(firstNode);
+ Elements.AddRange(followingNodes);
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ /// Abschlustag auf neuer Zeile beginnen
+ public void ToString(StringBuilder builder, int deep)
+ {
+ foreach (var v in Elements)
+ {
+ v.ToString(builder, deep);
+ }
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlNbsp.cs b/src/WebExpress/WebHtml/HtmlNbsp.cs
new file mode 100644
index 0000000..24b36bd
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlNbsp.cs
@@ -0,0 +1,30 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlNbsp : IHtmlNode
+ {
+ ///
+ /// Liefert oder setzt die Text
+ ///
+ public string Value { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlNbsp()
+ {
+ Value = " ";
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Value);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlRaw.cs b/src/WebExpress/WebHtml/HtmlRaw.cs
new file mode 100644
index 0000000..d1c848e
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlRaw.cs
@@ -0,0 +1,48 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlRaw : IHtmlNode
+ {
+ ///
+ /// Returns or sets the text.
+ ///
+ public string Html { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlRaw()
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The text.
+ public HtmlRaw(string html)
+ {
+ Html = html;
+ }
+
+ ///
+ /// In String konvertieren
+ ///
+ /// Das Objekt als String
+ public override string ToString()
+ {
+ return Html;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Html);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/HtmlText.cs b/src/WebExpress/WebHtml/HtmlText.cs
new file mode 100644
index 0000000..b54b800
--- /dev/null
+++ b/src/WebExpress/WebHtml/HtmlText.cs
@@ -0,0 +1,39 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public class HtmlText : IHtmlNode
+ {
+ ///
+ /// Liefert oder setzt die Text
+ ///
+ public string Value { get; set; }
+
+ ///
+ /// Constructor
+ ///
+ public HtmlText()
+ {
+
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The text.
+ public HtmlText(string value)
+ {
+ Value = value;
+ }
+
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ public virtual void ToString(StringBuilder builder, int deep)
+ {
+ builder.Append(Value);
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/IHtml.cs b/src/WebExpress/WebHtml/IHtml.cs
new file mode 100644
index 0000000..98725c0
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtml.cs
@@ -0,0 +1,14 @@
+using System.Text;
+
+namespace WebExpress.WebHtml
+{
+ public interface IHtml
+ {
+ ///
+ /// Convert to a string using a StringBuilder.
+ ///
+ /// The string builder.
+ /// The call depth.
+ void ToString(StringBuilder builder, int deep);
+ }
+}
diff --git a/src/WebExpress/WebHtml/IHtmlAttribute.cs b/src/WebExpress/WebHtml/IHtmlAttribute.cs
new file mode 100644
index 0000000..ca7785f
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlAttribute.cs
@@ -0,0 +1,11 @@
+namespace WebExpress.WebHtml
+{
+ public interface IHtmlAttribute : IHtml
+ {
+ ///
+ /// Returns or sets the name. des Attributes
+ ///
+ string Name { get; set; }
+
+ }
+}
diff --git a/src/WebExpress/WebHtml/IHtmlElementEdit.cs b/src/WebExpress/WebHtml/IHtmlElementEdit.cs
new file mode 100644
index 0000000..9502033
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementEdit.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Textinhalte einer Bedeutung zugewiesen wird
+ ///
+ public interface IHtmlElementEdit
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementEmbedded.cs b/src/WebExpress/WebHtml/IHtmlElementEmbedded.cs
new file mode 100644
index 0000000..e1c6a5b
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementEmbedded.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Inhalte einbettet
+ ///
+ public interface IHtmlElementEmbedded
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementForm.cs b/src/WebExpress/WebHtml/IHtmlElementForm.cs
new file mode 100644
index 0000000..4d13167
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementForm.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Teil eines Formulars ist
+ ///
+ public interface IHtmlElementForm
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementInteractive.cs b/src/WebExpress/WebHtml/IHtmlElementInteractive.cs
new file mode 100644
index 0000000..d419b65
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementInteractive.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welches interaktiv ist
+ ///
+ public interface IHtmlElementInteractive
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementMetadata.cs b/src/WebExpress/WebHtml/IHtmlElementMetadata.cs
new file mode 100644
index 0000000..1a6ee25
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementMetadata.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element als Metadaten
+ ///
+ public interface IHtmlElementMetadata
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementMultimedia.cs b/src/WebExpress/WebHtml/IHtmlElementMultimedia.cs
new file mode 100644
index 0000000..ec567ff
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementMultimedia.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Multimedia-Inhalte besitzt
+ ///
+ public interface IHtmlElementMultimedia
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementRoot.cs b/src/WebExpress/WebHtml/IHtmlElementRoot.cs
new file mode 100644
index 0000000..bfd0ee0
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementRoot.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element als Wurzel
+ ///
+ public interface IHtmlElementRoot
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementScripting.cs b/src/WebExpress/WebHtml/IHtmlElementScripting.cs
new file mode 100644
index 0000000..a9a55b0
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementScripting.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element als Skript
+ ///
+ public interface IHtmlElementScripting
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementSection.cs b/src/WebExpress/WebHtml/IHtmlElementSection.cs
new file mode 100644
index 0000000..d9b0067
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementSection.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element als Abschnitt
+ ///
+ public interface IHtmlElementSection
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementTable.cs b/src/WebExpress/WebHtml/IHtmlElementTable.cs
new file mode 100644
index 0000000..0baa207
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementTable.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Teil einer Tabelle ist
+ ///
+ public interface IHtmlElementTable
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementTextContent.cs b/src/WebExpress/WebHtml/IHtmlElementTextContent.cs
new file mode 100644
index 0000000..a5db9b6
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementTextContent.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Textinhalt strukturiert
+ ///
+ public interface IHtmlElementTextContent
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementTextSemantics.cs b/src/WebExpress/WebHtml/IHtmlElementTextSemantics.cs
new file mode 100644
index 0000000..b8b10d6
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementTextSemantics.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche Textinhalte einer Bedeutung zugewiesen wird
+ ///
+ public interface IHtmlElementTextSemantics
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlElementWebComponents.cs b/src/WebExpress/WebHtml/IHtmlElementWebComponents.cs
new file mode 100644
index 0000000..4938002
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlElementWebComponents.cs
@@ -0,0 +1,9 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Kennzeichnet ein Element welche als Platzhalter dient
+ ///
+ public interface IHtmlElementWebFragments
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/WebExpress/WebHtml/IHtmlFormularItem.cs b/src/WebExpress/WebHtml/IHtmlFormularItem.cs
new file mode 100644
index 0000000..86b3793
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlFormularItem.cs
@@ -0,0 +1,6 @@
+namespace WebExpress.WebHtml
+{
+ public interface IHtmlFormularItem : IHtmlElementForm
+ {
+ }
+}
diff --git a/src/WebExpress/WebHtml/IHtmlNode.cs b/src/WebExpress/WebHtml/IHtmlNode.cs
new file mode 100644
index 0000000..608e9c5
--- /dev/null
+++ b/src/WebExpress/WebHtml/IHtmlNode.cs
@@ -0,0 +1,6 @@
+namespace WebExpress.WebHtml
+{
+ public interface IHtmlNode : IHtml
+ {
+ }
+}
diff --git a/src/WebExpress/WebHtml/Style.cs b/src/WebExpress/WebHtml/Style.cs
new file mode 100644
index 0000000..2ad6626
--- /dev/null
+++ b/src/WebExpress/WebHtml/Style.cs
@@ -0,0 +1,28 @@
+using System.Linq;
+
+namespace WebExpress.WebHtml
+{
+ public static class Style
+ {
+ ///
+ /// Verbindet die angebenen Styles zu einem String
+ ///
+ /// Die einzelnen Styles
+ /// Die Styles als String
+ public static string Concatenate(params string[] items)
+ {
+ return string.Join(" ", items.Where(x => !string.IsNullOrWhiteSpace(x)).Distinct());
+ }
+
+ ///
+ /// Entfernt die angegebenen Styles aus dem Gesammtsring
+ ///
+ /// Die in einem gemeinsamen String verbundenen Styles
+ /// Die zu entfernenden Styles
+ /// Die Styles als String
+ public static string Remove(string styles, params string[] remove)
+ {
+ return string.Join(" ", styles.Split(' ').Where(x => !remove.Contains(x)));
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/TypeEnctype.cs b/src/WebExpress/WebHtml/TypeEnctype.cs
new file mode 100644
index 0000000..f127008
--- /dev/null
+++ b/src/WebExpress/WebHtml/TypeEnctype.cs
@@ -0,0 +1,60 @@
+namespace WebExpress.WebHtml
+{
+ ///
+ /// Legt fest, wie die Daten encoded werden, wenn sie zum Server übertragen werden.
+ ///
+ public enum TypeEnctype
+ {
+ ///
+ /// Alle Zeichen werden encoded (Spaces wird zu "+" koncertiert und spezalzeichen in der Hexrepräsentation)
+ ///
+ UrLEncoded,
+ ///
+ /// Keine Zeichen werden encodes. Wird verwendet, wenn Dateien übertragen werden
+ ///
+ None,
+ ///
+ /// Nur Space-Zeichen werden encodiert.
+ ///
+ Text,
+ ///
+ /// Nicht zuordbar
+ ///
+ Default
+ }
+
+ public static class TypeEnctypeExtensions
+ {
+ ///
+ /// Umwandlung von String in TypeEnctype
+ ///
+ /// Die Kodierung
+ /// Die umgewandelte Kodierung
+ public static TypeEnctype Convert(string enctype)
+ {
+ return (enctype?.ToLower()) switch
+ {
+ "multipart/form-data" => TypeEnctype.None,
+ "text/plain" => TypeEnctype.Text,
+ "application/x-www-form-urlencoded" => TypeEnctype.UrLEncoded,
+ _ => TypeEnctype.Default,
+ };
+ }
+
+
+ ///
+ /// Conversion to string.repräsentation
+ ///
+ /// Die Kodierung
+ /// Die umgewandelte Kodierung
+ public static string Convert(this TypeEnctype enctype)
+ {
+ return enctype switch
+ {
+ TypeEnctype.None => "multipart/form-data",
+ TypeEnctype.Text => "text/plain",
+ _ => "application/x-www-form-urlencoded",
+ };
+ }
+ }
+}
diff --git a/src/WebExpress/WebHtml/TypeFavicon.cs b/src/WebExpress/WebHtml/TypeFavicon.cs
new file mode 100644
index 0000000..15b4eb9
--- /dev/null
+++ b/src/WebExpress/WebHtml/TypeFavicon.cs
@@ -0,0 +1,11 @@
+namespace WebExpress.WebHtml
+{
+ public enum TypeFavicon
+ {
+ Default,
+ ICON,
+ PNG,
+ JPG,
+ SVG
+ }
+}
diff --git a/src/WebExpress/WebHtml/TypeTarget.cs b/src/WebExpress/WebHtml/TypeTarget.cs
new file mode 100644
index 0000000..ea8bc3f
--- /dev/null
+++ b/src/WebExpress/WebHtml/TypeTarget.cs
@@ -0,0 +1,33 @@
+namespace WebExpress.WebHtml
+{
+ public enum TypeTarget
+ {
+ None,
+ Blank,
+ Self,
+ Parent,
+ Top,
+ Framename
+ }
+
+ public static class TypeTargetExtensions
+ {
+ ///
+ /// Umwandlung in einen Klartext
+ ///
+ /// Das Aufrufsziel
+ /// Der Klartext des Targets
+ public static string ToStringValue(this TypeTarget target)
+ {
+ return target switch
+ {
+ TypeTarget.Blank => "_blank",
+ TypeTarget.Self => "_self",
+ TypeTarget.Parent => "_parent",
+ TypeTarget.Top => "_top",
+ TypeTarget.Framename => "_framename",
+ _ => string.Empty,
+ };
+ }
+ }
+}
diff --git a/src/WebExpress/WebJob/Clock.cs b/src/WebExpress/WebJob/Clock.cs
new file mode 100644
index 0000000..3343e66
--- /dev/null
+++ b/src/WebExpress/WebJob/Clock.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("WebExpress.Test")]
+
+namespace WebExpress.WebJob
+{
+ public class Clock
+ {
+ ///
+ /// The underlying date and time.
+ ///
+ private DateTime DateTime { get; set; }
+
+ ///
+ /// The minute 0-59.
+ ///
+ public int Minute => DateTime.Minute;
+
+ ///
+ /// The hour 0-23.
+ ///
+ public int Hour => DateTime.Hour;
+
+ ///
+ /// The day 1-31.
+ ///
+ public int Day => DateTime.Day;
+
+ ///
+ /// The month 1-12.
+ ///
+ public int Month => DateTime.Month;
+
+ ///
+ /// The weekday 0-6 (Sunday-Saturday).
+ ///
+ public int Weekday => (int)DateTime.DayOfWeek;
+
+ ///
+ /// Constructor
+ ///
+ public Clock()
+ {
+ var dateTime = DateTime.Now;
+
+ DateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0);
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The time to copy.
+ public Clock(DateTime dateTime)
+ {
+ DateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0);
+ }
+
+ ///
+ /// Copy-Constructor
+ ///
+ /// The clock to be copied.
+ public Clock(Clock clock)
+ {
+ DateTime = clock.DateTime;
+ }
+
+ ///
+ /// Move the clock one tick (one minute) further.
+ ///
+ internal void Tick()
+ {
+ DateTime = DateTime.AddMinutes(1);
+ }
+
+ ///
+ /// Synchronizes the clock with the current time.
+ ///
+ /// The missed times.
+ public IEnumerable Synchronize()
+ {
+ var dateTime = DateTime.Now;
+ var current = new Clock();
+ var next = new Clock(this);
+
+ var elapsed = new List();
+
+ while (next < current)
+ {
+ elapsed.Add(new Clock(next));
+ next.Tick();
+ }
+
+ DateTime = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0);
+
+ return elapsed;
+ }
+
+ ///
+ /// Compare two times.
+ ///
+ /// The first time.
+ /// The second time.
+ /// True if both times match, false otherwise.
+ public static bool operator ==(Clock obj1, Clock obj2)
+ {
+ return obj1.Minute == obj2.Minute && obj1.Hour == obj2.Hour && obj1.Day == obj2.Day && obj1.Month == obj2.Month;
+ }
+
+ ///
+ /// Compares two times for inequality
+ ///
+ /// The first time.
+ /// The second time.
+ /// True if both times do not match, false otherwise.
+ public static bool operator !=(Clock obj1, Clock obj2)
+ {
+ return obj1.Minute != obj2.Minute || obj1.Hour != obj2.Hour || obj1.Day != obj2.Day || obj1.Month != obj2.Month;
+ }
+
+ ///
+ /// Compares two times to less than.
+ ///
+ /// The first time.
+ /// The second time.
+ /// True wenn die linke Uhrzeit kleiner ist als die Rechte, false sonst
+ public static bool operator <(Clock obj1, Clock obj2)
+ {
+ return obj1.DateTime < obj2.DateTime;
+ }
+
+ ///
+ /// Compares two times to greater than.
+ ///
+ /// The first time.
+ /// The second time.
+ /// True if the time on the left is greater than the time on the right, false otherwise.
+ public static bool operator >(Clock obj1, Clock obj2)
+ {
+ return obj1.DateTime > obj2.DateTime;
+ }
+
+ ///
+ /// Compares two times to less than or equal to.
+ ///
+ /// The first time.
+ /// The second time.
+ /// True if the time on the left is less than the time on the right, otherwise it is false.
+ public static bool operator <=(Clock obj1, Clock obj2)
+ {
+ return obj1 < obj2 || obj1 == obj2;
+ }
+
+ ///
+ /// Compares two times to greater than or equal to.
+ ///
+ /// The first time.
+ /// The second time.
+ /// True if the time on the left is greater than the time on the right, false otherwise.
+ public static bool operator >=(Clock obj1, Clock obj2)
+ {
+ return obj1 > obj2 || obj1 == obj2;
+ }
+
+ ///
+ /// The comparison function.
+ ///
+ /// The time to compare.
+ /// True if both times are the same, false otherwise.
+ public override bool Equals(object obj)
+ {
+ if (obj is null)
+ {
+ return false;
+ }
+
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ return Minute == (obj as Clock).Minute &&
+ Hour == (obj as Clock).Hour &&
+ Day == (obj as Clock).Day &&
+ Month == (obj as Clock).Month;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// The hash code.
+ public override int GetHashCode()
+ {
+ return DateTime.GetHashCode();
+ }
+ }
+}
diff --git a/src/WebExpress/WebJob/Cron.cs b/src/WebExpress/WebJob/Cron.cs
new file mode 100644
index 0000000..0ed4e4c
--- /dev/null
+++ b/src/WebExpress/WebJob/Cron.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using static WebExpress.Internationalization.InternationalizationManager;
+
+namespace WebExpress.WebJob
+{
+ ///
+ /// Manages commands that are executed on a scheduled basis (CRON = command run on notice).
+ ///
+ ///
+ public class Cron
+ {
+ ///
+ /// Returns or sets the reference to the context of the host
+ ///
+ private static IHttpServerContext Context { get; set; }
+
+ ///
+ /// The minute 0-59 or * for any. Comma seperated values or ranges (-) are also possible.
+ ///
+ private List Minute { get; } = new List();
+
+ ///
+ /// The hour 0-23 or * for any. Comma seperated values or ranges (-) are also possible.
+ ///
+ private List Hour { get; } = new List();
+
+ ///
+ /// The day 1-31 or * for any. Comma seperated values or ranges (-) are also possible.
+ ///
+ private List Day { get; } = new List();
+
+ ///
+ /// The month 1-12 or * for any. Comma seperated values or ranges (-) are also possible.
+ ///
+ private List Month { get; } = new List();
+
+ ///
+ /// The day of the week 0-6 (Sunday-Saturday) or * for any. Comma seperated values or ranges (-) are also possible.
+ ///
+ private List Weekday { get; } = new List();
+
+ ///
+ /// Constructor
+ ///
+ /// The reference to the host's context.
+ /// The minute 0-59 or * for any. Comma seperated values or ranges (-) are also possible.
+ /// The hour 0-23 or * for any. Comma seperated values or ranges (-) are also possible.
+ /// The day 1-31 or * for any. Comma seperated values or ranges (-) are also possible.
+ /// The month 1-12 or * for any. Comma seperated values or ranges (-) are also possible.
+ /// The day of the week 0-6 (Sunday-Saturday) or * for any. Comma seperated values or ranges (-) are also possible.
+ public Cron(IHttpServerContext context, string minute = "*", string hour = "*", string day = "*", string month = "*", string weekday = "*")
+ {
+ Context = context;
+
+ Minute.AddRange(Parse(minute, 0, 60));
+ Hour.AddRange(Parse(hour, 0, 24));
+ Day.AddRange(Parse(day, 1, 31));
+ Month.AddRange(Parse(month, 1, 12));
+ Weekday.AddRange(Parse(weekday, 0, 7));
+ }
+
+ ///
+ /// Parses the value.
+ ///
+ /// The value to parse.
+ /// The minimum.
+ /// The maximum.
+ /// The parsed values.
+ private IEnumerable Parse(string value, int minValue, int maxValue)
+ {
+ var items = new List() as IEnumerable;
+ value = value?.ToLower().Trim();
+
+ if (string.IsNullOrEmpty(value) || value.Equals("*"))
+ {
+ return Enumerable.Range(minValue, maxValue).ToList();
+ }
+
+ var commaSeparatedList = value.Split
+ (
+ ',',
+ System.StringSplitOptions.RemoveEmptyEntries | System.StringSplitOptions.TrimEntries
+ );
+
+ foreach (var i in commaSeparatedList)
+ {
+ var range = i.Split('-', System.StringSplitOptions.RemoveEmptyEntries | System.StringSplitOptions.TrimEntries);
+ if (range.Length == 2)
+ {
+ // range
+ var min = int.MinValue;
+ var max = int.MinValue;
+
+ if (int.TryParse(range[0], out int minResult))
+ {
+ min = Math.Max(minResult, minValue);
+ }
+
+ if (int.TryParse(range[1], out int maxResult))
+ {
+ max = Math.Min(maxResult, maxValue);
+ }
+
+ if (min != int.MinValue && max != int.MinValue && min < max)
+ {
+ items = items.Union(Enumerable.Range(min, (max - min) + 1));
+ }
+ else
+ {
+ Context.Log.Warning(message: I18N("webexpress:schedulermanager.cron.range"), args: value);
+ }
+ }
+ else if (range.Length == 1)
+ {
+ if (int.TryParse(range[0], out int result))
+ {
+ if (result >= minValue && result <= maxValue)
+ {
+ items = items.Union(new List { result });
+ }
+ else
+ {
+ Context.Log.Warning(message: I18N("webexpress:schedulermanager.cron.range"), args: result);
+ }
+ }
+ else
+ {
+ Context.Log.Warning(message: I18N("webexpress:schedulermanager.cron.parseerror"), args: value);
+ }
+ }
+ else
+ {
+ Context.Log.Warning(message: I18N("webexpress:schedulermanager.cron.parseerror"), args: value);
+ }
+ }
+
+ return items;
+ }
+
+ ///
+ /// Checks whether the cyclic processing of a command can take place.
+ ///
+ /// True if there is a match, false otherwise.
+ public bool Matching(Clock clock)
+ {
+ return Minute.Contains(clock.Minute) &&
+ Hour.Contains(clock.Hour) &&
+ Day.Contains(clock.Day) &&
+ Month.Contains(clock.Month) &&
+ Weekday.Contains(clock.Weekday);
+ }
+ }
+}
diff --git a/src/WebExpress/WebJob/IJob.cs b/src/WebExpress/WebJob/IJob.cs
new file mode 100644
index 0000000..2a62c98
--- /dev/null
+++ b/src/WebExpress/WebJob/IJob.cs
@@ -0,0 +1,22 @@
+using WebExpress.Internationalization;
+
+namespace WebExpress.WebJob
+{
+ ///
+ /// A task that can be performed cyclically.
+ ///
+ public interface IJob : II18N
+ {
+ ///
+ /// Initialization
+ ///
+ /// The context in which the job is executed.
+ public void Initialization(IJobContext context);
+
+ ///
+ /// Processing of the resource.
+ ///
+ public void Process();
+
+ }
+}
diff --git a/src/WebExpress/WebJob/IJobContext.cs b/src/WebExpress/WebJob/IJobContext.cs
new file mode 100644
index 0000000..1a612b8
--- /dev/null
+++ b/src/WebExpress/WebJob/IJobContext.cs
@@ -0,0 +1,28 @@
+using WebExpress.WebModule;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebJob
+{
+ public interface IJobContext
+ {
+ ///
+ /// Returns the associated plugin context.
+ ///
+ IPluginContext PluginContext { get; }
+
+ ///
+ /// Returns the corresponding module context.
+ ///
+ IModuleContext ModuleContext { get; }
+
+ ///
+ /// Returns the job id.
+ ///
+ string JobId { get; }
+
+ ///
+ /// Returns the cron-object.
+ ///
+ Cron Cron { get; }
+ }
+}
diff --git a/src/WebExpress/WebJob/Job.cs b/src/WebExpress/WebJob/Job.cs
new file mode 100644
index 0000000..b3ef4dd
--- /dev/null
+++ b/src/WebExpress/WebJob/Job.cs
@@ -0,0 +1,38 @@
+
+using System.Globalization;
+
+namespace WebExpress.WebJob
+{
+ ///
+ /// A task that can be performed cyclically.
+ ///
+ public class Job : IJob
+ {
+ ///
+ /// Returns or sets the culture.
+ ///
+ public CultureInfo Culture { get; set; }
+
+ ///
+ /// Returns the context.
+ ///
+ public IJobContext Context { get; private set; }
+
+ ///
+ /// Initialization
+ ///
+ /// The context in which the job is executed.
+ public virtual void Initialization(IJobContext context)
+ {
+ Context = context;
+ }
+
+ ///
+ /// Processing of the resource.
+ ///
+ public virtual void Process()
+ {
+
+ }
+ }
+}
diff --git a/src/WebExpress/WebJob/JobContext.cs b/src/WebExpress/WebJob/JobContext.cs
new file mode 100644
index 0000000..d358f4a
--- /dev/null
+++ b/src/WebExpress/WebJob/JobContext.cs
@@ -0,0 +1,47 @@
+using WebExpress.WebModule;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebJob
+{
+ public class JobContext : IJobContext
+ {
+ ///
+ /// Returns the associated plugin context.
+ ///
+ public IPluginContext PluginContext { get; internal set; }
+
+ ///
+ /// Returns the corresponding module context.
+ ///
+ public IModuleContext ModuleContext { get; internal set; }
+
+ ///
+ /// Returns the job id.
+ ///
+ public string JobId { get; internal set; }
+
+ ///
+ /// Returns the cron-object.
+ ///
+ public Cron Cron { get; internal set; }
+
+ ///
+ /// Constructor
+ ///
+ /// The module context.
+ internal JobContext(IModuleContext moduleContext)
+ {
+ PluginContext = moduleContext?.PluginContext;
+ ModuleContext = moduleContext;
+ }
+
+ ///
+ /// Constructor
+ ///
+ /// The plugin context.
+ internal JobContext(IPluginContext pluginContext)
+ {
+ PluginContext = pluginContext;
+ }
+ }
+}
diff --git a/src/WebExpress/WebJob/JobManager.cs b/src/WebExpress/WebJob/JobManager.cs
new file mode 100644
index 0000000..86e3bb5
--- /dev/null
+++ b/src/WebExpress/WebJob/JobManager.cs
@@ -0,0 +1,431 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using WebExpress.Internationalization;
+using WebExpress.WebAttribute;
+using WebExpress.WebComponent;
+using WebExpress.WebModule;
+using WebExpress.WebPlugin;
+
+namespace WebExpress.WebJob
+{
+ ///
+ /// Processing of cyclic jobs
+ ///
+ public sealed class JobManager : IComponentPlugin, ISystemComponent, IExecutableElements
+ {
+ ///
+ /// Thread termination.
+ ///
+ private CancellationTokenSource TokenSource { get; } = new CancellationTokenSource();
+
+ ///
+ /// The clock for determining the execution of the crons.
+ ///
+ private Clock Clock { get; } = new Clock();
+
+ ///
+ /// Returns or sets the reference to the context of the host.
+ ///
+ public IHttpServerContext HttpServerContext { get; private set; }
+
+ ///
+ /// Returns the directory where the static jobs are listed.
+ ///
+ private ScheduleDictionary StaticScheduleDictionary { get; } = new ScheduleDictionary();
+
+ ///
+ /// Returns the directory where the dynamic jobs are listed.
+ ///
+ private IEnumerable DynamicScheduleList { get; set; } = new List();
+
+ ///
+ /// Constructor
+ ///
+ internal JobManager()
+ {
+ ComponentManager.PluginManager.AddPlugin += (sender, pluginContext) =>
+ {
+ Register(pluginContext);
+ };
+
+ ComponentManager.PluginManager.RemovePlugin += (sender, pluginContext) =>
+ {
+ Remove(pluginContext);
+ };
+
+ ComponentManager.ModuleManager.AddModule += (sender, moduleContext) =>
+ {
+ AssignToModule(moduleContext);
+ };
+
+ ComponentManager.ModuleManager.RemoveModule += (sender, moduleContext) =>
+ {
+ DetachFromModule(moduleContext);
+ };
+ }
+
+ ///
+ /// Initialization
+ ///
+ /// The reference to the context of the host.
+ public void Initialization(IHttpServerContext context)
+ {
+ HttpServerContext = context;
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:jobmanager.initialization"
+ )
+ );
+ }
+
+ ///
+ /// Discovers and registers jobs from the specified plugin.
+ ///
+ /// A context of a plugin whose jobs are to be registered.
+ public void Register(IPluginContext pluginContext)
+ {
+ var assembly = pluginContext?.Assembly;
+
+ foreach (var job in assembly.GetTypes().Where
+ (
+ x => x.IsClass == true &&
+ x.IsSealed &&
+ x.IsPublic &&
+ x.GetInterface(typeof(IJob).Name) != null
+ ))
+ {
+ var id = job.FullName?.ToLower();
+ var minute = "*";
+ var hour = "*";
+ var day = "*";
+ var month = "*";
+ var weekday = "*";
+ var moduleId = string.Empty;
+
+ foreach (var customAttribute in job.CustomAttributes.Where(x => x.AttributeType == typeof(JobAttribute)))
+ {
+ minute = customAttribute.ConstructorArguments.FirstOrDefault().Value?.ToString();
+ hour = customAttribute.ConstructorArguments.Skip(1).FirstOrDefault().Value?.ToString();
+ day = customAttribute.ConstructorArguments.Skip(2).FirstOrDefault().Value?.ToString();
+ month = customAttribute.ConstructorArguments.Skip(3).FirstOrDefault().Value?.ToString();
+ weekday = customAttribute.ConstructorArguments.Skip(4).FirstOrDefault().Value?.ToString();
+ }
+
+ foreach (var customAttribute in job.CustomAttributes
+ .Where(x => x.AttributeType.GetInterfaces().Contains(typeof(IModuleAttribute))))
+ {
+ if (customAttribute.AttributeType.Name == typeof(ModuleAttribute<>).Name && customAttribute.AttributeType.Namespace == typeof(ModuleAttribute<>).Namespace)
+ {
+ moduleId = customAttribute.AttributeType.GenericTypeArguments.FirstOrDefault()?.FullName?.ToLower();
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(moduleId))
+ {
+ // no module specified
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:jobmanager.moduleless", id
+ )
+ );
+ }
+
+ // register the job
+ if (!StaticScheduleDictionary.ContainsKey(pluginContext))
+ {
+ StaticScheduleDictionary.Add(pluginContext, new List());
+ }
+
+ var dictItem = StaticScheduleDictionary[pluginContext];
+
+ dictItem.Add(new ScheduleStaticItem()
+ {
+ Assembly = assembly,
+ JobId = id,
+ Type = job,
+ Cron = new Cron(pluginContext.Host, minute, hour, day, month, weekday),
+ moduleId = moduleId
+ });
+
+ HttpServerContext.Log.Debug
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:jobmanager.job.register", moduleId, id
+ )
+ );
+
+ // assign the job to existing modules.
+ foreach (var moduleContext in ComponentManager.ModuleManager.GetModules(pluginContext, moduleId))
+ {
+ if (moduleContext.PluginContext != pluginContext)
+ {
+ // job is not part of the module
+ HttpServerContext.Log.Warning
+ (
+ InternationalizationManager.I18N
+ (
+ "webexpress:jobmanager.wrongmodule",
+ moduleContext.ModuleId, id
+ )
+ );
+ }
+
+ AssignToModule(moduleContext);
+ }
+ }
+ }
+
+ ///
+ /// Discovers and registers entries from the specified plugin.
+ ///
+ /// A list with plugin contexts that contain the jobs.
+ public void Register(IEnumerable pluginContexts)
+ {
+ foreach (var pluginContext in pluginContexts)
+ {
+ Register(pluginContext);
+ }
+ }
+
+ ///
+ /// Registers a job.
+ ///
+ /// The plugin context.
+ /// The cropn-object.
+ /// The job.
+ public IJob Register(IPluginContext pluginContext, Cron cron) where T : IJob
+ {
+ // create context
+ var jobContext = new JobContext(pluginContext)
+ {
+ JobId = typeof(T).FullName?.ToLower(),
+ Cron = cron
+ };
+
+ var jobInstance = Activator.CreateInstance(typeof(T)) as IJob;
+ jobInstance.Initialization(jobContext);
+
+ var item = new ScheduleDynamicItem()
+ {
+ JobContext = jobContext,
+ Instance = jobInstance
+ };
+
+ DynamicScheduleList = DynamicScheduleList.Append(item);
+
+ return jobInstance;
+ }
+
+ ///
+ /// Registers a job.
+ ///
+ /// The module context.
+ /// The cropn-object.
+ /// The job.
+ public IJob Register(IModuleContext moduleContext, Cron cron) where T : IJob
+ {
+ // create context
+ var jobContext = new JobContext(moduleContext)
+ {
+ JobId = typeof(T).FullName?.ToLower(),
+ Cron = cron
+ };
+
+ var jobInstance = Activator.CreateInstance(typeof(T)) as IJob;
+ jobInstance.Initialization(jobContext);
+
+ var item = new ScheduleDynamicItem()
+ {
+ JobContext = jobContext,
+ Instance = jobInstance
+ };
+
+ DynamicScheduleList = DynamicScheduleList.Append(item);
+
+ return jobInstance;
+ }
+
+ ///