This is an automated email from the ASF dual-hosted git repository.

dklco pushed a commit to branch insights-feature
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git


The following commit(s) were added to refs/heads/insights-feature by this push:
     new 5aca671  Somewhat functional i18n and readability implementaton
5aca671 is described below

commit 5aca6713e04f70c1d012a101471f8d3c77f3026e
Author: Dan Klco <[email protected]>
AuthorDate: Thu Oct 18 11:30:26 2018 -0400

    Somewhat functional i18n and readability implementaton
---
 api/pom.xml                                        |   4 +
 .../org/apache/sling/cms/insights/Insight.java     |  48 +++++--
 .../apache/sling/cms/insights/InsightFactory.java  |   6 +-
 .../apache/sling/cms/insights/InsightsModel.java   |  31 ++--
 .../org/apache/sling/cms/insights/Message.java     |   8 +-
 core/pom.xml                                       |  10 +-
 .../cms/core/i18n/impl/I18NDictionaryImpl.java     |  12 +-
 .../sling/cms/core/i18n/impl/I18NProviderImpl.java | 156 ++++++++++-----------
 .../core/insights/impl/FileInsightRequestImpl.java |  14 +-
 .../cms/core/insights/impl/InsightFactoryImpl.java |  27 +++-
 .../cms/core/insights/impl/InsightsWebConsole.java |  88 ++++++++++++
 .../core/insights/impl/PageInsightRequestImpl.java |  18 ++-
 .../core/internal/models/InsightsModelImpl.java    |  74 ++++++++++
 .../internal/models/ReadabilitySiteConfig.java     |   8 +-
 .../core/readability/impl/ReadabilityConfig.java   |  16 +--
 .../impl/ReadabilityInsightProvider.java           |  68 +++++++--
 .../main/resources/OSGI-INF/l10n/bundle.properties |  24 +++-
 pom.xml                                            |   6 +
 .../resources/SLING-INF/nodetypes/nodetypes.cnd    | 107 +++++++-------
 .../readability.jsp => caconfig/base/base.jsp}     |   3 +-
 .../{caconfigs => caconfig}/readability.json       |   1 +
 .../caconfig/readability/config/config.jsp         |  47 +++----
 .../caconfig/readability/config/edit.json          |  25 ++++
 .../readability/include.jsp}                       |  11 +-
 .../components/insights/insight/insight.jsp        |  44 ++++++
 .../insights/insightlist/insightlist.jsp           |  40 ++----
 .../libs/sling-cms/content/shared/insights.json    |  27 ++++
 .../resources/jcr_root/libs/sling-cms/i18n.json    |  34 +++++
 ...adability.impl.ReadabilityServiceImpl.en.config |  24 ++++
 29 files changed, 697 insertions(+), 284 deletions(-)

diff --git a/api/pom.xml b/api/pom.xml
index 64efe15..64255f0 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -18,6 +18,10 @@
     <name>Apache Sling - CMS API</name>
     <description>An API for the Apache Sling Reference CMS 
Application</description>
 
+    <properties>
+        <sling.java.version>8</sling.java.version>
+    </properties>
+
     <build>
         <plugins>
             <plugin>
diff --git a/api/src/main/java/org/apache/sling/cms/insights/Insight.java 
b/api/src/main/java/org/apache/sling/cms/insights/Insight.java
index 41c70e1..136ff16 100644
--- a/api/src/main/java/org/apache/sling/cms/insights/Insight.java
+++ b/api/src/main/java/org/apache/sling/cms/insights/Insight.java
@@ -24,16 +24,17 @@ import java.util.List;
 /**
  * Simple POJO Model for holding an insight provider's results.
  */
