From 9df75bd83c2fd73df2aefdbb796424caccac6d4d Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Thu, 7 Jul 2016 13:42:56 +0200 Subject: [PATCH] juplo:variables parses its parameter as JSON and can merge variable-defs * If the parameter can be interpreted as valid JSON, juplo:variables uses it directly as input. * The parameter accepts special keywords, that controll, if variables, that have been imported earlier, by a call to juplo:variables from an ancestor-tag, will be merged or simply overwritten. --- pom.xml | 16 ++ .../ImportVariablesAttrProcessor.java | 259 ++++++++++++++---- .../ImportVariablesAttrProcessorTest.java | 83 ++++++ src/test/resources/json/1.json | 75 +++++ src/test/resources/json/2.json | 1 + src/test/resources/json/3.json | 1 + 6 files changed, 388 insertions(+), 47 deletions(-) create mode 100644 src/test/java/de/juplo/thymeleaf/ImportVariablesAttrProcessorTest.java create mode 100644 src/test/resources/json/1.json create mode 100644 src/test/resources/json/2.json create mode 100644 src/test/resources/json/3.json diff --git a/pom.xml b/pom.xml index 6daf99a..a21a807 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,8 @@ UTF-8 1.8 + 4.12 + 1.1.7 1.0.0 2.1.5.RELEASE @@ -29,6 +31,20 @@ ${simple-mapper.version} + + + junit + junit + ${junit.version} + test + + + ch.qos.logback + logback-classic + ${logback.version} + test + + diff --git a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java index f679591..e864ab1 100644 --- a/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java +++ b/src/main/java/de/juplo/thymeleaf/ImportVariablesAttrProcessor.java @@ -5,9 +5,14 @@ import com.fasterxml.jackson.core.JsonFactory; import de.juplo.jackson.SimpleMapper; import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.thymeleaf.Arguments; @@ -16,6 +21,7 @@ import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.context.IContext; import org.thymeleaf.context.VariablesMap; import org.thymeleaf.dom.Element; +import org.thymeleaf.dom.Node; import org.thymeleaf.processor.ProcessorResult; import org.thymeleaf.processor.attr.AbstractAttrProcessor; import org.thymeleaf.resourceresolver.IResourceResolver; @@ -31,11 +37,18 @@ import org.thymeleaf.templateresolver.TemplateResolution; */ public class ImportVariablesAttrProcessor extends AbstractAttrProcessor { - public static final int ATTR_PRECEDENCE = 200; - private static final Logger LOG = LoggerFactory.getLogger(ImportVariablesAttrProcessor.class); private static final JsonFactory FACTORY = new JsonFactory(); + private static final String PROPERTY_NAME = + ImportVariablesAttrProcessor.class.getCanonicalName() + "_VARIABLES"; + + public static final Pattern PATTERN = + Pattern.compile( + "^\\s*(?:(?:(merge)|replace):)?\\s*(?:(\\{.*\\})|(.*))\\s*$", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE + ); + public static final int ATTR_PRECEDENCE = 200; public ImportVariablesAttrProcessor() @@ -52,73 +65,225 @@ public class ImportVariablesAttrProcessor extends AbstractAttrProcessor ) { Configuration config = arguments.getConfiguration(); - String templateName = element.getAttributeValue(name); + String parameter = element.getAttributeValue(name); - TemplateProcessingParameters params = - new TemplateProcessingParameters( - config, - templateName, - new IContext() // << We will not execute the template, hence we need no context - { - @Override - public VariablesMap getVariables() - { - return new VariablesMap<>(); - } + Iterator> it = null; - @Override - public Locale getLocale() - { - return Locale.getDefault(); - } + Matcher matcher = PATTERN.matcher(parameter); + boolean merge = false; + String json = null; + String resource = parameter; - @Override - public void addContextExecutionInfo(String templateName) - { - } - }); - - for (ITemplateResolver t_resolver : config.getTemplateResolvers()) + if (matcher.matches()) { - TemplateResolution resolution = t_resolver.resolveTemplate(params); - if (resolution == null) - continue; - if (!"JSON".equals(resolution.getTemplateMode())) - continue; - IResourceResolver r_resolver = resolution.getResourceResolver(); - InputStream is = - r_resolver.getResourceAsStream(params, resolution.getResourceName()); - if (is == null) - continue; + merge = matcher.group(1) != null; + json = matcher.group(2); + resource = matcher.group(3); + } + if (json != null) + { + LOG.info("parsing parameter as JSON"); + LOG.debug("parameter: {}", json); try { - Iterator> it = - SimpleMapper.getObjectIterator(FACTORY.createParser(is)); - while(it.hasNext()) - { - Entry entry = it.next(); - element.setNodeLocalVariable(entry.getKey(), entry.getValue()); - } + it = SimpleMapper.getObjectIterator(FACTORY.createParser(json)); } catch (IOException e) { - LOG.error("cannot retreive {} as JSON: {}", templateName, e.getMessage()); + LOG.error("cannot parse parameter as JSON: {}", json, e.getMessage()); throw new RuntimeException(e); } - catch (IllegalArgumentException e) + } + else + { + LOG.info("retriving {} as JSON-template", resource); + TemplateProcessingParameters params = + new TemplateProcessingParameters( + config, + resource, + new IContext() // << We will not execute the template, hence we need no context + { + @Override + public VariablesMap getVariables() + { + return new VariablesMap<>(); + } + + @Override + public Locale getLocale() + { + return Locale.getDefault(); + } + + @Override + public void addContextExecutionInfo(String templateName) + { + } + }); + + for (ITemplateResolver t_resolver : config.getTemplateResolvers()) { - LOG.error("cannot parse {} as JSON: {}", templateName, e.getMessage()); - throw new RuntimeException(e); + TemplateResolution resolution = t_resolver.resolveTemplate(params); + if (resolution == null) + continue; + if (!"JSON".equals(resolution.getTemplateMode())) + continue; + IResourceResolver r_resolver = resolution.getResourceResolver(); + InputStream is = + r_resolver.getResourceAsStream(params, resolution.getResourceName()); + if (is == null) + continue; + + try + { + it = SimpleMapper.getObjectIterator(FACTORY.createParser(is)); + break; + } + catch (IOException | IllegalArgumentException e) + { + LOG.error("cannot retreive {} as JSON: {}", parameter, e.getMessage()); + throw new RuntimeException(e); + } + } + + if (it == null) + { + LOG.error("cannot resolve {} as JSON (not found)!", parameter); + throw new RuntimeException("Template not found: " + parameter); } } + try + { + Map variables = getVariables(element); + if (merge) + { + while(it.hasNext()) + { + Entry variable = it.next(); + String key = variable.getKey(); + Object value = variable.getValue(); + Object existing = variables.get(key); + if (existing != null) + { + if (value instanceof String) + { + if (!(existing instanceof String)) + { + LOG.error( + "cannot merge variable {} of type {} with a string", + key, + existing.getClass() + ); + throw new RuntimeException( + "Type-Missmatch for variable " + key + ); + } + + String string = ((String)existing).concat((String) value); + LOG.info("appending variable to string {}", key); + element.setNodeLocalVariable(key, string); + } + else if (value instanceof Map) + { + if (!(existing instanceof Map)) + { + LOG.error( + "cannot merge variable {} of type {} with a map", + key, + existing.getClass() + ); + throw new RuntimeException( + "Type-Missmatch for variable " + key + ); + } + + Map map = ((Map)existing); + map.putAll((Map) value); + LOG.info("merging variable with map {}", key); + element.setNodeLocalVariable(key, map); + } + else if (value instanceof List) + { + if (!(existing instanceof List)) + { + LOG.error( + "cannot merge variable {} of type {} with a list", + key, + existing.getClass() + ); + throw new RuntimeException( + "Type-Missmatch for variable " + key + ); + } + + List list = ((List)existing); + list.addAll((List) value); + LOG.info("appending contents of variable to list {}", key); + element.setNodeLocalVariable(key, list); + } + else + { + LOG.error( + "variable {} is of unexpected type {}", key, value.getClass() + ); + throw new RuntimeException( + "Found variable of unexpected type: " + key + ); + } + } + else + { + LOG.info("adding new variable {}", key); + element.setNodeLocalVariable(key, value); + } + } + } + else + while(it.hasNext()) + { + Entry variable = it.next(); + String key = variable.getKey(); + Object value = variable.getValue(); + LOG.info("adding variable {}", key); + variables.put(key, value); + element.setNodeLocalVariable(key, value); + } + } + catch (IllegalArgumentException e) + { + LOG.error("cannot parse {} as JSON: {}", parameter, e.getMessage()); + throw new RuntimeException(e); + } + element.removeAttribute(name); return ProcessorResult.OK; } + Map getVariables(Node node) + { + Node parent = node; + do + { + Map variables = + (Map)parent.getNodeProperty(PROPERTY_NAME); + + if (variables != null) + return variables; + + parent = parent.getParent(); + } + while (parent != null); + + Map variables = new HashMap<>(); + node.setNodeProperty(PROPERTY_NAME, variables); + return variables; + } + + @Override public int getPrecedence() { diff --git a/src/test/java/de/juplo/thymeleaf/ImportVariablesAttrProcessorTest.java b/src/test/java/de/juplo/thymeleaf/ImportVariablesAttrProcessorTest.java new file mode 100644 index 0000000..e8e188e --- /dev/null +++ b/src/test/java/de/juplo/thymeleaf/ImportVariablesAttrProcessorTest.java @@ -0,0 +1,83 @@ +package de.juplo.thymeleaf; + + +import java.io.IOException; +import java.io.InputStream; +import java.util.Scanner; +import java.util.regex.Matcher; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + + + +/** + * + * @author Kai Moritz + */ +public class ImportVariablesAttrProcessorTest +{ + @Test + public void testPattern() throws IOException + { + Matcher matcher; + + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("{}"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" { } "); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\t{\t}\t"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n{\n}\n"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" \t\n{ \t\n} \t\n"); + assertTrue(matcher.matches()); + + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("{\"foo\":\"bar\",\"foobar\":{\"foo\":\"bar\"}"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(" { \"foo\":\"bar\", \"foobar\": { \"foo\": \"bar\" } "); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\t{\t\"foo\":\t\"bar\"\t,\t\"foobar\":\t{\t\"foo\":\"bar\"\t}"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n{\n\"foo\":\n\"bar\"\n,\n\"foobar\":\n{\n\"foo\":\"bar\"\n}"); + assertTrue(matcher.matches()); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("\n\t {\n\t \"foo\":\n\t \"bar\"\n\t ,\n\t \"foobar\":\n\t {\n\t \"foo\":\"bar\"\n\t }"); + assertTrue(matcher.matches()); + + String json; + + json = read("/json/1.json"); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json); + assertTrue(matcher.matches()); + json = read("/json/2.json"); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json); + assertTrue(matcher.matches()); + json = read("/json/3.json"); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher(json); + assertTrue(matcher.matches()); + + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("foo:bar"); + assertTrue(matcher.matches()); + assertNull(matcher.group(1)); + assertNull(matcher.group(2)); + assertEquals("foo:bar", matcher.group(3)); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("replace:foo"); + assertTrue(matcher.matches()); + assertNull(matcher.group(1)); + assertNull(matcher.group(2)); + assertEquals("foo", matcher.group(3)); + matcher = ImportVariablesAttrProcessor.PATTERN.matcher("merge:foo"); + assertTrue(matcher.matches()); + assertEquals("merge", matcher.group(1)); + assertNull(matcher.group(2)); + assertEquals("foo", matcher.group(3)); + } + + + String read(String resource) + { + InputStream is = getClass().getResourceAsStream(resource); + return new Scanner(is).useDelimiter("\\Z").next(); + } +} diff --git a/src/test/resources/json/1.json b/src/test/resources/json/1.json new file mode 100644 index 0000000..44c8c6e --- /dev/null +++ b/src/test/resources/json/1.json @@ -0,0 +1,75 @@ +{ "sections": { "blog": "/blog.html", "projects": "/projects.html", "about": "/about.html" }, "pages": { "/index.html": { "name": "Home" }, "/blog.html": { "name": "Blog", "childs": { "/blog/article.html": "An Article", "/blog/comments.html": "Comments" }, "crumbs": [ { "uri": "/blog.html", "name": "Blog" } ] }, "/blog/article.html": { "name": "An Article", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/article.html", "name": "An Article" } ] }, "/blog/comments.html": { "name": "Comments", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/comments.html", "name": "Comments" } ] }, "/projects.html": { "name": "Projects", "childs": { "#hibernate4-maven-plugin": "Hibernate 4 Maven Plugin", "/projects/fix-swf/overview.html": "Fix SWF", "#jquery.openx": "jQuery OpenX", "/projects/html-experimente.html": "HTML-Experimente", "#accelerator": "accelerator", "/projects/typo.html": "Typography" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" } ] }, "#hibernate4-maven-plugin": { "name": "Overview", "childs": {} }, "/projects/fix-swf/overview.html": { "name": "Overview", "childs": { "/projects/fix-swf/overview.html": "Overview", "/projects/fix-swf/getting-started.html": "Getting Started", "#faq": "FAQ", "#documentation": "Documentation" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/overview.html", "name": "Overview" } ] }, "#faq": { "name": "FAQ" }, "#documentation": { "name": "Documentation" }, "#jquery.openx": { "name": "jQuery OpenX" }, "#accelerator": { "name": "Accellerator" }, "/projects/typo.html": { "name": "Typography", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/typo.html", "name": "Typography" } ] }, "/projects/html-experimente.html": { "name": "HTML-Experimente", "childs": { "/projects/html-experimente/formulare.html": "Formulare", "/projects/html-experimente/symbole.html": "Symbol-Font", "/templates/404.html": "404-Template", "/projects/html-experimente/gibts-ja-gar-nicht.html": "404-Fehlerseite", "/templates/error.html": "5xx-Template", "/projects/html-experimente/error.html": "5xx-Fehlerseite", "/projects/html-experimente/fast-leer-mit-menü.html": "Leer, mit Menü, ohne Marginal", "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": "Leer, mit Menü, mit Marginal", "/projects/html-experimente/fast-leer-kein-menü.html": "Leer, ohne Menü, ohne Marginal", "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": "Leer, ohne Menü, mit Marginal", "/projects/html-experimente/fast-leer-einspaltig.html": "Leer, einspaltig", "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": "Leer, einspaltig, mit Marginal", "/projects/html-experimente/breadcrumb.html": "Langer Breadcrumb", "/projects/html-experimente/kein-layout.html": "Alle Stylings deaktiviert", "/projects/html-experimente/basis-layout.html": "Nur das Basis-Layout", "/projects/html-experimente/druck-layout.html": "Druck-Layout", "/projects/html-experimente/tiny.html": "Layout TINY", "/projects/html-experimente/phone.html": "Layout PHONE", "/projects/html-experimente/tablet.html": "Layout TABLET", "/projects/html-experimente/seitenaufteilung.html": "Basis-Layout & Seitenaufteilung", "/projects/html-experimente/seitenkopf.html": "Basis-Layout & Seitenkopf", "/projects/html-experimente/testlab.html": "Media-Query-Test (Beispiel)" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" } ] }, "/projects/fix-swf/getting-started.html": { "name": "Getting Started", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/getting-started.html", "name": "Getting Started" } ] }, "/projects/html-experimente/formulare.html": { "name": "Formulare", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/formulare.html", "name": "Formulare" } ] }, "/projects/html-experimente/symbole.html": { "name": "Symbol-Font", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/symbole.html", "name": "Symbol-Font" } ] }, "/templates/404.html": { "name": "404-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/404.html", "name": "404-Template" } ] }, "/projects/html-experimente/gibts-ja-gar-nicht.html": { "name": "404-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/gibts-ja-gar-nicht.html", "name": "404-Fehlerseite" } ] }, "/templates/error.html": { "name": "5xx-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/error.html", "name": "5xx-Template" } ] }, "/projects/html-experimente/error.html": { "name": "5xx-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/error.html", "name": "5xx-Fehlerseite" } ] + }, + "/projects/html-experimente/fast-leer-mit-menü.html": { + "name": "Leer, mit Menü, ohne Marginal", + "crumbs": [ + { "uri": "/projects.html", "name": "Projects" }, + { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, + { "uri": "/projects/html-experimente/fast-leer-mit-menü.html", "name": "Leer, mit Menü, ohne Marginal" } + ] + }, + "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": { + "name": "Leer, mit Menü, mit Marginal", + "crumbs": [ + { "uri": "/projects.html", "name": "Projects" }, + { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, + { "uri": "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html", "name": "Leer, mit Menü, mit Marginal" } + ] + }, + "/projects/html-experimente/fast-leer-kein-menü.html": { + "name": "Leer, ohne Menü, ohne Marginal", + "crumbs": [ + { "uri": "/projects.html", "name": "Projects" }, + { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, + { "uri": "/projects/html-experimente/fast-leer-kein-menü.html", "name": "Leer, ohne Menü, ohne Marginal" } + ] + }, + "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": { + "name": "Leer, ohne Menü, mit Marginal", + "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html", "name": "Leer, ohne Menü, mit Marginal" } ] }, "/projects/html-experimente/fast-leer-einspaltig.html": { "name": "Leer, einspaltig", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig.html", "name": "Leer, einspaltig" } ] }, "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": { "name": "Leer, einspaltig, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html", "name": "Leer, einspaltig, mit Marginal" } ] }, "/projects/html-experimente/breadcrumb.html": { "name": "Langer Breadcrumb", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/breadcrumb.html", "name": "Langer Breadcrumb" } ] }, "/projects/html-experimente/kein-layout.html": { "name": "Alle Stylings deaktiviert", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/kein-layout.html", "name": "Alle Stylings deaktiviert" } ] }, "/projects/html-experimente/basis-layout.html": { "name": "Nur das Basis-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/basis-layout.html", "name": "Nur das Basis-Layout" } ] }, "/projects/html-experimente/druck-layout.html": { "name": "Druck-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/druck-layout.html", "name": "Druck-Layout" } ] }, "/projects/html-experimente/tiny.html": { "name": "Layout TINY", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tiny.html", "name": "Layout TINY" } ] }, "/projects/html-experimente/phone.html": { "name": "Layout PHONE", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/phone.html", "name": "Layout PHONE" } ] }, "/projects/html-experimente/tablet.html": { "name": "Layout TABLET", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tablet.html", "name": "Layout TABLET" } + ] + }, + "/projects/html-experimente/seitenaufteilung.html": { + "name": "Basis-Layout & Seitenaufteilung", + "crumbs": [ + { "uri": "/projects.html", "name": "Projects" }, + { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, + { "uri": "/projects/html-experimente/seitenaufteilung.html", "name": "Basis-Layout & Seitenaufteilung" } + ] + }, + "/projects/html-experimente/seitenkopf.html": { + "name": "Basis-Layout & Seitenkopf", + "crumbs": [ + { "uri": "/projects.html", "name": "Projects" }, + { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, + { "uri": "/projects/html-experimente/seitenkopf.html", "name": "Basis-Layout & Seitenkopf" } + ] + }, "/projects/html-experimente/testlab.html": { "name": "Media-Query-Test (Beispiel)", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/testlab.html", "name": "Media-Query-Test (Beispiel)" } ] }, "/about.html": { "name": "About", "childs": { "/expertise.html": "Expertise", "/references.html": "References", "/impressum.html": "Impressum", "/contact.html": "Contact" }, "crumbs": [ { "uri": "/about.html", "name": "About" } ] }, "/expertise.html": { "name": "Expertise", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/expertise.html", "name": "Expertise" } ] }, "/references.html": { "name": "References", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/references.html", "name": "References" } ] }, "/impressum.html": { "name": "Impressum", "childs": { "/agb.html": "AGB", "/haftung-inhalte.html": "Haftung für Inhalte", "/haftung-links.html": "Haftung für Links", "/urheberrechte.html": "Urheberrechte", "/datenschutz.html": "Datenschutz", "/google-analytics.html": "Google Analytics" }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" } ] }, "/contact.html": { "name": "Contact", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/contact.html", "name": "Contact" } ] }, "/agb.html": { "name": "AGB", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/agb.html", "name": "AGB" } ] }, "/haftung-inhalte.html": { "name": "Haftung für Inhalte", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-inhalte.html", "name": "Haftung für Inhalte" } ] }, "/haftung-links.html": { "name": "Haftung für Links", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-links.html", "name": "Haftung für Links" } + ] + }, + "/urheberrechte.html": { + "name": "Urheberrechte", + "crumbs": [ + { "uri": "/about.html", "name": "About" }, + { "uri": "/impressum.html", "name": "Impressum" }, + { "uri": "/urheberrechte.html", "name": "Urheberrechte" } + ] + }, + "/datenschutz.html": { + "name": "Datenschutz", + "crumbs": [ + { "uri": "/about.html", "name": "About" }, + { "uri": "/impressum.html", "name": "Impressum" }, + { "uri": "/datenschutz.html", "name": "Datenschutz" } + ] + }, + "/google-analytics.html": { + "name": "Google Analytics", + "crumbs": [ + { "uri": "/about.html", "name": "About" }, + { "uri": "/impressum.html", "name": "Impressum" }, + { "uri": "/google-analytics.html", "name": "Google Analytics" } + ] + } + } +} diff --git a/src/test/resources/json/2.json b/src/test/resources/json/2.json new file mode 100644 index 0000000..b94325a --- /dev/null +++ b/src/test/resources/json/2.json @@ -0,0 +1 @@ +{ "sections": { "blog": "/blog.html", "projects": "/projects.html", "about": "/about.html" }, "pages": { "/index.html": { "name": "Home" }, "/blog.html": { "name": "Blog", "childs": { "/blog/article.html": "An Article", "/blog/comments.html": "Comments" }, "crumbs": [ { "uri": "/blog.html", "name": "Blog" } ] }, "/blog/article.html": { "name": "An Article", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/article.html", "name": "An Article" } ] }, "/blog/comments.html": { "name": "Comments", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/comments.html", "name": "Comments" } ] }, "/projects.html": { "name": "Projects", "childs": { "#hibernate4-maven-plugin": "Hibernate 4 Maven Plugin", "/projects/fix-swf/overview.html": "Fix SWF", "#jquery.openx": "jQuery OpenX", "/projects/html-experimente.html": "HTML-Experimente", "#accelerator": "accelerator", "/projects/typo.html": "Typography" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" } ] }, "#hibernate4-maven-plugin": { "name": "Overview", "childs": {} }, "/projects/fix-swf/overview.html": { "name": "Overview", "childs": { "/projects/fix-swf/overview.html": "Overview", "/projects/fix-swf/getting-started.html": "Getting Started", "#faq": "FAQ", "#documentation": "Documentation" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/overview.html", "name": "Overview" } ] }, "#faq": { "name": "FAQ" }, "#documentation": { "name": "Documentation" }, "#jquery.openx": { "name": "jQuery OpenX" }, "#accelerator": { "name": "Accellerator" }, "/projects/typo.html": { "name": "Typography", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/typo.html", "name": "Typography" } ] }, "/projects/html-experimente.html": { "name": "HTML-Experimente", "childs": { "/projects/html-experimente/formulare.html": "Formulare", "/projects/html-experimente/symbole.html": "Symbol-Font", "/templates/404.html": "404-Template", "/projects/html-experimente/gibts-ja-gar-nicht.html": "404-Fehlerseite", "/templates/error.html": "5xx-Template", "/projects/html-experimente/error.html": "5xx-Fehlerseite", "/projects/html-experimente/fast-leer-mit-menü.html": "Leer, mit Menü, ohne Marginal", "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": "Leer, mit Menü, mit Marginal", "/projects/html-experimente/fast-leer-kein-menü.html": "Leer, ohne Menü, ohne Marginal", "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": "Leer, ohne Menü, mit Marginal", "/projects/html-experimente/fast-leer-einspaltig.html": "Leer, einspaltig", "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": "Leer, einspaltig, mit Marginal", "/projects/html-experimente/breadcrumb.html": "Langer Breadcrumb", "/projects/html-experimente/kein-layout.html": "Alle Stylings deaktiviert", "/projects/html-experimente/basis-layout.html": "Nur das Basis-Layout", "/projects/html-experimente/druck-layout.html": "Druck-Layout", "/projects/html-experimente/tiny.html": "Layout TINY", "/projects/html-experimente/phone.html": "Layout PHONE", "/projects/html-experimente/tablet.html": "Layout TABLET", "/projects/html-experimente/seitenaufteilung.html": "Basis-Layout & Seitenaufteilung", "/projects/html-experimente/seitenkopf.html": "Basis-Layout & Seitenkopf", "/projects/html-experimente/testlab.html": "Media-Query-Test (Beispiel)" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" } ] }, "/projects/fix-swf/getting-started.html": { "name": "Getting Started", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/getting-started.html", "name": "Getting Started" } ] }, "/projects/html-experimente/formulare.html": { "name": "Formulare", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/formulare.html", "name": "Formulare" } ] }, "/projects/html-experimente/symbole.html": { "name": "Symbol-Font", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/symbole.html", "name": "Symbol-Font" } ] }, "/templates/404.html": { "name": "404-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/404.html", "name": "404-Template" } ] }, "/projects/html-experimente/gibts-ja-gar-nicht.html": { "name": "404-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/gibts-ja-gar-nicht.html", "name": "404-Fehlerseite" } ] }, "/templates/error.html": { "name": "5xx-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/error.html", "name": "5xx-Template" } ] }, "/projects/html-experimente/error.html": { "name": "5xx-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/error.html", "name": "5xx-Fehlerseite" } ] }, "/projects/html-experimente/fast-leer-mit-menü.html": { "name": "Leer, mit Menü, ohne Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-mit-menü.html", "name": "Leer, mit Menü, ohne Marginal" } ] }, "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": { "name": "Leer, mit Menü, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html", "name": "Leer, mit Menü, mit Marginal" } ] }, "/projects/html-experimente/fast-leer-kein-menü.html": { "name": "Leer, ohne Menü, ohne Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-kein-menü.html", "name": "Leer, ohne Menü, ohne Marginal" } ] }, "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": { "name": "Leer, ohne Menü, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html", "name": "Leer, ohne Menü, mit Marginal" } ] }, "/projects/html-experimente/fast-leer-einspaltig.html": { "name": "Leer, einspaltig", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig.html", "name": "Leer, einspaltig" } ] }, "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": { "name": "Leer, einspaltig, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html", "name": "Leer, einspaltig, mit Marginal" } ] }, "/projects/html-experimente/breadcrumb.html": { "name": "Langer Breadcrumb", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/breadcrumb.html", "name": "Langer Breadcrumb" } ] }, "/projects/html-experimente/kein-layout.html": { "name": "Alle Stylings deaktiviert", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/kein-layout.html", "name": "Alle Stylings deaktiviert" } ] }, "/projects/html-experimente/basis-layout.html": { "name": "Nur das Basis-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/basis-layout.html", "name": "Nur das Basis-Layout" } ] }, "/projects/html-experimente/druck-layout.html": { "name": "Druck-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/druck-layout.html", "name": "Druck-Layout" } ] }, "/projects/html-experimente/tiny.html": { "name": "Layout TINY", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tiny.html", "name": "Layout TINY" } ] }, "/projects/html-experimente/phone.html": { "name": "Layout PHONE", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/phone.html", "name": "Layout PHONE" } ] }, "/projects/html-experimente/tablet.html": { "name": "Layout TABLET", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tablet.html", "name": "Layout TABLET" } ] }, "/projects/html-experimente/seitenaufteilung.html": { "name": "Basis-Layout & Seitenaufteilung", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/seitenaufteilung.html", "name": "Basis-Layout & Seitenaufteilung" } ] }, "/projects/html-experimente/seitenkopf.html": { "name": "Basis-Layout & Seitenkopf", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/seitenkopf.html", "name": "Basis-Layout & Seitenkopf" } ] }, "/projects/html-experimente/testlab.html": { "name": "Media-Query-Test (Beispiel)", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/testlab.html", "name": "Media-Query-Test (Beispiel)" } ] }, "/about.html": { "name": "About", "childs": { "/expertise.html": "Expertise", "/references.html": "References", "/impressum.html": "Impressum", "/contact.html": "Contact" }, "crumbs": [ { "uri": "/about.html", "name": "About" } ] }, "/expertise.html": { "name": "Expertise", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/expertise.html", "name": "Expertise" } ] }, "/references.html": { "name": "References", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/references.html", "name": "References" } ] }, "/impressum.html": { "name": "Impressum", "childs": { "/agb.html": "AGB", "/haftung-inhalte.html": "Haftung für Inhalte", "/haftung-links.html": "Haftung für Links", "/urheberrechte.html": "Urheberrechte", "/datenschutz.html": "Datenschutz", "/google-analytics.html": "Google Analytics" }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" } ] }, "/contact.html": { "name": "Contact", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/contact.html", "name": "Contact" } ] }, "/agb.html": { "name": "AGB", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/agb.html", "name": "AGB" } ] }, "/haftung-inhalte.html": { "name": "Haftung für Inhalte", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-inhalte.html", "name": "Haftung für Inhalte" } ] }, "/haftung-links.html": { "name": "Haftung für Links", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-links.html", "name": "Haftung für Links" } ] }, "/urheberrechte.html": { "name": "Urheberrechte", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/urheberrechte.html", "name": "Urheberrechte" } ] }, "/datenschutz.html": { "name": "Datenschutz", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/datenschutz.html", "name": "Datenschutz" } ] }, "/google-analytics.html": { "name": "Google Analytics", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/google-analytics.html", "name": "Google Analytics" } ] } } } diff --git a/src/test/resources/json/3.json b/src/test/resources/json/3.json new file mode 100644 index 0000000..c0b809e --- /dev/null +++ b/src/test/resources/json/3.json @@ -0,0 +1 @@ +{ "sections": { "blog": "/blog.html", "projects": "/projects.html", "about": "/about.html" }, "pages": { "/index.html": { "name": "Home" }, "/blog.html": { "name": "Blog", "childs": { "/blog/article.html": "An Article", "/blog/comments.html": "Comments" }, "crumbs": [ { "uri": "/blog.html", "name": "Blog" } ] }, "/blog/article.html": { "name": "An Article", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/article.html", "name": "An Article" } ] }, "/blog/comments.html": { "name": "Comments", "crumbs": [ { "uri": "/blog.html", "name": "Blog" }, { "uri": "/blog/comments.html", "name": "Comments" } ] }, "/projects.html": { "name": "Projects", "childs": { "#hibernate4-maven-plugin": "Hibernate 4 Maven Plugin", "/projects/fix-swf/overview.html": "Fix SWF", "#jquery.openx": "jQuery OpenX", "/projects/html-experimente.html": "HTML-Experimente", "#accelerator": "accelerator", "/projects/typo.html": "Typography" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" } ] }, "#hibernate4-maven-plugin": { "name": "Overview", "childs": {} }, "/projects/fix-swf/overview.html": { "name": "Overview", "childs": { "/projects/fix-swf/overview.html": "Overview", "/projects/fix-swf/getting-started.html": "Getting Started", "#faq": "FAQ", "#documentation": "Documentation" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/overview.html", "name": "Overview" } ] }, "#faq": { "name": "FAQ" }, "#documentation": { "name": "Documentation" }, "#jquery.openx": { "name": "jQuery OpenX" }, "#accelerator": { "name": "Accellerator" }, "/projects/typo.html": { "name": "Typography", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/typo.html", "name": "Typography" } ] }, "/projects/html-experimente.html": { "name": "HTML-Experimente", "childs": { "/projects/html-experimente/formulare.html": "Formulare", "/projects/html-experimente/symbole.html": "Symbol-Font", "/templates/404.html": "404-Template", "/projects/html-experimente/gibts-ja-gar-nicht.html": "404-Fehlerseite", "/templates/error.html": "5xx-Template", "/projects/html-experimente/error.html": "5xx-Fehlerseite", "/projects/html-experimente/fast-leer-mit-menü.html": "Leer, mit Menü, ohne Marginal", "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": "Leer, mit Menü, mit Marginal", "/projects/html-experimente/fast-leer-kein-menü.html": "Leer, ohne Menü, ohne Marginal", "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": "Leer, ohne Menü, mit Marginal", "/projects/html-experimente/fast-leer-einspaltig.html": "Leer, einspaltig", "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": "Leer, einspaltig, mit Marginal", "/projects/html-experimente/breadcrumb.html": "Langer Breadcrumb", "/projects/html-experimente/kein-layout.html": "Alle Stylings deaktiviert", "/projects/html-experimente/basis-layout.html": "Nur das Basis-Layout", "/projects/html-experimente/druck-layout.html": "Druck-Layout", "/projects/html-experimente/tiny.html": "Layout TINY", "/projects/html-experimente/phone.html": "Layout PHONE", "/projects/html-experimente/tablet.html": "Layout TABLET", "/projects/html-experimente/seitenaufteilung.html": "Basis-Layout & Seitenaufteilung", "/projects/html-experimente/seitenkopf.html": "Basis-Layout & Seitenkopf", "/projects/html-experimente/testlab.html": "Media-Query-Test (Beispiel)" }, "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" } ] }, "/projects/fix-swf/getting-started.html": { "name": "Getting Started", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/fix-swf/overview.html", "name": "Fix SWF" }, { "uri": "/projects/fix-swf/getting-started.html", "name": "Getting Started" } ] }, "/projects/html-experimente/formulare.html": { "name": "Formulare", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/formulare.html", "name": "Formulare" } ] }, "/projects/html-experimente/symbole.html": { "name": "Symbol-Font", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/symbole.html", "name": "Symbol-Font" } ] }, "/templates/404.html": { "name": "404-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/404.html", "name": "404-Template" } ] }, "/projects/html-experimente/gibts-ja-gar-nicht.html": { "name": "404-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/gibts-ja-gar-nicht.html", "name": "404-Fehlerseite" } ] }, "/templates/error.html": { "name": "5xx-Template", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/templates/error.html", "name": "5xx-Template" } ] }, "/projects/html-experimente/error.html": { "name": "5xx-Fehlerseite", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/error.html", "name": "5xx-Fehlerseite" } ] }, "/projects/html-experimente/fast-leer-mit-menü.html": { "name": "Leer, mit Menü, ohne Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-mit-menü.html", "name": "Leer, mit Menü, ohne Marginal" } ] }, "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html": { "name": "Leer, mit Menü, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-mit-menü-und-marginalinhalt.html", "name": "Leer, mit Menü, mit Marginal" } ] }, "/projects/html-experimente/fast-leer-kein-menü.html": { "name": "Leer, ohne Menü, ohne Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-kein-menü.html", "name": "Leer, ohne Menü, ohne Marginal" } ] }, "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html": { "name": "Leer, ohne Menü, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-kein-menü-aber-marginalinhalt.html", "name": "Leer, ohne Menü, mit Marginal" } ] }, "/projects/html-experimente/fast-leer-einspaltig.html": { "name": "Leer, einspaltig", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig.html", "name": "Leer, einspaltig" } ] }, "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html": { "name": "Leer, einspaltig, mit Marginal", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/fast-leer-einspaltig-mit-marginalinhalt.html", "name": "Leer, einspaltig, mit Marginal" } ] }, "/projects/html-experimente/breadcrumb.html": { "name": "Langer Breadcrumb", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/breadcrumb.html", "name": "Langer Breadcrumb" } ] }, "/projects/html-experimente/kein-layout.html": { "name": "Alle Stylings deaktiviert", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/kein-layout.html", "name": "Alle Stylings deaktiviert" } ] }, "/projects/html-experimente/basis-layout.html": { "name": "Nur das Basis-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/basis-layout.html", "name": "Nur das Basis-Layout" } ] }, "/projects/html-experimente/druck-layout.html": { "name": "Druck-Layout", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/druck-layout.html", "name": "Druck-Layout" } ] }, "/projects/html-experimente/tiny.html": { "name": "Layout TINY", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tiny.html", "name": "Layout TINY" } ] }, "/projects/html-experimente/phone.html": { "name": "Layout PHONE", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/phone.html", "name": "Layout PHONE" } ] }, "/projects/html-experimente/tablet.html": { "name": "Layout TABLET", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/tablet.html", "name": "Layout TABLET" } ] }, "/projects/html-experimente/seitenaufteilung.html": { "name": "Basis-Layout & Seitenaufteilung", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/seitenaufteilung.html", "name": "Basis-Layout & Seitenaufteilung" } ] }, "/projects/html-experimente/seitenkopf.html": { "name": "Basis-Layout & Seitenkopf", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/seitenkopf.html", "name": "Basis-Layout & Seitenkopf" } ] }, "/projects/html-experimente/testlab.html": { "name": "Media-Query-Test (Beispiel)", "crumbs": [ { "uri": "/projects.html", "name": "Projects" }, { "uri": "/projects/html-experimente.html", "name": "HTML-Experimente" }, { "uri": "/projects/html-experimente/testlab.html", "name": "Media-Query-Test (Beispiel)" } ] }, "/about.html": { "name": "About", "childs": { "/expertise.html": "Expertise", "/references.html": "References", "/impressum.html": "Impressum", "/contact.html": "Contact" }, "crumbs": [ { "uri": "/about.html", "name": "About" } ] }, "/expertise.html": { "name": "Expertise", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/expertise.html", "name": "Expertise" } ] }, "/references.html": { "name": "References", "childs": { }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/references.html", "name": "References" } ] }, "/impressum.html": { "name": "Impressum", "childs": { "/agb.html": "AGB", "/haftung-inhalte.html": "Haftung für Inhalte", "/haftung-links.html": "Haftung für Links", "/urheberrechte.html": "Urheberrechte", "/datenschutz.html": "Datenschutz", "/google-analytics.html": "Google Analytics" }, "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" } ] }, "/contact.html": { "name": "Contact", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/contact.html", "name": "Contact" } ] }, "/agb.html": { "name": "AGB", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/agb.html", "name": "AGB" } ] }, "/haftung-inhalte.html": { "name": "Haftung für Inhalte", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-inhalte.html", "name": "Haftung für Inhalte" } ] }, "/haftung-links.html": { "name": "Haftung für Links", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/haftung-links.html", "name": "Haftung für Links" } ] }, "/urheberrechte.html": { "name": "Urheberrechte", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/urheberrechte.html", "name": "Urheberrechte" } ] }, "/datenschutz.html": { "name": "Datenschutz", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/datenschutz.html", "name": "Datenschutz" } ] }, "/google-analytics.html": { "name": "Google Analytics", "crumbs": [ { "uri": "/about.html", "name": "About" }, { "uri": "/impressum.html", "name": "Impressum" }, { "uri": "/google-analytics.html", "name": "Google Analytics" } ] } } } -- 2.20.1