-public class Insight {
+public class Insight implements Comparable<Insight> {
 
-    private Object data;
     private boolean display = true;
+    private Message primaryMessage;
     private InsightProvider provider;
     private InsightRequest request;
     private double score;
     private boolean scored = false;
     private List<Message> scoreDetails = new ArrayList<>();
     private boolean skip = false;
+
     private boolean succeeded = true;
 
     public Insight(InsightProvider provider, InsightRequest request) {
@@ -45,11 +46,21 @@ public class Insight {
         scoreDetails.add(message);
     }
 
-    /**
-     * @return the data
-     */
-    public Object getData() {
-        return data;
+    @Override
+    public int compareTo(Insight o) {
+        if (o.scored && !scored) {
+            return 1;
+        } else if (!o.scored && scored) {
+            return -1;
+        } else if (o.scored && scored) {
+            return (int) (score - o.score);
+        } else {
+            return provider.getTitle().compareTo(o.getProvider().getTitle());
+        }
+    }
+
+    public Message getPrimaryMessage() {
+        return primaryMessage;
     }
 
     /**
@@ -106,19 +117,16 @@ public class Insight {
     }
 
     /**
-     * @param data the data to set
-     */
-    public void setData(Object data) {
-        this.data = data;
-    }
-
-    /**
      * @param display the display to set
      */
     public void setDisplay(boolean display) {
         this.display = display;
     }
 
+    public void setPrimaryMessage(Message primaryMessage) {
+        this.primaryMessage = primaryMessage;
+    }
+
     /**
      * @param provider the provider to set
      */
@@ -165,4 +173,16 @@ public class Insight {
         this.succeeded = succeeded;
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "Insight [display=" + display + ", primaryMessage=" + 
primaryMessage + ", provider=" + provider
+                + ", request=" + request + ", score=" + score + ", scored=" + 
scored + ", scoreDetails=" + scoreDetails
+                + ", skip=" + skip + ", succeeded=" + succeeded + "]";
+    }
+
 }
diff --git 
a/api/src/main/java/org/apache/sling/cms/insights/InsightFactory.java 
b/api/src/main/java/org/apache/sling/cms/insights/InsightFactory.java
index f7d2e9b..c500a7a 100644
--- a/api/src/main/java/org/apache/sling/cms/insights/InsightFactory.java
+++ b/api/src/main/java/org/apache/sling/cms/insights/InsightFactory.java
@@ -18,7 +18,7 @@
  */
 package org.apache.sling.cms.insights;
 
-import java.util.Collection;
+import java.util.List;
 
 import org.apache.sling.cms.File;
 import org.apache.sling.cms.Page;
@@ -34,7 +34,7 @@ public interface InsightFactory {
      * @param file the file for which to retrieve the insights
      * @return the insights
      */
-    Collection<Insight> getInsights(File file);
+    List<Insight> getInsights(File file);
     
 
     /**
@@ -43,6 +43,6 @@ public interface InsightFactory {
      * @param page the page for which to retrieve the insights
      * @return the insights
      */
-    Collection<Insight> getInsights(Page page);
+    List<Insight> getInsights(Page page);
 
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
 b/api/src/main/java/org/apache/sling/cms/insights/InsightsModel.java
similarity index 58%
copy from 
core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
copy to api/src/main/java/org/apache/sling/cms/insights/InsightsModel.java
index ce3bd85..bfe8ec0 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
+++ b/api/src/main/java/org/apache/sling/cms/insights/InsightsModel.java
@@ -16,31 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.cms.core.insights.impl;
+package org.apache.sling.cms.insights;
 
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.insights.FileInsightRequest;
+import java.util.List;
 
 /**
- * Implementation of the FileInsightRequest interface
+ * A model interface for retrieving insights for the current resource
  */
-public class FileInsightRequestImpl implements FileInsightRequest {
+public interface InsightsModel {
 
-    private File file;
-
-    public FileInsightRequestImpl(File file) {
-        this.file = file;
-    }
-
-    @Override
-    public Resource getResource() {
-        return file.getResource();
-    }
-
-    @Override
-    public File getFile() {
-        return file;
-    }
+    /**
+     * Retrieve the insights for the current resource.
+     * 
+     * @return the insights for the resource
+     */
+    List<Insight> getInsights();
 
 }
diff --git a/api/src/main/java/org/apache/sling/cms/insights/Message.java 
b/api/src/main/java/org/apache/sling/cms/insights/Message.java
index 132d86b..c3635cd 100644
--- a/api/src/main/java/org/apache/sling/cms/insights/Message.java
+++ b/api/src/main/java/org/apache/sling/cms/insights/Message.java
@@ -24,7 +24,7 @@ package org.apache.sling.cms.insights;
 public class Message {
 
     public enum STYLE {
-        DANGER, DEFAULT, SUCCESS, WARN
+        DANGER, DEFAULT, SUCCESS, WARNING
     }
 
     public static Message danger(String text) {
@@ -40,7 +40,7 @@ public class Message {
     }
 
     public static Message warn(String text) {
-        return new Message(text, STYLE.WARN);
+        return new Message(text, STYLE.WARNING);
     }
 
     private STYLE style;
@@ -55,11 +55,11 @@ public class Message {
     public STYLE getStyle() {
         return style;
     }
-
+    
     public String getStyleClass() {
         String styleClass = "";
         if (style != STYLE.DEFAULT) {
-            styleClass = "text-" + style.toString().toLowerCase();
+            styleClass = "is-" + style.toString().toLowerCase();
         }
         return styleClass;
     }
diff --git a/core/pom.xml b/core/pom.xml
index f1b3683..219306d 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -16,7 +16,11 @@
     <artifactId>org.apache.sling.cms.core</artifactId>
     <packaging>bundle</packaging>
     <name>Apache Sling - CMS Core</name>
-    <description>The c for the Apache Sling Reference CMS 
Application</description>
+    <description>The core for the Apache Sling Reference CMS 
Application</description>
+
+    <properties>
+        <sling.java.version>8</sling.java.version>
+    </properties>
 
     <build>
         <plugins>
@@ -194,5 +198,9 @@
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.i18n</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.webconsole</artifactId>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NDictionaryImpl.java
 
b/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NDictionaryImpl.java
index aae84f8..36ff759 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NDictionaryImpl.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NDictionaryImpl.java
@@ -40,13 +40,15 @@ public class I18NDictionaryImpl implements I18NDictionary {
     public String get(String key, Object[] args) {
         String localized = get(key);
 
-        if (localized == null || args == null) {
+        if (localized == null) {
             return key;
         }
-        for (int i = 0; i < args.length; i++) {
-            Object o = args[i];
-            if (o != null) {
-                localized = localized.replace("{" + i + "}", o.toString());
+        if (args != null) {
+            for (int i = 0; i < args.length; i++) {
+                Object o = args[i];
+                if (o != null) {
+                    localized = localized.replace("{" + i + "}", o.toString());
+                }
             }
         }
         return localized;
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NProviderImpl.java 
b/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NProviderImpl.java
index c4e846a..32aacb7 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NProviderImpl.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/i18n/impl/I18NProviderImpl.java
@@ -37,34 +37,84 @@ import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.osgi.service.component.annotations.ReferencePolicy;
 import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("deprecation")
 @Component(service = I18NProvider.class)
 public class I18NProviderImpl implements I18NProvider {
+    /**
+     * Provider that goes through a list of registered providers and takes the 
first
+     * non-null responses
+     */
+    private class CombinedBundleProvider implements ResourceBundleProvider {
+
+        @Override
+        public Locale getDefaultLocale() {
+            // ask all registered providers, use the first one that returns
+            final ResourceBundleProvider[] sp = sortedProviders;
+            for (int i = sp.length - 1; i >= 0; i--) {
+                final ResourceBundleProvider provider = sp[i];
+                final Locale locale = provider.getDefaultLocale();
+                if (locale != null) {
+                    log.trace("Found default locale {}", locale);
+                    return locale;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public ResourceBundle getResourceBundle(final Locale locale) {
+            return getResourceBundle(null, locale);
+        }
+
+        @Override
+        public ResourceBundle getResourceBundle(final String baseName, final 
Locale locale) {
+            log.debug("Retrieving resource bundle for {}", locale);
+            // ask all registered providers, use the first one that returns
+            final ResourceBundleProvider[] sp = sortedProviders;
+            for (int i = sp.length - 1; i >= 0; i--) {
+                final ResourceBundleProvider provider = sp[i];
+                final ResourceBundle bundle = baseName != null ? 
provider.getResourceBundle(baseName, locale)
+                        : provider.getResourceBundle(locale);
+                if (bundle != null) {
+                    log.trace("Using bundle {}", bundle);
+                    return bundle;
+                }
+            }
+            return null;
+        }
+    }
+
+    private static final Logger log = 
LoggerFactory.getLogger(I18NProviderImpl.class);
 
     private final DefaultLocaleResolver defaultLocaleResolver = new 
DefaultLocaleResolver();
 
     private volatile LocaleResolver localeResolver = defaultLocaleResolver;
 
-    private volatile RequestLocaleResolver requestLocaleResolver = 
defaultLocaleResolver;
-
     private final Map<Object, ResourceBundleProvider> providers = new 
TreeMap<>();
 
+    private volatile RequestLocaleResolver requestLocaleResolver = 
defaultLocaleResolver;
+
     private volatile ResourceBundleProvider[] sortedProviders = new 
ResourceBundleProvider[0];
 
-    @Override
-    public I18NDictionary getDictionary(SlingHttpServletRequest request) {
-        List<Locale> locales = requestLocaleResolver.resolveLocale(request);
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = 
ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+    protected void bindLocaleResolver(final LocaleResolver resolver) {
+        this.localeResolver = resolver;
+    }
 
-        CombinedBundleProvider cbp = new CombinedBundleProvider();
-        ResourceBundle bundle = null;
-        for (Locale locale : locales) {
-            bundle = cbp.getResourceBundle(locale);
-            if (bundle != null) {
-                break;
-            }
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = 
ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
+    protected void bindRequestLocaleResolver(final RequestLocaleResolver 
resolver) {
+        this.requestLocaleResolver = resolver;
+    }
+
+    @Reference(service = ResourceBundleProvider.class, cardinality = 
ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+    protected void bindResourceBundleProvider(final ResourceBundleProvider 
provider, final Map<String, Object> props) {
+        synchronized (this.providers) {
+            
this.providers.put(ServiceUtil.getComparableForServiceRanking(props, 
Order.ASCENDING), provider);
+            this.sortedProviders = this.providers.values().toArray(new 
ResourceBundleProvider[this.providers.size()]);
         }
-        return new I18NDictionaryImpl(bundle);
     }
 
     @Override
@@ -77,9 +127,19 @@ public class I18NProviderImpl implements I18NProvider {
         return new I18NDictionaryImpl(cbp.getResourceBundle(locale));
     }
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = 
ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    protected void bindLocaleResolver(final LocaleResolver resolver) {
-        this.localeResolver = resolver;
+    @Override
+    public I18NDictionary getDictionary(SlingHttpServletRequest request) {
+        List<Locale> locales = requestLocaleResolver.resolveLocale(request);
+
+        CombinedBundleProvider cbp = new CombinedBundleProvider();
+        ResourceBundle bundle = null;
+        for (Locale locale : locales) {
+            bundle = cbp.getResourceBundle(locale);
+            if (bundle != null) {
+                break;
+            }
+        }
+        return new I18NDictionaryImpl(bundle);
     }
 
     protected void unbindLocaleResolver(final LocaleResolver resolver) {
@@ -88,24 +148,13 @@ public class I18NProviderImpl implements I18NProvider {
         }
     }
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = 
ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
-    protected void bindRequestLocaleResolver(final RequestLocaleResolver 
resolver) {
-        this.requestLocaleResolver = resolver;
-    }
-
     protected void unbindRequestLocaleResolver(final RequestLocaleResolver 
resolver) {
         if (this.requestLocaleResolver == resolver) {
             this.requestLocaleResolver = defaultLocaleResolver;
         }
     }
 
-    @Reference(service = ResourceBundleProvider.class, cardinality = 
ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
-    protected void bindResourceBundleProvider(final ResourceBundleProvider 
provider, final Map<String, Object> props) {
-        synchronized (this.providers) {
-            
this.providers.put(ServiceUtil.getComparableForServiceRanking(props, 
Order.ASCENDING), provider);
-            this.sortedProviders = this.providers.values().toArray(new 
ResourceBundleProvider[this.providers.size()]);
-        }
-    }
+    // ---------- internal 
-----------------------------------------------------
 
     protected void unbindResourceBundleProvider(final ResourceBundleProvider 
provider,
             final Map<String, Object> props) {
@@ -115,55 +164,4 @@ public class I18NProviderImpl implements I18NProvider {
         }
     }
 
-    // ---------- internal 
-----------------------------------------------------
-
-    /**
-     * Provider that goes through a list of registered providers and takes the 
first
-     * non-null responses
-     */
-    private class CombinedBundleProvider implements ResourceBundleProvider {
-
-        @Override
-        public Locale getDefaultLocale() {
-            // ask all registered providers, use the first one that returns
-            final ResourceBundleProvider[] sp = sortedProviders;
-            for (int i = sp.length - 1; i >= 0; i--) {
-                final ResourceBundleProvider provider = sp[i];
-                final Locale locale = provider.getDefaultLocale();
-                if (locale != null) {
-                    return locale;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public ResourceBundle getResourceBundle(final Locale locale) {
-            // ask all registered providers, use the first one that returns
-            final ResourceBundleProvider[] sp = sortedProviders;
-            for (int i = sp.length - 1; i >= 0; i--) {
-                final ResourceBundleProvider provider = sp[i];
-                final ResourceBundle bundle = 
provider.getResourceBundle(locale);
-                if (bundle != null) {
-                    return bundle;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public ResourceBundle getResourceBundle(final String baseName, final 
Locale locale) {
-            // ask all registered providers, use the first one that returns
-            final ResourceBundleProvider[] sp = sortedProviders;
-            for (int i = sp.length - 1; i >= 0; i--) {
-                final ResourceBundleProvider provider = sp[i];
-                final ResourceBundle bundle = 
provider.getResourceBundle(baseName, locale);
-                if (bundle != null) {
-                    return bundle;
-                }
-            }
-            return null;
-        }
-    }
-
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
index ce3bd85..c46b43b 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
@@ -34,13 +34,23 @@ public class FileInsightRequestImpl implements 
FileInsightRequest {
     }
 
     @Override
+    public File getFile() {
+        return file;
+    }
+
+    @Override
     public Resource getResource() {
         return file.getResource();
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
     @Override
-    public File getFile() {
-        return file;
+    public String toString() {
+        return "FileInsightRequestImpl [file=" + file + "]";
     }
 
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightFactoryImpl.java
 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightFactoryImpl.java
index 7f63bfc..e0b8573 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightFactoryImpl.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightFactoryImpl.java
@@ -19,7 +19,9 @@
 package org.apache.sling.cms.core.insights.impl;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -30,6 +32,7 @@ import org.apache.sling.cms.insights.Insight;
 import org.apache.sling.cms.insights.InsightFactory;
 import org.apache.sling.cms.insights.InsightProvider;
 import org.apache.sling.cms.insights.InsightRequest;
+import org.apache.sling.engine.SlingRequestProcessor;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
@@ -38,15 +41,22 @@ import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Implementation of the InsightFactory service interface
+ */
 @Component(immediate = true, service = { InsightFactory.class, 
ServiceListener.class })
 public class InsightFactoryImpl implements InsightFactory, ServiceListener {
 
     private static final Logger log = 
LoggerFactory.getLogger(InsightFactoryImpl.class);
     private static final Map<String, InsightProvider> insightProviders = new 
HashMap<>();
 
+    @Reference
+    private SlingRequestProcessor requestProcessor;
+
     @Activate
     public void activate(ComponentContext context) throws 
InvalidSyntaxException {
         log.info("activate");
@@ -80,19 +90,24 @@ public class InsightFactoryImpl implements InsightFactory, 
ServiceListener {
     }
 
     @Override
-    public Collection<Insight> getInsights(File file) {
+    public List<Insight> getInsights(File file) {
         return getInsights(new FileInsightRequestImpl(file));
     }
 
     @Override
-    public Collection<Insight> getInsights(Page page) {
-        return getInsights(new PageInsightRequestImpl(page));
+    public List<Insight> getInsights(Page page) {
+        return getInsights(new PageInsightRequestImpl(page, requestProcessor));
     }
 
-    private Collection<Insight> getInsights(InsightRequest request) {
-        return insightProviders.values().stream().filter(ip -> 
ip.isEnabled(request))
-                .map(ip -> 
ip.evaluateRequest(request)).collect(Collectors.toList());
+    public Collection<InsightProvider> getProviders() {
+        return insightProviders.values();
+    }
 
+    private List<Insight> getInsights(InsightRequest request) {
+        List<Insight> insights = insightProviders.values().stream().filter(ip 
-> ip.isEnabled(request))
+                .map(ip -> 
ip.evaluateRequest(request)).collect(Collectors.toList());
+        Collections.sort(insights);
+        return insights;
     }
 
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightsWebConsole.java
 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightsWebConsole.java
new file mode 100644
index 0000000..416ee29
--- /dev/null
+++ 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/InsightsWebConsole.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.cms.core.insights.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Collection;
+
+import javax.servlet.Servlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.sling.cms.insights.InsightFactory;
+import org.apache.sling.cms.insights.InsightProvider;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * Simple web console plugin for listing out the available insight provider
+ */
+@Component(property = { Constants.SERVICE_DESCRIPTION + "=Web Console Plugin 
for Apache Sling CMS Insights API",
+        Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+        WebConsoleConstants.PLUGIN_LABEL + "=" + 
InsightsWebConsole.CONSOLE_LABEL,
+        WebConsoleConstants.PLUGIN_TITLE + "=" + 
InsightsWebConsole.CONSOLE_TITLE,
+        WebConsoleConstants.CONFIG_PRINTER_MODES + "=always",
+        WebConsoleConstants.PLUGIN_CATEGORY + "=Status" }, service = { 
Servlet.class })
+public class InsightsWebConsole extends AbstractWebConsolePlugin {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 4819043498961127418L;
+    public static final String CONSOLE_LABEL = "insights";
+    public static final String CONSOLE_TITLE = "Insights";
+
+    @Reference
+    private InsightFactory insightFactory;
+
+    @Override
+    public String getTitle() {
+        return CONSOLE_TITLE;
+    }
+
+    @Override
+    public String getLabel() {
+        return CONSOLE_LABEL;
+    }
+
+    @Override
+    protected void renderContent(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse)
+            throws IOException {
+        PrintWriter pw = httpServletResponse.getWriter();
+        pw.println("<div id='content' class='ui-widget'><br>");
+        pw.println("<pre>");
+        pw.println("Available Insight Providers");
+        pw.println("========================");
+
+        Collection<InsightProvider> providers = ((InsightFactoryImpl) 
insightFactory).getProviders();
+
+        providers.forEach(p -> {
+            pw.println();
+            pw.println(p.getTitle() + " (" + p.getClass().getName() + ")");
+            pw.println("-------------------------------------");
+        });
+        pw.println("</pre>");
+        pw.println("</div>");
+    }
+
+}
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/PageInsightRequestImpl.java
 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/PageInsightRequestImpl.java
index bd3860f..eadd4cd 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/PageInsightRequestImpl.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/insights/impl/PageInsightRequestImpl.java
@@ -24,7 +24,6 @@ import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.inject.Inject;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -51,13 +50,13 @@ public class PageInsightRequestImpl implements 
PageInsightRequest {
 
     private final Page page;
 
-    @Inject
-    private SlingRequestProcessor requestProcessor;
+    private final SlingRequestProcessor requestProcessor;
 
     private final ResourceResolver resourceResolver;
 
-    public PageInsightRequestImpl(Page page) {
+    public PageInsightRequestImpl(Page page, SlingRequestProcessor 
requestProcessor) {
         this.page = page;
+        this.requestProcessor = requestProcessor;
         this.resourceResolver = page.getResource().getResourceResolver();
     }
 
@@ -110,4 +109,15 @@ public class PageInsightRequestImpl implements 
PageInsightRequest {
         return page.getResource();
     }
 
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "PageInsightRequestImpl [markupCache=" + markupCache + ", 
page=" + page + ", requestProcessor="
+                + requestProcessor + ", resourceResolver=" + resourceResolver 
+ "]";
+    }
+
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/internal/models/InsightsModelImpl.java
 
b/core/src/main/java/org/apache/sling/cms/core/internal/models/InsightsModelImpl.java
new file mode 100644
index 0000000..6f2e41e
--- /dev/null
+++ 
b/core/src/main/java/org/apache/sling/cms/core/internal/models/InsightsModelImpl.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.cms.core.internal.models;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.CMSConstants;
+import org.apache.sling.cms.File;
+import org.apache.sling.cms.Page;
+import org.apache.sling.cms.insights.Insight;
+import org.apache.sling.cms.insights.InsightFactory;
+import org.apache.sling.cms.insights.InsightsModel;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.OSGiService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the Insights Model
+ */
+@Model(adaptables = Resource.class, adapters = InsightsModel.class)
+public class InsightsModelImpl implements InsightsModel {
+
+    private static final Logger log = 
LoggerFactory.getLogger(InsightsModelImpl.class);
+
+    @OSGiService
+    private InsightFactory insightsFactory;
+
+    private List<Insight> insights;
+
+    private Resource resource;
+
+    public InsightsModelImpl(Resource resource) {
+        this.resource = resource;
+    }
+
+    @PostConstruct
+    public void init() {
+        if (CMSConstants.NT_FILE.equals(resource.getResourceType())) {
+            log.debug("Gathering file insights for resource {}", resource);
+            insights = 
insightsFactory.getInsights(resource.adaptTo(File.class));
+        } else if (CMSConstants.NT_PAGE.equals(resource.getResourceType())) {
+            log.debug("Gathering page insights for resource {}", resource);
+            insights = 
insightsFactory.getInsights(resource.adaptTo(Page.class));
+        } else {
+            log.debug("Insights not available for resource {}", resource);
+            insights = Collections.emptyList();
+        }
+    }
+
+    @Override
+    public List<Insight> getInsights() {
+        return insights;
+    }
+
+}
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/internal/models/ReadabilitySiteConfig.java
 
b/core/src/main/java/org/apache/sling/cms/core/internal/models/ReadabilitySiteConfig.java
index 5007857..b329e3d 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/internal/models/ReadabilitySiteConfig.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/internal/models/ReadabilitySiteConfig.java
@@ -16,6 +16,8 @@
  */
 package org.apache.sling.cms.core.internal.models;
 
+import javax.inject.Inject;
+
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.models.annotations.Model;
 
@@ -26,8 +28,10 @@ import org.apache.sling.models.annotations.Model;
 @Model(adaptables = Resource.class)
 public interface ReadabilitySiteConfig {
 
-    double minGradeLevel();
+    @Inject
+    double getMinGradeLevel();
 
-    double maxGradeLevel();
+    @Inject
+    double getMaxGradeLevel();
 
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityConfig.java
 
b/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityConfig.java
index 5cba33f..71ea4e0 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityConfig.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityConfig.java
@@ -20,27 +20,27 @@ import 
org.osgi.service.metatype.annotations.AttributeDefinition;
 import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 
 /**
- * An interface for configuring the readability services for a particular
+ * An interface for configuring the %readability services for a particular
  * language
  */
-@ObjectClassDefinition(name = "%config.name", description = 
"%config.description", localization = "OSGI-INF/l10n/bundle")
+@ObjectClassDefinition(name = "%readability.config.name", description = 
"%readability.config.description", localization = "OSGI-INF/l10n/bundle")
 public @interface ReadabilityConfig {
 
-    @AttributeDefinition(name = "%param.locale.name", description = 
"%param.locale.description")
+    @AttributeDefinition(name = "%readability.param.locale.name", description 
= "%readability.param.locale.description")
     String locale();
 
-    @AttributeDefinition(name = "%param.vowelexp.name", description = 
"%param.vowelexp.description")
+    @AttributeDefinition(name = "%readability.param.vowelexp.name", 
description = "%readability.param.vowelexp.description")
     String vowelExpression();
 
-    @AttributeDefinition(name = "%param.extravowelexp.name", description = 
"%param.extravowelexp.description")
+    @AttributeDefinition(name = "%readability.param.extravowelexp.name", 
description = "%readability.param.extravowelexp.description")
     String extraVowelExpression();
 
-    @AttributeDefinition(name = "%param.wordstems.name", description = 
"%param.wordstems.description")
+    @AttributeDefinition(name = "%readability.param.wordstems.name", 
description = "%readability.param.wordstems.description")
     String[] wordstems();
 
-    @AttributeDefinition(name = "%param.complexitymin.name", description = 
"%param.complexitymin.description")
+    @AttributeDefinition(name = "%readability.param.complexitymin.name", 
description = "%readability.param.complexitymin.description")
     int complexityMin();
 
-    @AttributeDefinition(name = "%param.iswordexp.name", description = 
"%param.iswordexp.description")
+    @AttributeDefinition(name = "%readability.param.iswordexp.name", 
description = "%readability.param.iswordexp.description")
     String isWordExpression();
 }
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityInsightProvider.java
 
b/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityInsightProvider.java
index d15a392..47d94e2 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityInsightProvider.java
+++ 
b/core/src/main/java/org/apache/sling/cms/core/readability/impl/ReadabilityInsightProvider.java
@@ -16,6 +16,8 @@
  */
 package org.apache.sling.cms.core.readability.impl;
 
+import java.text.DecimalFormat;
+
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.caconfig.resource.ConfigurationResourceResolver;
 import org.apache.sling.cms.CMSConstants;
@@ -32,15 +34,23 @@ import org.apache.sling.cms.insights.Message;
 import org.apache.sling.cms.insights.PageInsightRequest;
 import org.apache.sling.cms.readability.ReadabilityService;
 import org.apache.sling.cms.readability.ReadabilityServiceFactory;
+import org.apache.sling.cms.readability.Text;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Component(service = InsightProvider.class)
 public class ReadabilityInsightProvider extends BaseInsightProvider {
 
-    public static final String I18N_KEY_READABILITY_RESULT_DANGER = 
"sling.cms.readability.danger";
-    public static final String I18N_KEY_READABILITY_RESULT_SUCCESS = 
"sling.cms.readability.success";
-    public static final String I18N_KEY_READABILITY_RESULT_WARN = 
"sling.cms.readability.warn";
+    public static final String I18N_KEY_READABILITY_DETAIL = 
"slingcms.readability.detail";
+
+    public static final String I18N_KEY_READABILITY_RESULT_DANGER = 
"slingcms.readability.danger";
+    public static final String I18N_KEY_READABILITY_RESULT_SUCCESS = 
"slingcms.readability.success";
+    public static final String I18N_KEY_READABILITY_RESULT_WARN = 
"slingcms.readability.warn";
+    public static final String I18N_KEY_READABILITY_STATS = 
"slingcms.readability.stats";
+
+    private static final Logger log = 
LoggerFactory.getLogger(ReadabilityInsightProvider.class);
 
     public static final String READABILITY_CA_CONFIG = "readability";
 
@@ -53,6 +63,10 @@ public class ReadabilityInsightProvider extends 
BaseInsightProvider {
     @Reference
     private I18NProvider i18nProvider;
 
+    private void addDetail(Insight insight, I18NDictionary dictionary, double 
score, String title) {
+        insight.getScoreDetails().add(Message.defaultMsg(title + ": " + new 
DecimalFormat("##0.00").format(score)));
+    }
+
     /**
      * Method for the extending classes to implement, this can safely throw
      * exceptions and this will trigger a failure result to be returned.
@@ -77,6 +91,7 @@ public class ReadabilityInsightProvider extends 
BaseInsightProvider {
                 CMSConstants.INSIGHTS_CA_CONFIG_BUCKET, READABILITY_CA_CONFIG);
         ReadabilitySiteConfig config = null;
         if (readabilityResource != null) {
+            log.debug("Using readability configuration {}", 
readabilityResource);
             config = readabilityResource.adaptTo(ReadabilitySiteConfig.class);
         }
 
@@ -85,22 +100,42 @@ public class ReadabilityInsightProvider extends 
BaseInsightProvider {
             ReadabilityService svc = 
factory.getReadabilityService(site.getLocale());
 
             double score = svc.calculateAverageGradeLevel(text);
+            String scoreStr = new DecimalFormat("##0.00").format(score);
 
             insight.setScored(true);
 
-            if (score > config.maxGradeLevel() || score < 
config.minGradeLevel()) {
+            log.debug("Calculating readability of page {}", 
pageRequest.getPage());
+
+            if (score > config.getMaxGradeLevel() || score < 
config.getMinGradeLevel()) {
+                log.debug("Retrieved out of bounds readability {} based on 
range {}-{}", score,
+                        config.getMinGradeLevel(), config.getMaxGradeLevel());
                 insight.setScore(0.5);
-                
insight.addMessage(Message.success(dictionary.get(I18N_KEY_READABILITY_RESULT_WARN,
-                        new Object[] { config.minGradeLevel(), 
config.maxGradeLevel(), score })));
+                
insight.setPrimaryMessage(Message.warn(dictionary.get(I18N_KEY_READABILITY_RESULT_WARN,
+                        new Object[] { config.getMinGradeLevel(), 
config.getMaxGradeLevel(), scoreStr })));
             } else {
+                log.debug("Retrieved in bounds readability {} based on range 
{}-{}", score, config.getMinGradeLevel(),
+                        config.getMaxGradeLevel());
                 insight.setScore(1.0);
-                
insight.addMessage(Message.success(dictionary.get(I18N_KEY_READABILITY_RESULT_SUCCESS,
-                        new Object[] { config.minGradeLevel(), 
config.maxGradeLevel(), score })));
+                
insight.setPrimaryMessage(Message.success(dictionary.get(I18N_KEY_READABILITY_RESULT_SUCCESS,
+                        new Object[] { config.getMinGradeLevel(), 
config.getMaxGradeLevel(), scoreStr })));
             }
+            Text t = svc.extractSentences(text);
+
+            
insight.getScoreDetails().add(Message.defaultMsg(dictionary.get(I18N_KEY_READABILITY_STATS,
+                    new Object[] { t.getSentences().size(), t.getWordCount(), 
t.getComplexWordCount() })));
+            addDetail(insight, dictionary, svc.calculateARI(t), "ARI");
+            addDetail(insight, dictionary, svc.calculateColemanLiauIndex(t), 
"Coleman-Liau Index");
+            addDetail(insight, dictionary, 
svc.calculateFleschKincaidGradeLevel(t), "Flesch-Kincaid Grade Level");
+            addDetail(insight, dictionary, svc.calculateFleschReadingEase(t), 
"Flesch-Kincaid Reading Ease");
+            addDetail(insight, dictionary, svc.calculateGunningFog(t), 
"Gunning Fog");
+            addDetail(insight, dictionary, svc.calculateSMOG(t), "SMOG");
+
         } else {
+            log.warn("Failed to get readability for resource {} site or config 
were null",
+                    pageRequest.getPage().getResource());
             insight.setScored(false);
             insight.setSucceeded(false);
-            
insight.addMessage(Message.danger(dictionary.get(I18N_KEY_READABILITY_RESULT_DANGER,
+            
insight.setPrimaryMessage(Message.danger(dictionary.get(I18N_KEY_READABILITY_RESULT_DANGER,
                     new Object[] { pageRequest.getPage().getPath() })));
         }
 
@@ -124,7 +159,18 @@ public class ReadabilityInsightProvider extends 
BaseInsightProvider {
         if (smgr != null) {
             site = smgr.getSite();
         }
-        return request.getType() == InsightRequest.TYPE.PAGE && site != null 
&& site.getLocale() != null
-                && factory.getReadabilityService(site.getLocale()) != null;
+        if (request.getType() != InsightRequest.TYPE.PAGE) {
+            log.debug("Insight is not of page type");
+            return false;
+        }
+        if (site == null || site.getLocale() == null) {
+            log.debug("Did not find site or locale");
+            return false;
+        }
+        if (factory.getReadabilityService(site.getLocale()) == null) {
+            log.debug("Unable to get readability service for locale {}", 
site.getLocale());
+            return false;
+        }
+        return true;
     }
 }
diff --git a/core/src/main/resources/OSGI-INF/l10n/bundle.properties 
b/core/src/main/resources/OSGI-INF/l10n/bundle.properties
index a1ca302..168dc90 100644
--- a/core/src/main/resources/OSGI-INF/l10n/bundle.properties
+++ b/core/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -87,4 +87,26 @@ pathsuggestionservlet.typeFilters.name=Type Filters
 pathsuggestionservlet.typeFilters.description=The defined filters for the path 
\
 suggestion servlet. Each filter is provided in the format 
[name]=[type1],[type2] \
 Each child node of the parent resource to the provided path will be checked to 
see \
-if the node is one of the provided types (or a sub-type) for the filter. 
\ No newline at end of file
+if the node is one of the provided types (or a sub-type) for the filter. 
+
+readability.config.name=Readability Service
+readability.config.description=A service for calculating the readability of 
text using a number of different readability \
+algorithms
+
+readability.param.locale.name=Locale
+readability.param.locale.description=The locale for this configuration, should 
be a valid Java Locale string
+
+readability.param.vowelexp.name=Vowel Expression
+readability.param.vowelexp.description=A regular expression for detecting 
vowels within a string to denote separators for syllables
+
+readability.param.extravowelexp.name=Extra Vowel Expression
+readability.param.extravowelexp.description=A regular expression for detecting 
if a word should have an additional syllable
+
+readability.param.wordstems.name=Word Stems
+readability.param.wordstems.description=An array of word stems to be stripped 
from the words
+
+readability.param.complexitymin.name=Minimum Complexity
+readability.param.complexitymin.description=The minimum number of syllables 
for a word to be considered complex
+
+readability.param.iswordexp.name=Is Word Expression
+readability.param.iswordexp.description=A regular expression for detecting if 
a string is a word
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d6f0146..2003a1a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -183,6 +183,12 @@
                 <version>2.5.14</version>
                 <scope>provided</scope>
             </dependency>
+            <dependency>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>org.apache.felix.webconsole</artifactId>
+                <version>4.2.0</version>
+                <scope>provided</scope>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd 
b/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
index a3d3731..2b33cde 100644
--- a/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
+++ b/ui/src/main/resources/SLING-INF/nodetypes/nodetypes.cnd
@@ -18,70 +18,75 @@
 //  You can find out more documentation on this topic 
 //  by following these links:
 //
-//     -  http://sling.apache.org/site/content-loading.html
-//     -  http://jackrabbit.apache.org/node-type-notation.html
+//    -  http://sling.apache.org/site/content-loading.html
+//    -  http://jackrabbit.apache.org/node-type-notation.html
 
 <sling = 'http://www.sling.apache.org/sling/1.0'>
-       
+    
 
 [sling:Component] > nt:unstructured
-       - componentType (string)
-       - jcr:title (string)
-       
+    - componentType (string)
+    - jcr:title (string)
+    
 [sling:Config] > nt:hierarchyNode
-       orderable
-       - sling:created (date)
-       - sling:createdBy (string)
-       - sling:resourceType (string)
-       - jcr:lastModified (date)
-       - jcr:lastModifiedBy (string)
-       - jcr:title (string)
-       + * (nt:unstructured) = nt:unstructured version
-       
+    orderable
+    - sling:created (date)
+    - sling:createdBy (string)
+    - sling:resourceType (string)
+    - jcr:lastModified (date)
+    - jcr:lastModifiedBy (string)
+    - jcr:title (string)
+    + * (nt:unstructured) = nt:unstructured version
+    - * (UNDEFINED) multiple
+    - * (UNDEFINED)
+    
 [sling:File] > nt:file
-        - * (undefined) copy
-        + jcr:content (sling:FileContent) = sling:FileContent copy primary 
autocreated
-       
+     - * (undefined) copy
+     + jcr:content (sling:FileContent) = sling:FileContent copy primary 
autocreated
+    
 [sling:FileContent] > nt:resource
-       - * (undefined) copy
-       - * (undefined) copy multiple
+    - * (undefined) copy
+    - * (undefined) copy multiple
 
 [sling:Page] > nt:hierarchyNode
-       orderable
-       - published (boolean)
-       + jcr:content (nt:unstructured) = nt:unstructured copy primary
-       + * (nt:base) = nt:base version
+    orderable
+    - published (boolean)
+    + jcr:content (nt:unstructured) = nt:unstructured copy primary
+    + * (nt:base) = nt:base version
 
 [sling:Site] > nt:hierarchyNode
-       orderable
-       - sling:configRef (string)
-       - sling:created (date)
-       - sling:createdBy (string)
-       - sling:url (string)
-       - jcr:language (string)
-       - jcr:lastModified (date)
-       - jcr:lastModifiedBy (string)
-       - jcr:title (string)
-       - jcr:description (string)
-       + * (nt:base) = nt:base version
+    orderable
+    - sling:configRef (string)
+    - sling:created (date)
+    - sling:createdBy (string)
+    - sling:url (string)
+    - jcr:language (string)
+    - jcr:lastModified (date)
+    - jcr:lastModifiedBy (string)
+    - jcr:title (string)
+    - jcr:description (string)
+    + * (nt:base) = nt:base version
 
 [sling:Taxonomy] > nt:hierarchyNode
-       orderable
-       - sling:related (string)
-       - sling:created (date)
-       - sling:createdBy (string)
-       - jcr:lastModified (date)
-       - jcr:lastModifiedBy (string)
-       - jcr:title (string)
-       + * (sling:Taxonomy) = sling:Taxonomy version
+    orderable
+    - sling:related (string)
+    - sling:created (date)
+    - sling:createdBy (string)
+    - jcr:lastModified (date)
+    - jcr:lastModifiedBy (string)
+    - jcr:title (string)
+    + * (sling:Taxonomy) = sling:Taxonomy version
 
 [sling:UGC] > nt:unstructured
     - approveaction (string)
-       - contenttype (string)
-       - finalpath (string)
-       - preview (string)
-       - published (boolean)
-       - referrer (string)
-       - user (string)
-       - useragent (string)
-       - userip (string)
+    - contenttype (string)
+    - finalpath (string)
+    - preview (string)
+    - published (boolean)
+    - referrer (string)
+    - user (string)
+    - useragent (string)
+    - userip (string)
+    - * (UNDEFINED) multiple
+    - * (UNDEFINED)
+    
\ No newline at end of file
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/base/readability.jsp
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/base/base.jsp
similarity index 82%
rename from 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/base/readability.jsp
rename to 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/base/base.jsp
index 4b2b340..bf665b4 100644
--- 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/base/readability.jsp
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/base/base.jsp
@@ -21,8 +21,7 @@
 <sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
 
 <c:set var="oldAvailableTypes" value="${availableTypes}" />
-<c:set var="availableTypes" value="SlingCMS-FileEditor" scope="request" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" 
resourceType="sling-cms/components/cms/fileeditorconfig/config" />
+<sling:call script="include.jsp" />
 <c:set var="availableTypes" value="${oldAvailableTypes}" scope="request" />
 
 <sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability.json
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability.json
similarity index 66%
rename from 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability.json
rename to 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability.json
index 9085b01..e0f61ba 100644
--- 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability.json
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability.json
@@ -1,5 +1,6 @@
 {
        "jcr:primaryType": "sling:Component",
        "jcr:title": "Sling CMS - Readability Configuration",
+       "sling:resourceSuperType": "sling-cms/components/caconfig/base",
     "componentType": "SlingCMS-Config"
 }
\ No newline at end of file
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/config.jsp
similarity index 57%
copy from 
core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
copy to 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/config.jsp
index ce3bd85..309db35 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/config.jsp
@@ -1,4 +1,4 @@
-/*
+<%-- /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -15,32 +15,19 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
- */
-package org.apache.sling.cms.core.insights.impl;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.insights.FileInsightRequest;
-
-/**
- * Implementation of the FileInsightRequest interface
- */
-public class FileInsightRequestImpl implements FileInsightRequest {
-
-    private File file;
-
-    public FileInsightRequestImpl(File file) {
-        this.file = file;
-    }
-
-    @Override
-    public Resource getResource() {
-        return file.getResource();
-    }
-
-    @Override
-    public File getFile() {
-        return file;
-    }
-
-}
+ */ --%>
+<%@include file="/libs/sling-cms/global.jsp"%>
+<dl>
+    <dt>
+        Min Grade Level
+    </dt>
+    <dd>
+        ${sling:encode(properties.minGradeLevel,'HTML')}
+    </dd>
+    <dt>
+        Max Grade Level
+    </dt>
+    <dd>
+        ${sling:encode(properties.maxGradeLevel,'HTML')}
+    </dd>
+</dl>
\ No newline at end of file
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/edit.json
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/edit.json
new file mode 100644
index 0000000..00534c1
--- /dev/null
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/config/edit.json
@@ -0,0 +1,25 @@
+ {
+    "jcr:primaryType": "nt:unstructured",
+    "sling:resourceType": "sling-cms/components/editor/slingform",
+    "button": "Save Readability Configuration",
+    "fields": {
+        "jcr:primaryType": "nt:unstructured",
+        "sling:resourceType": "sling-cms/components/general/container",
+        "minGradeLevel": {
+            "jcr:primaryType": "nt:unstructured",
+            "sling:resourceType": "sling-cms/components/editor/fields/text",
+            "label": "Minimum Grade Level",
+            "name": "minGradeLevel",
+            "required": true,
+            "type": "number"
+        },
+        "maxGradeLevel": {
+            "jcr:primaryType": "nt:unstructured",
+            "sling:resourceType": "sling-cms/components/editor/fields/text",
+            "label": "Maximum Grade Level",
+            "name": "maxGradeLevel",
+            "required": true,
+            "type": "number"
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability/readability.jsp
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/include.jsp
similarity index 62%
rename from 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability/readability.jsp
rename to 
ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/include.jsp
index 4b2b340..409dc28 100644
--- 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfigs/readability/readability.jsp
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/caconfig/readability/include.jsp
@@ -17,13 +17,4 @@
  * under the License.
  */ --%>
  <%@include file="/libs/sling-cms/global.jsp"%>
-<c:set var="cmsEditEnabled" value="true" scope="request" />
-<sling:call script="/libs/sling-cms/components/editor/scripts/init.jsp" />
-
-<c:set var="oldAvailableTypes" value="${availableTypes}" />
-<c:set var="availableTypes" value="SlingCMS-FileEditor" scope="request" />
-<sling:include path="${slingRequest.requestPathInfo.suffix}" 
resourceType="sling-cms/components/cms/fileeditorconfig/config" />
-<c:set var="availableTypes" value="${oldAvailableTypes}" scope="request" />
-
-<sling:call script="/libs/sling-cms/components/editor/scripts/finalize.jsp" />
-<c:set var="cmsEditEnabled" value="false" scope="request" />
\ No newline at end of file
+<sling:include path="${slingRequest.requestPathInfo.suffix}" 
resourceType="sling-cms/components/caconfig/readability/config" />
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insight/insight.jsp
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insight/insight.jsp
new file mode 100644
index 0000000..f56b343
--- /dev/null
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insight/insight.jsp
@@ -0,0 +1,44 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */ --%>
+<%@include file="/libs/sling-cms/global.jsp"%>
+<article class="message ${insight.primaryMessage.styleClass}">
+    <div class="message-header toggle-hidden" 
data-target="#${insight.provider.id}-body">
+        <p>
+            <sling:encode value="${insight.provider.title}" mode="HTML" />
+            <c:if test="${insight.scored}">
+                <fmt:formatNumber type="percent" maxFractionDigits="2" 
value="${insight.score}" />
+            </c:if>
+        </p>
+    </div>
+    <div class="message-body is-hidden" id="${insight.provider.id}-body">
+        <strong><sling:encode value="${insight.primaryMessage.text}" 
mode="HTML" /></strong>
+        <c:if test="${fn:length(insight.scoreDetails) > 0}">
+            <ul>
+                <c:forEach var="detail" items="${insight.scoreDetails}">
+                    <li>
+                        <c:if test="${detail.style != 'DEFAULT'}">
+                            <sling:encode value="${detail.style}" mode="HTML" 
/> -
+                        </c:if>
+                        <sling:encode value="${detail.text}" mode="HTML" />
+                    </li>
+                </c:forEach>
+            </ul>
+        </c:if>
+    </div>
+</article>
\ No newline at end of file
diff --git 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insightlist/insightlist.jsp
similarity index 57%
copy from 
core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
copy to 
ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insightlist/insightlist.jsp
index ce3bd85..71e27ff 100644
--- 
a/core/src/main/java/org/apache/sling/cms/core/insights/impl/FileInsightRequestImpl.java
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/components/insights/insightlist/insightlist.jsp
@@ -1,4 +1,4 @@
-/*
+<%-- /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -15,32 +15,12 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
- */
-package org.apache.sling.cms.core.insights.impl;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.cms.File;
-import org.apache.sling.cms.insights.FileInsightRequest;
-
-/**
- * Implementation of the FileInsightRequest interface
- */
-public class FileInsightRequestImpl implements FileInsightRequest {
-
-    private File file;
-
-    public FileInsightRequestImpl(File file) {
-        this.file = file;
-    }
-
-    @Override
-    public Resource getResource() {
-        return file.getResource();
-    }
-
-    @Override
-    public File getFile() {
-        return file;
-    }
-
-}
+ */ --%>
+<%@include file="/libs/sling-cms/global.jsp"%>
+<sling:adaptTo var="insights" 
adaptable="${slingRequest.requestPathInfo.suffixResource}" 
adaptTo="org.apache.sling.cms.insights.InsightsModel" />
+<c:forEach var="in" items="${insights.insights}" varStatus="status">
+    <c:if test="${!in.skip}">
+        <c:set var="insight" value="${in}" scope="request" />
+        <sling:include path="insight-${status.index}" 
resourceType="sling-cms/components/insights/insight" />
+    </c:if>
+</c:forEach>
\ No newline at end of file
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/insights.json 
b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/insights.json
new file mode 100644
index 0000000..1f865e0
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/shared/insights.json
@@ -0,0 +1,27 @@
+{
+    "jcr:primaryType": "sling:Page",
+    "jcr:content": {
+        "sling:resourceType": "sling-cms/components/pages/base",
+        "jcr:title": "View Insights",
+        "jcr:primaryType": "nt:unstructured",
+        "container": {
+            "jcr:primaryType": "nt:unstructured",
+            "sling:resourceType": "sling-cms/components/general/container",
+            "richtext": {
+                "jcr:primaryType": "nt:unstructured",
+                "sling:resourceType": "sling-cms/components/general/richtext",
+                "text": "<h2>Content Insights</h2>"
+            },
+            "contentbreadcrumb": {
+                "jcr:primaryType": "nt:unstructured",
+                "sling:resourceType": 
"sling-cms/components/cms/contentbreadcrumb",
+                "depth": 3,
+                "prefix": "/cms/site/content.html"
+            },
+            "siteconfig": {
+                "jcr:primaryType": "nt:unstructured",
+                "sling:resourceType": 
"sling-cms/components/insights/insightlist"
+            }
+        }
+    }
+}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json 
b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json
new file mode 100644
index 0000000..48f47f4
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json
@@ -0,0 +1,34 @@
+{
+    "jcr:primaryType": "sling:OrderedFolder",
+    "jcr:content": {
+        "jcr:title": "Sling CMS"
+    },
+    "en_US": {
+        "jcr:primaryType": "sling:Folder",
+        "jcr:mixinTypes": [
+            "mix:language"
+        ],
+        "jcr:language": "en",
+        "sling:resourceType": "sling-cms/components/cms/blank",
+        "slingcms-readability-danger": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Failed to calculate readability for {1}",
+            "sling:key": "slingcms.readability.danger"
+        },
+        "slingcms-readability-stats": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Found {0} sentences with {1} words and {2} 
complex words",
+            "sling:key": "slingcms.readability.stats"
+        },
+        "slingcms-readability-success": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Readability grade {2} is between expected range: 
({0}-{1})",
+            "sling:key": "slingcms.readability.success"
+        },
+        "slingcms-readability-warn": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Readability grade {2} is outside expected range: 
({0}-{1})",
+            "sling:key": "slingcms.readability.warn"
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/ui/src/main/resources/jcr_root/libs/sling-cms/install/org.apache.sling.cms.core.readability.impl.ReadabilityServiceImpl.en.config
 
b/ui/src/main/resources/jcr_root/libs/sling-cms/install/org.apache.sling.cms.core.readability.impl.ReadabilityServiceImpl.en.config
new file mode 100644
index 0000000..dd77ed5
--- /dev/null
+++ 
b/ui/src/main/resources/jcr_root/libs/sling-cms/install/org.apache.sling.cms.core.readability.impl.ReadabilityServiceImpl.en.config
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+locale="en"
+extraVowelExpression=".+y$"
+vowelExpression="a|e|i|o|u"
+isWordExpression="[a-zA-Z]*"
+wordstems=["es","ed","ing","e"]
+complexityMin=I"3"
\ No newline at end of file

Reply via email to