Compare commits

..

22 Commits

Author SHA1 Message Date
9fe8cba35f more fixes for BeeDK 2021-02-04 16:41:39 -05:00
d020061450 major project structure refactoring; using BeeDK 2021-02-03 15:41:01 -05:00
brian
a0384107fb tengine run fixes 2021-01-19 10:27:24 -05:00
brian
7c2cf314bb tengine config related fixes 2021-01-19 10:13:51 -05:00
0e110947fc fixed run for tengine 2021-01-18 17:45:46 -05:00
340c7c6f30 fixed config load 2021-01-18 17:43:40 -05:00
brian
d15b54796d added quick test and validating HTML output 2021-01-18 17:05:06 -05:00
brian
3ed79aebb7 added several negative tests 2021-01-18 16:53:07 -05:00
brian
bc6a09f9b9 changes to get testing framework ready 2021-01-18 16:35:12 -05:00
brian
41164123a3 added engine selection 2021-01-18 15:56:53 -05:00
brian
b448025ee2 implemented flexmark & commonmark engines 2021-01-18 15:48:46 -05:00
0d322c7ec9 added tengine project; not implemented but builds 2021-01-18 10:55:02 -05:00
ade1b4f144 added github/table extensions, but still not using 2021-01-18 00:29:47 -05:00
9950e45dee upgraded showdown to v1.9.1; including table/github extensions, but not using them yet 2021-01-18 00:27:40 -05:00
11a4729b03 fixed module folder naming issue 2021-01-18 00:23:06 -05:00
daffe7f54a wrapped in the Alfresco SDK with new name 2021-01-17 23:35:04 -05:00
cetra3
2a7a0f10ad Increment repo version 2017-09-20 09:02:07 +09:30
peter
5a688398bb Merge branch 'fixBug' into 'master'
Fix the issue of md preview module in Alfresco 5.2.1

See merge request !1
2017-09-13 08:28:02 +09:30
Zhi Wang
e1edfcbe4c Fix the issue when choose file strip render mode in document library, the preview of md file will fail 2017-09-12 18:06:02 +09:30
cetra3
86eecbc3b9 Include markdown editor screenshot 2016-09-27 09:13:07 +09:30
cetra3
37ccb6dd0e Include editing capabilities 2016-09-26 17:50:11 +09:30
cetra3
d2020178c6 Exclude preview from external share proxy 2016-09-26 12:49:24 +09:30
91 changed files with 9907 additions and 2673 deletions

39
.gitignore vendored
View File

@ -1 +1,38 @@
*.amp **.log*
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar
# Eclipse
.metadata
.project
.classpath
bin/
tmp/
*.tmp
.settings/
.loadpath
.recommenders
# IntelliJ IDEA
**.idea
**.iml
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# macOS
*.DS_Store

View File

@ -1,9 +1,13 @@
# Markdown Preview for Alfresco Share # Markdown Preview for Alfresco Share
This module adds a markdown preview to Alfresco Share: This module adds a markdown preview and edit button to Alfresco Share:
![](markdown-preview.png) ![](markdown-preview.png)
This also adds a markdown editor:
![](markdown-editor.png)
## Compiling ## Compiling
You will need: You will need:
@ -13,12 +17,19 @@ You will need:
* Parashift's alfresco amp plugin from here: https://bitbucket.org/parashift/alfresco-amp-plugin * Parashift's alfresco amp plugin from here: https://bitbucket.org/parashift/alfresco-amp-plugin
* Run `gradle amp` from the `share` and `repo` directories * Run `gradle amp` from the `share` and `repo` directories
### Installing to Alfresco ## Installing to Alfresco
* Deploy the amp to both the repo and share end using alfresco-mmt or other methods * Deploy the amp to both the repo and share end using alfresco-mmt or other methods
### Usage ## Usage
The usage is automatic. ### Previewing a Markdown document
Any documents with the mime type `text/x-markdown` will display within the document details view. * Navigate to the document details page of a markdown document
### Editing a Markdown document
* Find a markdown document within the document library
* Select `Edit Markdown`
* When you are finished, select `Save Markdown`

BIN
markdown-editor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

69
platform-webapp/pom.xml Normal file
View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfmarkdown-platform-webapp</artifactId>
<name>Alfmarkdown Platform/Repository Web Application</name>
<packaging>pom</packaging>
<parent>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<developers>
<developer>
<id>brian.long</id>
<name>Brian Long</name>
<email>brian@inteligr8.com</email>
</developer>
</developers>
<properties>
<ate.docker.image.name>inteligr8/alfmarkdown-tengine</ate.docker.image.name>
<ate.docker.image.tag>${project.version}</ate.docker.image.tag>
<ate.debugger.port>8001</ate.debugger.port>
</properties>
<dependencies>
<dependency>
<groupId>de.fmaul</groupId>
<artifactId>javascript-console-repo</artifactId>
<version>0.6.0</version>
<type>amp</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>alfmarkdown-platform</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>com.inteligr8.alfresco:beedk-ate-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-lts-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-platform-webapp-tile:1.0-SNAPSHOT</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>inteligr8-releases</id>
<url>http://repos.yateslong.us/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,22 @@
FROM ${docker.acs.image}:${alfresco.platform.version}
ARG TOMCAT_DIR=/usr/local/tomcat
USER root
# Copy Dockerfile to avoid an error if no JARs exist
COPY Dockerfile extensions/*.jar $TOMCAT_DIR/webapps/alfresco/WEB-INF/lib/
# Copy Dockerfile to avoid an error if no AMPs exist
COPY Dockerfile extensions/*.amp $TOMCAT_DIR/amps/
RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install \
$TOMCAT_DIR/amps $TOMCAT_DIR/webapps/alfresco -directory -nobackup -force
COPY alfresco-global.properties $TOMCAT_DIR/shared/classes/alfresco-global.properties
COPY dev-log4j.properties $TOMCAT_DIR/shared/classes/alfresco/extension
COPY disable-webscript-caching-context.xml $TOMCAT_DIR/shared/classes/alfresco/extension
# Copy Dockerfile to avoid an error if no license file exists
COPY Dockerfile license/*.* $TOMCAT_DIR/webapps/alfresco/WEB-INF/classes/alfresco/extension/license/
USER ${USERNAME}

View File

@ -0,0 +1,87 @@
# 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.
# RUN TIME PROPERTIES
# -------------------
#
# Alfresco configuration for running locally with PostgreSQL Database
#
# Configuration when running Tomcat embedded from Maven.
# Property values from the POM but it can also be edited here.
#
# Alfresco Repo Webapp (alfresco.war) context, ports etc
alfresco.context=alfresco
alfresco.host=localhost
alfresco.port=8080
alfresco.protocol=http
# Alfresco Share Webapp (share.war) context, ports etc
share.context=share
share.host=localhost
share.port=8180
share.protocol=http
# Don't try and recover any index
index.recovery.mode=NONE
# These jobs seem to require Lucene (Unsupported Operation with Solr) so we disable them / set to future date
# See https://forums.alfresco.com/en/viewtopic.php?f=52&t=41597
# If you want to enable them (and so full WQS functionality), please also set index.subsystem.name=lucene
wcmqs.dynamicCollectionProcessor.schedule=0 30 2 * * ? 2060
wcmqs.feedbackProcessor.schedule=0 40 2 * * ? 2060
wcmqs.publishQueueProcessor.schedule=0 50 2 * * ? 2060
# Fail or not when there are node integrity checker errors
integrity.failOnError=true
# Alfresco Repository PostgreSQL Database configuration.
# The PostgreSQL Driver is brought in via the tomcat7-maven-plugin as a dependency.
db.driver=org.postgresql.Driver
# This Alfresco Platform Configuration file should be used for custom properties that are introduced by this module.
# Define default values for all properties here.
# System Administrators can override these values in environment specific configurations in
# alfresco/tomcat/shared/classes/alfresco-global.properties.
#
index.subsystem.name=solr6
solr.host=alfmarkdown-ass
solr.port=8983
solr.secureComms=none
db.username=alfresco
db.password=alfresco
db.pool.initial=10
db.pool.max=100
db.url=jdbc:postgresql://alfmarkdown-postgres:5432/alfresco
# File servers related properties
# For local runs we disable CIFS and FTP
cifs.enabled=false
ftp.enabled=false
csrf.filter.enabled=false
# Embedded broker without persistence
messaging.broker.url=vm://localhost?broker.persistent=false
# Disable ATS
transform.service.enabled=false
local.transform.service.enabled=true
legacy.transform.service.enabled=false
jodconverter.enabled=false
-DlocalTransform.alfmarkdown.url=http://alfmarkdown-tengine:8090/

View File

@ -0,0 +1,266 @@
# Set root logger level to error
log4j.rootLogger=error, Console, File
# All outputs currently set to be a ConsoleAppender.
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
# use log4j NDC to replace %x with tenant domain / username
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} %x %-5p [%c{3}] [%t] %m%n
#log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=alfresco.log
log4j.appender.File.Append=true
log4j.appender.File.DatePattern='.'yyyy-MM-dd
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
# Commented-in loggers will be exposed as JMX MBeans (refer to org.alfresco.repo.admin.Log4JHierarchyInit)
# Hence, generally useful loggers should be listed with at least ERROR level to allow simple runtime
# control of the level via a suitable JMX Console. Also, any other loggers can be added transiently via
# Log4j addLoggerMBean as long as the logger exists and has been loaded.
# Hibernate
log4j.logger.org.hibernate=error
log4j.logger.org.hibernate.util.JDBCExceptionReporter=fatal
log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=fatal
log4j.logger.org.hibernate.type=warn
log4j.logger.org.hibernate.cfg.SettingsFactory=warn
# Spring
log4j.logger.org.springframework=warn
# Turn off Spring remoting warnings that should really be info or debug.
log4j.logger.org.springframework.remoting.support=error
log4j.logger.org.springframework.util=error
# Axis/WSS4J
log4j.logger.org.apache.axis=info
log4j.logger.org.apache.ws=info
# CXF
log4j.logger.org.apache.cxf=error
# MyFaces
log4j.logger.org.apache.myfaces.util.DebugUtils=info
log4j.logger.org.apache.myfaces.el.VariableResolverImpl=error
log4j.logger.org.apache.myfaces.application.jsp.JspViewHandlerImpl=error
log4j.logger.org.apache.myfaces.taglib=error
# OpenOfficeConnection
log4j.logger.net.sf.jooreports.openoffice.connection=fatal
# log prepared statement cache activity log4j.logger.org.hibernate.ps.PreparedStatementCache=info
# Alfresco
log4j.logger.org.alfresco=error
log4j.logger.org.alfresco.repo.admin=info
log4j.logger.org.alfresco.repo.transaction=warn
log4j.logger.org.alfresco.repo.cache.TransactionalCache=warn
log4j.logger.org.alfresco.repo.model.filefolder=warn
log4j.logger.org.alfresco.repo.tenant=info
log4j.logger.org.alfresco.config=warn
log4j.logger.org.alfresco.config.JndiObjectFactoryBean=warn
log4j.logger.org.alfresco.config.JBossEnabledWebApplicationContext=warn
log4j.logger.org.alfresco.repo.management.subsystems=warn
log4j.logger.org.alfresco.repo.management.subsystems.ChildApplicationContextFactory=info
log4j.logger.org.alfresco.repo.management.subsystems.ChildApplicationContextFactory$ChildApplicationContext=warn
log4j.logger.org.alfresco.repo.security.sync=info
log4j.logger.org.alfresco.repo.security.person=info
log4j.logger.org.alfresco.sample=info
log4j.logger.org.alfresco.web=info
#log4j.logger.org.alfresco.web.app.AlfrescoNavigationHandler=debug
#log4j.logger.org.alfresco.web.ui.repo.component.UIActions=debug
#log4j.logger.org.alfresco.web.ui.repo.tag.PageTag=debug
#log4j.logger.org.alfresco.web.bean.clipboard=debug
log4j.logger.org.alfresco.service.descriptor.DescriptorService=info
#log4j.logger.org.alfresco.web.page=debug
log4j.logger.org.alfresco.repo.importer.ImporterBootstrap=error
#log4j.logger.org.alfresco.repo.importer.ImporterBootstrap=info
log4j.logger.org.alfresco.repo.admin.patch.PatchExecuter=info
log4j.logger.org.alfresco.repo.domain.patch.ibatis.PatchDAOImpl=info
# Specific patches
log4j.logger.org.alfresco.repo.admin.patch.impl.DeploymentMigrationPatch=info
log4j.logger.org.alfresco.repo.version.VersionMigrator=info
log4j.logger.org.alfresco.repo.module.ModuleServiceImpl=info
log4j.logger.org.alfresco.repo.domain.schema.SchemaBootstrap=info
log4j.logger.org.alfresco.repo.admin.ConfigurationChecker=info
log4j.logger.org.alfresco.repo.node.index.AbstractReindexComponent=warn
log4j.logger.org.alfresco.repo.node.index.IndexTransactionTracker=warn
log4j.logger.org.alfresco.repo.node.index.FullIndexRecoveryComponent=info
log4j.logger.org.alfresco.util.OpenOfficeConnectionTester=info
log4j.logger.org.alfresco.repo.node.db.hibernate.HibernateNodeDaoServiceImpl=warn
log4j.logger.org.alfresco.repo.domain.hibernate.DirtySessionMethodInterceptor=warn
log4j.logger.org.alfresco.repo.transaction.RetryingTransactionHelper=warn
log4j.logger.org.alfresco.util.transaction.SpringAwareUserTransaction.trace=warn
log4j.logger.org.alfresco.util.AbstractTriggerBean=warn
log4j.logger.org.alfresco.enterprise.repo.cluster=info
log4j.logger.org.alfresco.repo.version.Version2ServiceImpl=warn
#log4j.logger.org.alfresco.web.app.DebugPhaseListener=debug
log4j.logger.org.alfresco.repo.node.db.NodeStringLengthWorker=info
log4j.logger.org.alfresco.repo.workflow=info
# CIFS server debugging
log4j.logger.org.alfresco.smb.protocol=error
#log4j.logger.org.alfresco.smb.protocol.auth=debug
#log4j.logger.org.alfresco.acegi=debug
# FTP server debugging
log4j.logger.org.alfresco.ftp.protocol=error
#log4j.logger.org.alfresco.ftp.server=debug
# WebDAV debugging
#log4j.logger.org.alfresco.webdav.protocol=debug
log4j.logger.org.alfresco.webdav.protocol=info
# NTLM servlet filters
#log4j.logger.org.alfresco.web.app.servlet.NTLMAuthenticationFilter=debug
#log4j.logger.org.alfresco.repo.webdav.auth.NTLMAuthenticationFilter=debug
# Kerberos servlet filters
#log4j.logger.org.alfresco.web.app.servlet.KerberosAuthenticationFilter=debug
#log4j.logger.org.alfresco.repo.webdav.auth.KerberosAuthenticationFilter=debug
# File servers
log4j.logger.org.alfresco.fileserver=warn
# Repo filesystem debug logging
#log4j.logger.org.alfresco.filesys.repo.ContentDiskDriver=debug
# Integrity message threshold - if 'failOnViolation' is off, then WARNINGS are generated
log4j.logger.org.alfresco.repo.node.integrity=ERROR
# Indexer debugging
log4j.logger.org.alfresco.repo.search.Indexer=error
#log4j.logger.org.alfresco.repo.search.Indexer=debug
log4j.logger.org.alfresco.repo.search.impl.lucene.index=error
log4j.logger.org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexerImpl=warn
#log4j.logger.org.alfresco.repo.search.impl.lucene.index=DEBUG
# Audit debugging
# log4j.logger.org.alfresco.repo.audit=DEBUG
# log4j.logger.org.alfresco.repo.audit.model=DEBUG
# Property sheet and modelling debugging
# change to error to hide the warnings about missing properties and associations
log4j.logger.alfresco.missingProperties=warn
# Dictionary/Model debugging
log4j.logger.org.alfresco.repo.dictionary=warn
log4j.logger.org.alfresco.repo.dictionary.types.period=warn
# Virtualization Server Registry
log4j.logger.org.alfresco.mbeans.VirtServerRegistry=error
# Spring context runtime property setter
log4j.logger.org.alfresco.util.RuntimeSystemPropertiesSetter=info
# Debugging options for clustering
log4j.logger.org.alfresco.repo.content.ReplicatingContentStore=error
log4j.logger.org.alfresco.repo.content.replication=error
#log4j.logger.org.alfresco.repo.deploy.DeploymentServiceImpl=debug
# Activity service
log4j.logger.org.alfresco.repo.activities=warn
# User usage tracking
log4j.logger.org.alfresco.repo.usage=info
# Sharepoint
log4j.logger.org.alfresco.module.vti=info
# Forms Engine
log4j.logger.org.alfresco.web.config.forms=info
log4j.logger.org.alfresco.web.scripts.forms=info
# CMIS
log4j.logger.org.alfresco.opencmis=error
log4j.logger.org.alfresco.opencmis.AlfrescoCmisServiceInterceptor=error
log4j.logger.org.alfresco.cmis=error
log4j.logger.org.alfresco.cmis.dictionary=warn
log4j.logger.org.apache.chemistry.opencmis=info
log4j.logger.org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet=OFF
log4j.logger.org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet=OFF
# IMAP
log4j.logger.org.alfresco.repo.imap=info
# JBPM
# Note: non-fatal errors (eg. logged during job execution) should be handled by Alfresco's retrying transaction handler
log4j.logger.org.jbpm.graph.def.GraphElement=fatal
#log4j.logger.org.alfresco.repo.googledocs=debug
# Web Framework
log4j.logger.org.springframework.extensions.webscripts=info
log4j.logger.org.springframework.extensions.webscripts.ScriptLogger=warn
log4j.logger.org.springframework.extensions.webscripts.ScriptDebugger=off
# Repository
log4j.logger.org.alfresco.repo.web.scripts=warn
log4j.logger.org.alfresco.repo.web.scripts.BaseWebScriptTest=info
log4j.logger.org.alfresco.repo.web.scripts.AlfrescoRhinoScriptDebugger=off
log4j.logger.org.alfresco.repo.jscript=error
log4j.logger.org.alfresco.repo.jscript.ScriptLogger=warn
log4j.logger.org.alfresco.repo.cmis.rest.CMISTest=info
log4j.logger.org.alfresco.repo.domain.schema.script.ScriptBundleExecutorImpl=off
log4j.logger.org.alfresco.repo.domain.schema.script.ScriptExecutorImpl=info
log4j.logger.org.alfresco.repo.search.impl.solr.facet.SolrFacetServiceImpl=info
# Bulk Filesystem Import Tool
log4j.logger.org.alfresco.repo.bulkimport=warn
# Freemarker
# Note the freemarker.runtime logger is used to log non-fatal errors that are handled by Alfresco's retrying transaction handler
log4j.logger.freemarker.runtime=
# Metadata extraction
log4j.logger.org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter=warn
# Reduces PDFont error level due to ALF-7105
log4j.logger.org.apache.pdfbox.pdmodel.font.PDSimpleFont=fatal
log4j.logger.org.apache.pdfbox.pdmodel.font.PDFont=fatal
log4j.logger.org.apache.pdfbox.pdmodel.font.PDCIDFont=fatal
# no index support
log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexIndexer=fatal
log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexSearchService=fatal
# lucene index warnings
log4j.logger.org.alfresco.repo.search.impl.lucene.index.IndexInfo=warn
# Warn about RMI socket bind retries.
log4j.logger.org.alfresco.util.remote.server.socket.HostConfigurableSocketFactory=warn
log4j.logger.org.alfresco.repo.usage.RepoUsageMonitor=info
# Authorization
log4j.logger.org.alfresco.enterprise.repo.authorization.AuthorizationService=info
log4j.logger.org.alfresco.enterprise.repo.authorization.AuthorizationsConsistencyMonitor=warn
#-----------------------------------------------------------------------
# Platform module logging
#-----------------------------------------------------------------------
log4j.logger.com.inteligr8.alfresco.module.alfmarkdown=debug

View File

@ -0,0 +1,63 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<!--
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.
-->
<beans>
<!--
To support hot reloading of server side Javascript files in Share, we have to turn on development mode.
This setting will tell the Rhinoscript Processor not to compile and cache the JS files.
Cool, we can now change server side JS files and have the changes picked up,
without having to restart or refresh web scripts.
But… Due to a known bug in the Surf framework (ALF-9970) this will break the admin consoles in Share.
Override this bean and disable javascript compilation so that webscripts can be hot reloaded.
We have changed the 'compile' property from true to false.
-->
<bean id="javaScriptProcessor" class="org.alfresco.repo.jscript.RhinoScriptProcessor" init-method="register">
<property name="name">
<value>javascript</value>
</property>
<property name="extension">
<value>js</value>
</property>
<!-- Do not "compile javascript and cache compiled scripts" -->
<property name="compile">
<value>false</value>
</property>
<!-- allow sharing of sealed scopes for performance -->
<!-- disable to give each script it's own new scope which can be extended -->
<property name="shareSealedScopes">
<value>true</value>
</property>
<property name="scriptService">
<ref bean="scriptService"/>
</property>
<!-- Creates ScriptNodes which require the ServiceRegistry -->
<property name="serviceRegistry">
<ref bean="ServiceRegistry"/>
</property>
<property name="storeUrl">
<value>${spaces.store}</value>
</property>
<property name="storePath">
<value>${spaces.company_home.childname}</value>
</property>
</bean>
</beans>

View File

@ -0,0 +1,48 @@
# Enable hotswap so that changes in this module will be automatically reloaded
# Watch for changed class files on watchResources path and reload class definition in the running application.
autoHotswap=true
#autoHotswap.port=8000
# Add a directory prior to application classpath (load classes and resources).
#
# This may be useful for example in multi module maven project to load class changes from upstream project
# classes. Set extraClasspath to upstream project compiler output and .class file will have precedence to
# classes from built JAR file.
# i.e. monitor /target/classes
# should work with extraClasspath=${project.build.outputDirectory}
# If not try
extraClasspath=/usr/local/tomcat/hotswap-agent
# Comma separated list of disabled plugins
# Use plugin name - e.g.
# Hotswapper, AnonymousClassPatch, WatchResources, Hibernate, Spring, Jersey2, Jetty, Tomcat,
# ZK, Logback, JSF, Seam, ELResolver, OsgiEquinox, Proxy, WebObjects, Weld, JBossModules, Resteasy, Gae
disabledPlugins=Hibernate,Spring
# Add a directory prior to webapp path (load webapp resources).
#
# Load web application resources (such as HTML, JSP, CSS, ...) from this directory prior to default processing.
# Use this setting to set to serve resources from source directory directly (e.g. src/main/webapp).
extraWebappContext=/usr/local/tomcat/hotswap-agent/alfmarkdown-platform/target/classes/META-INF/resources;
# Load static web resources from different directory.
#
# This setting is dependent on application server plugin(Jetty, Tomcat, JBoss, ...)
webappDir=/usr/local/tomcat/hotswap-agent/alfmarkdown-platform/target/classes/META-INF/resources;
# Watch for changes in a directory (resources only).
#
# Similar to extraClasspath this property adds classpath when searching for resources (not classes).
# While extra classpath just modifies the classloader, this setting does nothing until the resource
# is really changed.
#
# Sometimes it is not possible to point extraClasspath to your i.e. src/main/resources, because there are multiple
# replacements of resources in a building step (maven filtering resource option).
# This setting will leave i.e. src/target/classes as default source for resources, but after the resource is modified
# in src/main/resources, the new changed resource is served instead.
# watchResources=
LOGGER.org.hotswap.agent=DEBUG
#LOGGER.org.hotswap.agent.plugin=TRACE
#LOGGER.org.hotswap.agent.watch=TRACE
#LOGGER.org.hotswap.agent.command=TRACE

View File

@ -0,0 +1,6 @@
# Enterprise License location
Put the Alfresco Enterprise license file in this directory.
It will then be copied into the ACS container in the
$TOMCAT_DIR/WEB-INF/classes/alfresco/extension/license directory.

46
pom.xml Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
<name>AlfMarkdown</name>
<description>A Markdown suite of extensions for Alfresco</description>
<packaging>pom</packaging>
<properties>
<alfresco.sdk.version>4.1.0</alfresco.sdk.version>
<edition>community</edition>
<alfresco.platform.version>6.2.0-ga</alfresco.platform.version>
<alfresco.share.version>6.2.2.2</alfresco.share.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<modules>
<module>tengine</module>
<module>repo</module>
<module>platform-webapp</module>
<module>share</module>
<module>share-webapp</module>
</modules>
<!-- Alfresco Maven Repositories -->
<repositories>
<repository>
<id>alfresco-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>alfresco-plugin-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</pluginRepository>
</pluginRepositories>
</project>

79
rad.sh Normal file
View File

@ -0,0 +1,79 @@
#!/bin/sh
DOCKER_CONTAINER_NAME_PREFIX=alfmarkdown
if [ -z "${M2_HOME}" ]; then
export MVN_EXEC="mvn"
else
export MVN_EXEC="${M2_HOME}/bin/mvn"
fi
start() {
$MVN_EXEC clean package
$MVN_EXEC -pl $1 integration-test
}
stop() {
docker container stop $(docker container ls -q --filter name=$DOCKER_CONTAINER_NAME_PREFIX)
docker container rm $(docker container ls -aq --filter name=$DOCKER_CONTAINER_NAME_PREFIX)
}
reload() {
docker container stop $(docker container ls -q --filter name=$DOCKER_CONTAINER_NAME_PREFIX-.*-$1)
docker container start $(docker container ls -q --filter name=$DOCKER_CONTAINER_NAME_PREFIX-.*-$1)
}
list() {
docker container ls --filter name=$DOCKER_CONTAINER_NAME_PREFIX
}
tail() {
docker container logs $2 $(docker container ls -q --filter name=$DOCKER_CONTAINER_NAME_PREFIX-.*-$1)
}
case "$1" in
status)
list
;;
start)
if [ -z "$2" ]; then
echo "Usage: $0 start <project_folder>"
$MVN_EXEC -q --also-make exec:exec -Dexec.executable="pwd" | sed 's~/mnt/data/home/brian/Code/git/alfresco/alfmarkdown/\?\(.*\)~\1~'
else
start $2
fi
;;
stop)
stop
;;
reload)
if [ -z "$2" ]; then
echo "Usage: $0 restart <container_suffix>"
docker container ls --filter name=$DOCKER_CONTAINER_NANE_PREFIX --format "{{.Names}}"
else
restart $2
fi
;;
follow)
if [ -z "$2" ]; then
echo "Usage: $0 follow <container_suffix>"
docker container ls --filter name=$DOCKER_CONTAINER_NANE_PREFIX --format "{{.Names}}"
else
tail $2 "-f"
fi
;;
tail)
if [ -z "$2" ]; then
echo "Usage: $0 tail <container_suffix> [ since ]"
echo " Example since: 40m (for 40 minutes into history)"
docker container ls --filter name=$DOCKER_CONTAINER_NANE_PREFIX --format "{{.Names}}"
elif [ -z "$3" ]; then
tail $2 "--tail 20"
else
tail $2 "--since $3"
fi
;;
*)
echo "Usage: $0 { status | start <project_folder> | stop | reload <container_suffix> | follow <container_suffix> | tail <container_suffix> [ since ] }"
esac

View File

@ -1,64 +0,0 @@
buildscript {
repositories {
jcenter()
mavenLocal()
}
dependencies {
classpath group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.3.6'
classpath group: 'com.parashift.amp', name: 'amp-plugin', version: '1.0-SNAPSHOT'
}
}
apply plugin: 'alfresco-amp'
allprojects {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
}
}
version = "1.0.0"
ext {
alfresco = [:]
alfresco.version = "5.0.1"
}
repositories {
mavenCentral()
maven { url "https://maven.alfresco.com/nexus/content/groups/public/" }
maven {
credentials {
username project['alfresco.repo.private.username']
password project['alfresco.repo.private.password']
}
url "https://maven.alfresco.com/nexus/content/groups/private/"
}
mavenLocal()
flatDir name: 'localRepository', dirs: 'lib'
}
configurations {
all*.exclude group: 'maven-plugins'
all*.exclude group: 'org.jvnet.staxex'
}
dependencies {
compile (group: "org.alfresco", name: "alfresco", version: "${alfresco.version}", classifier: "classes")
compile 'org.slf4j:slf4j-api:1.7.5'
}
amp {
id = "com.parashift." + project.name
baseName = project.name
alias = project.name
version = project.version
title = project.title
description = project.description
addLibDir("ampLib")
}

View File

@ -1,2 +0,0 @@
title=Markdown Preview Repo
description=Allows Markdown files to be Previewed in Share

65
repo/pom.xml Normal file
View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfmarkdown-platform</artifactId>
<name>Alfmarkdown Platform JAR Module</name>
<packaging>jar</packaging>
<parent>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
<ate.docker.image.name>inteligr8/alfmarkdown-tengine</ate.docker.image.name>
<ate.docker.image.tag>${project.version}</ate.docker.image.tag>
<ate.debugger.port>8001</ate.debugger.port>
</properties>
<dependencies>
<dependency>
<groupId>de.fmaul</groupId>
<artifactId>javascript-console-repo</artifactId>
<version>0.6.0</version>
<type>amp</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-repository</artifactId>
<version>8.98</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>com.inteligr8.alfresco:beedk-ate-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-lts-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-platform-module-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8:maven-private-deploy-tile:[1.0.0,2.0.0)</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>inteligr8-releases</id>
<url>http://repos.yateslong.us/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
</project>

View File

@ -1 +0,0 @@
rootProject.name = "parashift-mdpreview-repo"

View File

@ -0,0 +1,13 @@
{
"renditions": [
{
"renditionName": "flexmark-md-html",
"targetMediaType": "text/html"
},
{
"renditionName": "commonmark-md-html",
"targetMediaType": "text/html",
"options": [ { "name": "engine", "value": "commonmark" } ]
}
]
}

View File

@ -19,7 +19,6 @@ import java.util.Map;
/** /**
* Created by cetra on 30/08/2016. * Created by cetra on 30/08/2016.
*/ */
@Component(value = "webscript.mdpreview.path.get") @Component(value = "webscript.mdpreview.path.get")
public class ContentGet extends AbstractWebScript { public class ContentGet extends AbstractWebScript {

View File

@ -0,0 +1,2 @@
log4j.logger.com.parashift.mdpreview=info
log4j.logger.com.inteligr8.alfresco.model.alfmarkdown=info

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<model name="mta:dataModel"
xmlns="http://www.alfresco.org/model/dictionary/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.alfresco.org/model/dictionary/1.0 https://raw.githubusercontent.com/Alfresco/alfresco-repository/master/src/main/resources/alfresco/model/modelSchema.xsd">
<description>MTA Data Model</description>
<author>Brian Long</author>
<version>1.0</version>
<imports>
<!-- Import Alfresco Dictionary Definitions -->
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
<!-- Import Alfresco System Model Definitions -->
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
</imports>
<namespaces>
<namespace uri="http://www.mta.info/alfresco/model/1.0" prefix="mta"/>
</namespaces>
<constraints>
<constraint name="mta:ptcWg" type="LIST">
<parameter name="allowedValues">
<list>
<value></value>
<value>Communications</value>
<value>Onboard</value>
<value>Safety</value>
<value>System Engineering</value>
<value>Test and Commissioning - 1 SAT</value>
<value>Test and Commissioning - 2 FAT</value>
<value>Training</value>
</list>
</parameter>
</constraint>
</constraints>
<aspects>
<aspect name="mta:submittal">
<title>MTA Submittal</title>
<properties>
<property name="mta:submittalName">
<title>Name</title>
<type>d:text</type>
<mandatory>true</mandatory>
<index enabled="true">
<tokenised>false</tokenised>
<facetable>false</facetable>
</index>
</property>
<property name="mta:submittalDocNum">
<title>Document #</title>
<type>d:int</type>
<mandatory>true</mandatory>
<index enabled="true">
<tokenised>false</tokenised>
<facetable>false</facetable>
</index>
</property>
<property name="mta:submittalRevNum">
<title>Revision #</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>true</tokenised>
<facetable>true</facetable>
</index>
</property>
<property name="mta:submittalStatusSummary">
<title>Status Summary #</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>true</tokenised>
<facetable>true</facetable>
</index>
</property>
</properties>
</aspect>
<aspect name="mta:ptcDoc">
<title>MTA PTC Document</title>
<properties>
<property name="mta:ptcEquipCat">
<title>Equipment Category</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>true</tokenised>
<facetable>false</facetable>
</index>
</property>
<property name="mta:ptcCdrlNum">
<title>CDRL #</title>
<type>d:text</type>
<mandatory>false</mandatory>
<index enabled="true">
<tokenised>false</tokenised>
<facetable>false</facetable>
</index>
</property>
<property name="mta:ptcWg">
<title>WG</title>
<type>d:text</type>
<mandatory>true</mandatory>
<index enabled="true">
<tokenised>false</tokenised>
<facetable>true</facetable>
</index>
<constraints>
<constraint ref="mta:ptcWg"/>
</constraints>
</property>
</properties>
<mandatory-aspects>
<aspect>mta:submittal</aspect>
</mandatory-aspects>
</aspect>
</aspects>
</model>

View File

@ -0,0 +1,11 @@
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.parashift.mdpreview" />
</beans>

View File

@ -0,0 +1,5 @@
module.id=${project.artifactId}
#module.aliases=myModule-123, my-module
module.title=${project.name}
module.description=${project.description}
module.version=${project.version}

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.parashift.mdpreview" />
</beans>

74
share-webapp/pom.xml Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfmarkdown-share-webapp</artifactId>
<name>Alfmarkdown Share Web Application</name>
<packaging>pom</packaging>
<parent>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<developers>
<developer>
<id>brian.long</id>
<name>Brian Long</name>
<email>brian@inteligr8.com</email>
</developer>
</developers>
<properties>
<project.sibling.build.directory>${basedir}/../platform-webapp/target</project.sibling.build.directory>
<project.sibling.build.warDirectory>${project.sibling.build.directory}/war</project.sibling.build.warDirectory>
<project.sibling.build.warFile>${project.sibling.build.warDirectory}/content-services-community-${alfresco.platform.version}.war</project.sibling.build.warFile>
<ate.docker.image.name>inteligr8/alfmarkdown-tengine</ate.docker.image.name>
<ate.docker.image.tag>${project.version}</ate.docker.image.tag>
<ate.debugger.port>8001</ate.debugger.port>
</properties>
<dependencies>
<dependency>
<groupId>de.fmaul</groupId>
<artifactId>javascript-console-share</artifactId>
<version>0.6.0</version>
<type>amp</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>alfmarkdown-share</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>com.inteligr8.alfresco:beedk-ate-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-lts-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-platform-sibling-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-share-webapp-tile:1.0-SNAPSHOT</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>inteligr8-releases</id>
<url>http://repos.yateslong.us/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,16 @@
FROM ${docker.share.image}:${alfresco.share.version}
ARG TOMCAT_DIR=/usr/local/tomcat
# Copy Dockerfile to avoid an error if no JARs exist
COPY Dockerfile extensions/*.jar $TOMCAT_DIR/webapps/share/WEB-INF/lib/
# Copy Dockerfile to avoid an error if no AMPs exist
COPY Dockerfile extensions/*.amp $TOMCAT_DIR/amps_share/
RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install \
$TOMCAT_DIR/amps_share $TOMCAT_DIR/webapps/share -directory -nobackup -force
COPY share-config-custom.xml $TOMCAT_DIR/shared/classes/alfresco/web-extension
COPY log4j.properties $TOMCAT_DIR/shared/classes
COPY hotswap-agent.properties $TOMCAT_DIR/shared/classes

View File

@ -0,0 +1,49 @@
# Enable hotswap so that changes in this module will be automatically reloaded
# Watch for changed class files on watchResources path and reload class definition in the running application.
autoHotswap=true
#autoHotswap.port=8000
# Add a directory prior to application classpath (load classes and resources).
#
# This may be useful for example in multi module maven project to load class changes from upstream project
# classes. Set extraClasspath to upstream project compiler output and .class file will have precedence to
# classes from built JAR file.
# i.e. monitor /target/classes
# should work with extraClasspath=${project.build.outputDirectory}
# If not try
extraClasspath=/usr/local/tomcat/hotswap-agent/target/classes
# Comma separated list of disabled plugins
# Use plugin name - e.g.
# Hotswapper, AnonymousClassPatch, WatchResources, Hibernate, Spring, Jersey2, Jetty, Tomcat,
# ZK, Logback, JSF, Seam, ELResolver, OsgiEquinox, Proxy, WebObjects, Weld, JBossModules, Resteasy, Gae
disabledPlugins=Hibernate,Spring
# Add a directory prior to webapp path (load webapp resources).
#
# Load web application resources (such as HTML, JSP, CSS, ...) from this directory prior to default processing.
# Use this setting to set to serve resources from source directory directly (e.g. src/main/webapp).
extraWebappContext=/usr/local/tomcat/hotswap-agent/target/classes/META-INF;
# Load static web resources from different directory.
#
# This setting is dependent on application server plugin(Jetty, Tomcat, JBoss, ...)
webappDir=/usr/local/tomcat/hotswap-agent/target/classes/META-INF;
# Watch for changes in a directory (resources only).
#
# Similar to extraClasspath this property adds classpath when searching for resources (not classes).
# While extra classpath just modifies the classloader, this setting does nothing until the resource
# is really changed.
#
# Sometimes it is not possible to point extraClasspath to your i.e. src/main/resources, because there are multiple
# replacements of resources in a building step (maven filtering resource option).
# This setting will leave i.e. src/target/classes as default source for resources, but after the resource is modified
# in src/main/resources, the new changed resource is served instead.
# watchResources=
LOGGER.org.hotswap.agent=DEBUG
#LOGGER.org.hotswap.agent.plugin=TRACE
#LOGGER.org.hotswap.agent.watch=TRACE
#LOGGER.org.hotswap.agent.command=TRACE

View File

@ -0,0 +1,54 @@
# Set root logger level to error
log4j.rootLogger=error, Console, File
# Console appender definition #
# All outputs currently set to be a ConsoleAppender.
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
# use log4j NDC to replace %x with tenant domain / username
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} %x %-5p [%c{3}] [%t] %m%n
#log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n
# File appender definition #
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=share.log
log4j.appender.File.Append=true
log4j.appender.File.DatePattern='.'yyyy-MM-dd
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n
# Spring
log4j.logger.org.springframework=warn
# Turn off Spring remoting warnings that should really be info or debug.
log4j.logger.org.springframework.remoting.support=error
log4j.logger.org.springframework.util=error
# MyFaces
log4j.logger.org.apache.myfaces.util.DebugUtils=info
log4j.logger.org.apache.myfaces.el.VariableResolverImpl=error
log4j.logger.org.apache.myfaces.application.jsp.JspViewHandlerImpl=error
log4j.logger.org.apache.myfaces.taglib=error
# Alfresco
log4j.logger.org.alfresco=error
log4j.logger.org.alfresco.config=warn
log4j.logger.org.alfresco.config.JndiObjectFactoryBean=warn
log4j.logger.org.alfresco.web=info
# Web Framework
log4j.logger.org.springframework.extensions.webscripts=info
log4j.logger.org.springframework.extensions.webscripts.ScriptLogger=warn
log4j.logger.org.springframework.extensions.webscripts.ScriptDebugger=off
# Freemarker
# Note the freemarker.runtime logger is used to log non-fatal errors that are handled by Alfresco's retrying transaction handler
log4j.logger.freemarker.runtime=
#-----------------------------------------------------------------------
# Custom Share module logging goes here...
#-----------------------------------------------------------------------
log4j.logger.com.inteligr8.alfresco.module.alfmarkdown=debug

View File

@ -0,0 +1,105 @@
<alfresco-config>
<config evaluator="string-compare" condition="WebFramework">
<web-framework>
<autowire>
<!-- Changing this to 'development' currently breaks the Admin Console.
Instead we make a POST to clear Share dependency caches, see 'clear-caches-refresh-ws' profile. -->
<mode>production</mode> <!-- not really need in the long run, used for YUI - deprecate -->
</autowire>
<!--
We don't need to do this when we have the new refresh mojos in the Alfresco plug-in.
If resource caching has been disabled then all the dependency caches will be cleared
before processing the Aikau jsonModel request...
(i.e. this.dojoDependencyHandler.clearCaches() )
For more information see the Aikau source code: https://github.com/Alfresco/Aikau
-->
<disable-resource-caching>false</disable-resource-caching>
</web-framework>
</config>
<!-- Global config section -->
<config replace="true">
<flags>
<!--
Developer debugging setting to turn on DEBUG mode for client scripts in the browser
-->
<client-debug>true</client-debug>
<!--
LOGGING can always be toggled at runtime when in DEBUG mode (Ctrl, Ctrl, Shift, Shift).
This flag automatically activates logging on page load.
-->
<client-debug-autologging>false</client-debug-autologging>
</flags>
</config>
<!--
Disable CSRF completely for now
It seems Share has issues on 4.2.x with the embedded tomcat and CSRFPolicy
-->
<config evaluator="string-compare" condition="CSRFPolicy" replace="true">
<filter/>
</config>
<!--
Change so it is picked up from property where the Alfresco Repo Webapp is running
(e.g. http://localhost:8080/alfresco)
-->
<config evaluator="string-compare" condition="Remote">
<remote>
<endpoint>
<id>alfresco-noauth</id>
<name>Alfresco - unauthenticated access</name>
<description>Access to Alfresco Repository WebScripts that do not require authentication</description>
<connector-id>alfresco</connector-id>
<endpoint-url>http://${acs.host}:8080/alfresco/s</endpoint-url>
<identity>none</identity>
</endpoint>
<endpoint>
<id>alfresco</id>
<name>Alfresco - user access</name>
<description>Access to Alfresco Repository WebScripts that require user authentication</description>
<connector-id>alfresco</connector-id>
<endpoint-url>http://${acs.host}:8080/alfresco/s</endpoint-url>
<identity>user</identity>
</endpoint>
<endpoint>
<id>alfresco-feed</id>
<name>Alfresco Feed</name>
<description>Alfresco Feed - supports basic HTTP authentication via the EndPointProxyServlet</description>
<connector-id>http</connector-id>
<endpoint-url>http://${acs.host}:8080/alfresco/s</endpoint-url>
<basic-auth>true</basic-auth>
<identity>user</identity>
</endpoint>
<endpoint>
<id>activiti-admin</id>
<name>Activiti Admin UI - user access</name>
<description>Access to Activiti Admin UI, that requires user authentication</description>
<connector-id>activiti-admin-connector</connector-id>
<endpoint-url>http://${acs.host}:8080/alfresco/activiti-admin</endpoint-url>
<identity>user</identity>
</endpoint>
<endpoint>
<id>alfresco-api</id>
<parent-id>alfresco</parent-id>
<name>Alfresco Public API - user access</name>
<description>Access to Alfresco Repository Public API that require user authentication.
This makes use of the authentication that is provided by parent 'alfresco' endpoint.</description>
<connector-id>alfresco</connector-id>
<endpoint-url>http://${acs.host}:8080/alfresco/api</endpoint-url>
<identity>user</identity>
</endpoint>
</remote>
</config>
</alfresco-config>

View File

@ -30,7 +30,7 @@ configurations {
all*.exclude group: 'maven-plugins' all*.exclude group: 'maven-plugins'
} }
version = "1.0.0" version = "1.1.1"
ext { ext {
alfresco = [:] alfresco = [:]

71
share/pom.xml Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfmarkdown-share</artifactId>
<name>Alfmarkdown Share JAR Module</name>
<packaging>jar</packaging>
<parent>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<properties>
<project.sibling.build.directory>${basedir}/../repo/target</project.sibling.build.directory>
<project.sibling.build.warDirectory>${project.sibling.build.directory}/war</project.sibling.build.warDirectory>
<project.sibling.build.warFile>${project.sibling.build.warDirectory}/content-services-community-${alfresco.platform.version}.war</project.sibling.build.warFile>
<ate.docker.image.name>inteligr8/alfmarkdown-tengine</ate.docker.image.name>
<ate.docker.image.tag>${project.version}</ate.docker.image.tag>
<ate.debugger.port>8001</ate.debugger.port>
</properties>
<dependencies>
<dependency>
<groupId>de.fmaul</groupId>
<artifactId>javascript-console-share</artifactId>
<version>0.6.0</version>
<type>amp</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>share</artifactId>
<version>${alfresco.share.version}</version>
<classifier>classes</classifier>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>com.inteligr8.alfresco:beedk-ate-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-lts-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-platform-sibling-it-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-acs-share-module-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8:maven-private-deploy-tile:[1.0.0,2.0.0)</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>inteligr8-releases</id>
<url>http://repos.yateslong.us/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,37 @@
<alfresco-config>
<!-- not yet implemented
<config evaluator="string-compare" condition="DocumentLibrary">
<create-content>
<content id="markdown" label="create-content.md" type="pagelink" index="25">
<param name="page">markdown-edit?destination={nodeRef}</param>
</content>
</create-content>
</config>
-->
<config evaluator="string-compare" condition="DocLibActions">
<actions>
<action id="document-markdown-edit" type="pagelink" label="actions.document.markdown-edit">
<param name="page">markdown-edit?nodeRef={node.nodeRef}</param>
<permissions>
<permission allow="true">Write</permission>
</permissions>
<evaluator>evaluator.doclib.action.markdownMimetype</evaluator>
<evaluator>evaluator.doclib.action.editableByCurrentUser</evaluator>
<evaluator negate="true">evaluator.doclib.action.isLocked</evaluator>
</action>
</actions>
<actionGroups>
<actionGroup id="document-browse">
<action index="90" id="document-markdown-edit" />
</actionGroup>
<actionGroup id="document-details">
<action index="90" id="document-markdown-edit" />
</actionGroup>
</actionGroups>
</config>
</alfresco-config>

View File

@ -15,9 +15,25 @@
<property name="configService" ref="web.config" /> <property name="configService" ref="web.config" />
<property name="configs"> <property name="configs">
<list> <list>
<value>classpath:alfresco/mdpreview-config.xml</value> <value>classpath:${alfresco.ext.path}/mdpreview-config.xml</value>
</list> </list>
</property> </property>
</bean> </bean>
<bean id="mdpreview.custom.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
<property name="resourceBundles">
<list>
<value>${alfresco.ext.package}.messages.mdpreview</value>
</list>
</property>
</bean>
<bean id="evaluator.doclib.action.markdownMimetype" parent="evaluator.doclib.action.isMimetype">
<property name="mimetypes">
<list>
<value>text/x-markdown</value>
</list>
</property>
</bean>
</beans> </beans>

View File

@ -0,0 +1,2 @@
create-content.md=Markdown...
actions.document.markdown-edit=Edit Markdown

View File

@ -0,0 +1,55 @@
<extension>
<modules>
<module>
<id>${project.artifactId} Markdown Preview</id>
<version>${project.version}</version>
<auto-deploy>true</auto-deploy>
<customizations>
<customization>
<targetPackageRoot>org.alfresco.components.preview</targetPackageRoot>
<sourcePackageRoot>com.parashift.markdown.preview-config</sourcePackageRoot>
<dependencies>
<js>/res/lib/highlightjs/hightlight.pack.js</js>
<js>/res/components/preview/MarkDown.js</js>
<js>/res/lib/highlightjs/hightlight-init.js</js>
<css>/res/lib/highlightjs/default.css</css>
<css>/res/components/preview/MarkDown.css</css>
</dependencies>
</customization>
<customization>
<targetPackageRoot>org.alfresco.components.documentlibrary</targetPackageRoot>
<sourcePackageRoot>com.parashift.markdown.preview-config</sourcePackageRoot>
<dependencies>
<js>/res/lib/highlightjs/hightlight.pack.js</js>
<js>/res/components/preview/MarkDown.js</js>
<js>/res/lib/highlightjs/hightlight-init.js</js>
<css>/res/highlightjs/default.css</css>
<css>/res/components/preview/MarkDown.css</css>
</dependencies>
</customization>
</customizations>
</module>
<module>
<id>Markdown-It Library</id>
<version>12.0.4</version>
<auto-deploy>true</auto-deploy>
<configurations>
<config evaluator="string-compare" condition="WebFramework" replace="false">
<web-framework>
<dojo-pages>
<packages>
<package name="markdown-it" location="lib/markdown-it" main="markdown-it.min" />
<package name="markdown-it-deflist" location="lib/markdown-it" main="markdown-it-deflist.min" />
<package name="markdown-it-emoji" location="lib/markdown-it" main="markdown-it-emoji.min" />
<package name="markdown-it-footnote" location="lib/markdown-it" main="markdown-it-footnote.min" />
<package name="markdown-it-ins" location="lib/markdown-it" main="markdown-it-ins.min" />
<package name="markdown-it-sub" location="lib/markdown-it" main="markdown-it-sub.min" />
<package name="markdown-it-sup" location="lib/markdown-it" main="markdown-it-sup.min" />
</packages>
</dojo-pages>
</web-framework>
</config>
</configurations>
</module>
</modules>
</extension>

View File

@ -0,0 +1,9 @@
<?xml version='1.0' encoding='UTF-8'?>
<page>
<title>Edit Markdown</title>
<title-id>page.markdown-edit.title</title-id>
<description>Edit Markdown</description>
<description-id>page.markdown-edit.description</description-id>
<template-instance>markdown-edit</template-instance>
<authentication>user</authentication>
</page>

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<template-instance>
<template-type>com/parashift/markdown-edit</template-type>
<components>
<!-- My Sites -->
<component>
<region-id>markdown-edit</region-id>
<url>/components/markdown-edit</url>
</component>
</components>
</template-instance>

View File

@ -0,0 +1,5 @@
<webscript>
<shortname>Markdown Edit</shortname>
<description>Allows a user to edit Markdown</description>
<url>/components/markdown-edit</url>
</webscript>

View File

@ -0,0 +1,3 @@
<#-- PLEASE NOTE:
<#-- Use of .head.ftl WebScript files has now been deprecated from WebScripts that render Share Components. -->
<#-- Dependencies are now loaded through the use of the <@script> and <@link> tags in the main .html.ftl file. -->

View File

@ -0,0 +1,41 @@
<@markup id="css" >
<#-- CSS Dependencies -->
<@link href="${url.context}/res/components/preview/MarkDown.css" group="markdown"/>
<@link href="${url.context}/res/components/markdown-edit.css" group="markdown"/>
<@link href="${url.context}/res/lib/highlightjs/default.css" group="markdown"/>
</@>
<@markup id="js">
<#-- JavaScript Dependencies -->
<@script src="${url.context}/res/lib/highlightjs/highlight.pack.js" group="markdown"/>
<@script src="${url.context}/res/components/markdown-edit.js" group="markdown"/>
<@script src="${url.context}/res/lib/highlightjs/highlight-init.js" group="markdown"/>
</@>
<@markup id="html">
<@uniqueIdDiv>
<div class="markdown-section">
<div class="markdown-editor" id="md-edit">
<h1>Editor:</h1>
<textarea class="markdown-text" id="md-text"></textarea>
</div>
<div class="markdown-preview" id="md-preview">
<h1>Preview:</h1>
<div class="markdown-body" id="md-body"></div>
</div>
</div>
<div class="markdown-save-back">
<div class="form-buttons">
<span class="yui-button yui-submit-button alf-primary-button">
<span class="first-child">
<button type="button" id="markdownSaveback">Save Markdown</button>
</span>
</span>
</div>
</div>
</@>
</@>

View File

@ -3,11 +3,11 @@ if (model.widgets)
for (var i = 0; i < model.widgets.length; i++) for (var i = 0; i < model.widgets.length; i++)
{ {
var widget = model.widgets[i]; var widget = model.widgets[i];
if (widget.id == "WebPreview") if (widget.id == "WebPreview" && model.proxy != "alfresco-noauth")
{ {
//We need to know some extra bits about the node, such as the repoPath to display images //We need to know some extra bits about the node, such as the repoPath to display images
pObj = eval('(' + remote.call("/slingshot/doclib2/node/" + url.args.nodeRef.replace(":/","")) + ')'); pObj = eval('(' + remote.call("/slingshot/doclib2/node/" + model.nodeRef.replace(":/","")) + ')');
//We check to see if the mime type is markdown, and if so, overwrite the conditions object. //We check to see if the mime type is markdown, and if so, overwrite the conditions object.
if(pObj.item && pObj.item.node && pObj.item.node.mimetype == "text/x-markdown") { if(pObj.item && pObj.item.node && pObj.item.node.mimetype == "text/x-markdown") {

View File

@ -0,0 +1,24 @@
<#include "../../org/alfresco/include/alfresco-template.ftl" />
<@templateHeader>
</@>
<@templateBody>
<@markup id="alf-hd">
<div id="alf-hd">
<@region scope="global" id="share-header" chromeless="true"/>
</div>
</@>
<@markup id="bd">
<div id="bd">
<@region id="markdown-edit" scope="template" />
</div>
</@>
</@>
<@templateFooter>
<@markup id="alf-ft">
<div id="alf-ft">
<@region id="footer" scope="global" />
</div>
</@>
</@>

View File

@ -0,0 +1,2 @@
log4j.logger.com.parashift.markdown=info
log4j.logger.com.inteligr8.alfresco.module.alfmarkdown=info

View File

@ -0,0 +1,4 @@
module.id=${project.artifactId}
module.title=${project.name}
module.description=${project.description}
module.version=${project.version}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,3 +0,0 @@
<alfresco-config>
<!-- Insert configuration here -->
</alfresco-config>

View File

@ -1,19 +0,0 @@
<extension>
<modules>
<module>
<id>Parashift Markdown Preview</id>
<version>1.0</version>
<auto-deploy>true</auto-deploy>
<customizations>
<customization>
<targetPackageRoot>org.alfresco.components.preview</targetPackageRoot>
<sourcePackageRoot>com.parashift.markdown.preview-config</sourcePackageRoot>
<dependencies>
<js>/res/components/preview/MarkDown.js</js>
<css>/res/components/preview/MarkDown.css</css>
</dependencies>
</customization>
</customizations>
</module>
</modules>
</extension>

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,35 @@
.markdown-section {
overflow: hidden;
border: 1px solid #ccc !important;
background-color: #fff;
margin: 10px 0;
box-shadow: 0.33px 2px 8px rgba(0, 0, 0, 0.1);
}
.markdown-section .markdown-body {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
border: 0px;
overflow-x: auto;
}
.markdown-editor, .markdown-preview {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box; /* Opera/IE 8+ */
float: left;
width: 50%;
padding: 5px;
}
.markdown-text {
width: 100% !important;
}
.markdown-section h1 {
border-bottom: 3px solid #ccc;
}

View File

@ -0,0 +1,107 @@
require(["dojo/dom", "dojo/query", "dojo/on", "dojo/request", "markdown-it", "markdown-it-deflist", "markdown-it-emoji", "markdown-it-footnote", "markdown-it-ins", "markdown-it-sub", "markdown-it-sup", "dojo/domReady!"],
function(dom, query, on, request, MarkdownIt, MarkdownItDefList, MarkdownItEmoji, MarkdownItFootnote, MarkdownItIns, MarkdownItSub, MarkdownItSup){
function resizeFrame(elem) {
elem.style.height = (window.innerHeight - 280) + "px";
}
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ""])[1].replace(/\+/g, '%20')) || null
}
var nodePath = getURLParameter("nodeRef").replace(":/","");
request.get(Alfresco.constants.PROXY_URI_RELATIVE + "/slingshot/doclib2/node/" + nodePath,{ handleAs: "json"}).then(function(nodeData) {
var locationPath = Alfresco.constants.PROXY_URI_RELATIVE + "markdown" + nodeData.item.location.repoPath + "/";
var mdOpts = {
html: true,
typographer: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}
return ''; // use external default escaping
}
};
var md = new MarkdownIt(mdOpts)
.use(new MarkdownItIns())
.use(new MarkdownItSub())
.use(new MarkdownItSuper())
.use(new MarkdownItEmoji())
.use(new MarkdownItFootnote())
.use(new MarkdownItDefList());
var translateImageSrc = function(source) {
return source.replace(/<img src="([^"]*)"/g, function(match, src) {
if(src.startsWith("http")) {
//if this includes external links, then don't change it.
return match;
} else {
//if it's a relative link, we need to use our webscript
return "<img src=\"" + locationPath + src + "\"";
}
});
};
var editorFrame = dom.byId("md-text");
var previewFrame = dom.byId("md-body");
var saveBack = dom.byId("markdownSaveback");
resizeFrame(editorFrame);
resizeFrame(previewFrame);
on(window, "resize", function() {
resizeFrame(editorFrame);
resizeFrame(previewFrame);
});
function updateMarkdown() {
previewFrame.innerHTML = md.render(editorFrame.value);
}
on(editorFrame, "change", updateMarkdown);
on(editorFrame, "keyup", updateMarkdown);
on(editorFrame, "paste", updateMarkdown);
request.get(Alfresco.constants.PROXY_URI_RELATIVE + "/api/node/content/" + nodePath).then(function(nodeContent) {
editorFrame.value = nodeContent;
updateMarkdown();
});
on(saveBack, "click", function() {
var postHeaders = {
"Content-Type" : "application/json"
}
if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled()) {
postHeaders[Alfresco.util.CSRFPolicy.getHeader()] = Alfresco.util.CSRFPolicy.getToken();
}
request.post(Alfresco.constants.PROXY_URI_RELATIVE + "api/node/" + nodePath + "/formprocessor", {
headers: postHeaders,
data : JSON.stringify({
prop_cm_content : editorFrame.value
})
}).then(function() {
Alfresco.util.PopupManager.displayMessage({"text": "Update Submitted"});
}, function (err) {
//Tries to find the exception from the error page and send a prompt
Alfresco.util.PopupManager.displayPrompt({"title": "Error Updating Alfresco"});
});
});
});
});

View File

@ -20,6 +20,7 @@
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
padding: 10px; padding: 10px;
margin-left: 3px; margin-left: 3px;
text-align: left;
} }
@ -300,6 +301,8 @@
.markdown-body li { .markdown-body li {
list-style: inside !important; list-style: inside !important;
float: none;
text-align: left;
} }
.markdown-body ul, .markdown-body ul,

View File

@ -25,18 +25,33 @@
//get the Div Element we'll be putting the Markdown //get the Div Element we'll be putting the Markdown
var divElem = document.getElementById(this.wp.id + "-body") var divElem = document.getElementById(this.wp.id + "-body")
//Execute Ajax request for content //Execute Ajax request for content
require(["dojo/request", "showdown"], function(request, showdown){ require(["dojo/request", "markdown-it", "markdown-it-ins", "markdown-it-sub", "markdown-it-sup", "markdown-it-emoji", "markdown-it-footnote", "markdown-it-deflist"],
function(request, MarkdownIt, MarkdownItIns, MarkdownItSub, MarkdownItSuper, MarkdownItEmoji, MarkdownItFootnote, MarkdownItDefList){
var mdOpts = {
html: true,
typographer: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}
return ''; // use external default escaping
}
};
var md = new MarkdownIt(mdOpts)
.use(new MarkdownItIns())
.use(new MarkdownItSub())
.use(new MarkdownItSuper())
.use(new MarkdownItEmoji())
.use(new MarkdownItFootnote())
.use(new MarkdownItDefList());
//Once we have the content, let's create a converter and add the html to the div element var translateImageSrc = function(source) {
converter = new showdown.Converter({
extensions: [
function() {
return [{
type: 'output',
filter: function(source) {
return source.replace(/<img src="([^"]*)"/g, function(match, src) { return source.replace(/<img src="([^"]*)"/g, function(match, src) {
if(src.startsWith("http")) { if(src.startsWith("http")) {
@ -47,21 +62,16 @@
return "<img src=\"" + locationPath + src + "\""; return "<img src=\"" + locationPath + src + "\"";
} }
}); });
} };
}]
}
]
});
request.get(Alfresco.constants.PROXY_URI_RELATIVE + node.contentURL).then(function(mdData) { request.get(Alfresco.constants.PROXY_URI_RELATIVE + node.contentURL).then(function(mdData) {
newHtml = converter.makeHtml(mdData); newHtml = md.render(mdData);
divElem.className = "markdown-body"; divElem.className = "markdown-body";
divElem.innerHTML = converter.makeHtml(mdData); divElem.innerHTML = newHtml;
}); });

View File

@ -0,0 +1,99 @@
/*
Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #F0F0F0;
}
/* Base color: saturation 0; */
.hljs,
.hljs-subst {
color: #444;
}
.hljs-comment {
color: #888888;
}
.hljs-keyword,
.hljs-attribute,
.hljs-selector-tag,
.hljs-meta-keyword,
.hljs-doctag,
.hljs-name {
font-weight: bold;
}
/* User color: hue: 0 */
.hljs-type,
.hljs-string,
.hljs-number,
.hljs-selector-id,
.hljs-selector-class,
.hljs-quote,
.hljs-template-tag,
.hljs-deletion {
color: #880000;
}
.hljs-title,
.hljs-section {
color: #880000;
font-weight: bold;
}
.hljs-regexp,
.hljs-symbol,
.hljs-variable,
.hljs-template-variable,
.hljs-link,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #BC6060;
}
/* Language color: hue: 90; */
.hljs-literal {
color: #78A960;
}
.hljs-built_in,
.hljs-bullet,
.hljs-code,
.hljs-addition {
color: #397300;
}
/* Meta color: hue: 200 */
.hljs-meta {
color: #1f7199;
}
.hljs-meta-string {
color: #4d99bf;
}
/* Misc effects */
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -0,0 +1,99 @@
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-quote {
color: #998;
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-subst {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-template-variable,
.hljs-tag .hljs-attr {
color: #008080;
}
.hljs-string,
.hljs-doctag {
color: #d14;
}
.hljs-title,
.hljs-section,
.hljs-selector-id {
color: #900;
font-weight: bold;
}
.hljs-subst {
font-weight: normal;
}
.hljs-type,
.hljs-class .hljs-title {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-name,
.hljs-attribute {
color: #000080;
font-weight: normal;
}
.hljs-regexp,
.hljs-link {
color: #009926;
}
.hljs-symbol,
.hljs-bullet {
color: #990073;
}
.hljs-built_in,
.hljs-builtin-name {
color: #0086b3;
}
.hljs-meta {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

View File

@ -0,0 +1 @@
hljs.initHighlightingOnLoad();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
/*!
markdown-it-deflist
https://github.com/markdown-it/markdown-it-deflist
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).markdownitDeflist=e()}}((function(){return function e(t,n,r){function i(f,d){if(!n[f]){if(!t[f]){var s="function"==typeof require&&require;if(!d&&s)return s(f,!0);if(o)return o(f,!0);var u=new Error("Cannot find module '"+f+"'");throw u.code="MODULE_NOT_FOUND",u}var a=n[f]={exports:{}};t[f][0].call(a.exports,(function(e){return i(t[f][1][e]||e)}),a,a.exports,e,t,n,r)}return n[f].exports}for(var o="function"==typeof require&&require,f=0;f<r.length;f++)i(r[f]);return i}({"/":[function(e,t,n){"use strict";t.exports=function(e){var t=e.utils.isSpace;function n(e,t){var n,r,i=e.bMarks[t]+e.tShift[t],o=e.eMarks[t];return i>=o||126!==(r=e.src.charCodeAt(i++))&&58!==r||i===(n=e.skipSpaces(i))||n>=o?-1:i}e.block.ruler.before("paragraph","deflist",(function(e,r,i,o){var f,d,s,u,a,l,p,k,c,h,b,y,m,g,C,I,v,_,w,x;if(o)return!(e.ddIndent<0)&&n(e,r)>=0;if((c=r+1)>=i)return!1;if(e.isEmpty(c)&&++c>=i)return!1;if(e.sCount[c]<e.blkIndent)return!1;if((d=n(e,c))<0)return!1;p=e.tokens.length,w=!0,(x=e.push("dl_open","dl",1)).map=l=[r,0],u=r,s=c;e:for(;;){for(_=!1,(x=e.push("dt_open","dt",1)).map=[u,u],(x=e.push("inline","",0)).map=[u,u],x.content=e.getLines(u,u+1,e.blkIndent,!1).trim(),x.children=[],x=e.push("dt_close","dt",-1);;){for((x=e.push("dd_open","dd",1)).map=a=[c,0],v=d,k=e.eMarks[s],h=e.sCount[s]+d-(e.bMarks[s]+e.tShift[s]);v<k&&(f=e.src.charCodeAt(v),t(f));)9===f?h+=4-h%4:h++,v++;if(d=v,I=e.tight,b=e.ddIndent,y=e.blkIndent,C=e.tShift[s],g=e.sCount[s],m=e.parentType,e.blkIndent=e.ddIndent=e.sCount[s]+2,e.tShift[s]=d-e.bMarks[s],e.sCount[s]=h,e.tight=!0,e.parentType="deflist",e.md.block.tokenize(e,s,i,!0),e.tight&&!_||(w=!1),_=e.line-s>1&&e.isEmpty(e.line-1),e.tShift[s]=C,e.sCount[s]=g,e.tight=I,e.parentType=m,e.blkIndent=y,e.ddIndent=b,x=e.push("dd_close","dd",-1),a[1]=c=e.line,c>=i)break e;if(e.sCount[c]<e.blkIndent)break e;if((d=n(e,c))<0)break;s=c}if(c>=i)break;if(u=c,e.isEmpty(u))break;if(e.sCount[u]<e.blkIndent)break;if((s=u+1)>=i)break;if(e.isEmpty(s)&&s++,s>=i)break;if(e.sCount[s]<e.blkIndent)break;if((d=n(e,s))<0)break}return x=e.push("dl_close","dl",-1),l[1]=c,e.line=c,w&&function(e,t){var n,r,i=e.level+2;for(n=t+2,r=e.tokens.length-2;n<r;n++)e.tokens[n].level===i&&"paragraph_open"===e.tokens[n].type&&(e.tokens[n+2].hidden=!0,e.tokens[n].hidden=!0,n+=2)}(e,p),!0}),{alt:["paragraph","reference","blockquote"]})}},{}]},{},[])("/")}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
/*! markdown-it-ins 3.0.1 https://github.com/markdown-it/markdown-it-mark @license MIT */
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).markdownitIns=n()}(this,(function(){"use strict";return function(e){function n(e,n){var t,o,s,i,r,l=[],f=n.length;for(t=0;t<f;t++)43===(s=n[t]).marker&&-1!==s.end&&(i=n[s.end],(r=e.tokens[s.token]).type="ins_open",r.tag="ins",r.nesting=1,r.markup="++",r.content="",(r=e.tokens[i.token]).type="ins_close",r.tag="ins",r.nesting=-1,r.markup="++",r.content="","text"===e.tokens[i.token-1].type&&"+"===e.tokens[i.token-1].content&&l.push(i.token-1));for(;l.length;){for(o=(t=l.pop())+1;o<e.tokens.length&&"ins_close"===e.tokens[o].type;)o++;t!==--o&&(r=e.tokens[o],e.tokens[o]=e.tokens[t],e.tokens[t]=r)}}e.inline.ruler.before("emphasis","ins",(function(e,n){var t,o,s,i,r=e.pos,l=e.src.charCodeAt(r);if(n)return!1;if(43!==l)return!1;if(s=(o=e.scanDelims(e.pos,!0)).length,i=String.fromCharCode(l),s<2)return!1;for(s%2&&(e.push("text","",0).content=i,s--),t=0;t<s;t+=2)e.push("text","",0).content=i+i,(o.can_open||o.can_close)&&e.delimiters.push({marker:l,length:0,jump:t/2,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close});return e.pos+=o.length,!0})),e.inline.ruler2.before("emphasis","ins",(function(e){var t,o=e.tokens_meta,s=(e.tokens_meta||[]).length;for(n(e,e.delimiters),t=0;t<s;t++)o[t]&&o[t].delimiters&&n(e,o[t].delimiters)}))}}));

View File

@ -0,0 +1,2 @@
/*! markdown-it-sub 1.0.0 https://github.com//markdown-it/markdown-it-sub @license MIT */
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.markdownitSub=e()}}(function(){return function e(r,o,n){function t(i,u){if(!o[i]){if(!r[i]){var f="function"==typeof require&&require;if(!u&&f)return f(i,!0);if(s)return s(i,!0);var p=new Error("Cannot find module '"+i+"'");throw p.code="MODULE_NOT_FOUND",p}var a=o[i]={exports:{}};r[i][0].call(a.exports,function(e){var o=r[i][1][e];return t(o?o:e)},a,a.exports,e,r,o,n)}return o[i].exports}for(var s="function"==typeof require&&require,i=0;i<n.length;i++)t(n[i]);return t}({1:[function(e,r){"use strict";function o(e,r){var o,t,s,i=e.posMax,u=e.pos;if(126!==e.src.charCodeAt(u))return!1;if(r)return!1;if(u+2>=i)return!1;for(e.pos=u+1;e.pos<i;){if(126===e.src.charCodeAt(e.pos)){o=!0;break}e.md.inline.skipToken(e)}return o&&u+1!==e.pos?(t=e.src.slice(u+1,e.pos),t.match(/(^|[^\\])(\\\\)*\s/)?(e.pos=u,!1):(e.posMax=e.pos,e.pos=u+1,s=e.push("sub_open","sub",1),s.markup="~",s=e.push("text","",0),s.content=t.replace(n,"$1"),s=e.push("sub_close","sub",-1),s.markup="~",e.pos=e.posMax+1,e.posMax=i,!0)):(e.pos=u,!1)}var n=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;r.exports=function(e){e.inline.ruler.after("emphasis","sub",o)}},{}]},{},[1])(1)});

View File

@ -0,0 +1,2 @@
/*! markdown-it-sup 1.0.0 https://github.com//markdown-it/markdown-it-sup @license MIT */
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.markdownitSup=e()}}(function(){return function e(r,o,n){function t(i,p){if(!o[i]){if(!r[i]){var u="function"==typeof require&&require;if(!p&&u)return u(i,!0);if(s)return s(i,!0);var f=new Error("Cannot find module '"+i+"'");throw f.code="MODULE_NOT_FOUND",f}var a=o[i]={exports:{}};r[i][0].call(a.exports,function(e){var o=r[i][1][e];return t(o?o:e)},a,a.exports,e,r,o,n)}return o[i].exports}for(var s="function"==typeof require&&require,i=0;i<n.length;i++)t(n[i]);return t}({1:[function(e,r){"use strict";function o(e,r){var o,t,s,i=e.posMax,p=e.pos;if(94!==e.src.charCodeAt(p))return!1;if(r)return!1;if(p+2>=i)return!1;for(e.pos=p+1;e.pos<i;){if(94===e.src.charCodeAt(e.pos)){o=!0;break}e.md.inline.skipToken(e)}return o&&p+1!==e.pos?(t=e.src.slice(p+1,e.pos),t.match(/(^|[^\\])(\\\\)*\s/)?(e.pos=p,!1):(e.posMax=e.pos,e.pos=p+1,s=e.push("sup_open","sup",1),s.markup="^",s=e.push("text","",0),s.content=t.replace(n,"$1"),s=e.push("sup_close","sup",-1),s.markup="^",e.pos=e.posMax+1,e.posMax=i,!0)):(e.pos=p,!1)}var n=/\\([ \\!"#$%&'()*+,.\/:;<=>?@[\]^_`{|}~-])/g;r.exports=function(e){e.inline.ruler.after("emphasis","sup",o)}},{}]},{},[1])(1)});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,26 @@
/*! showdown-github 03-06-2015 */
(function () {
'use strict';
var github = function () {
return [
{
type: 'lang',
regex: '(~T){2}([^~]+)(~T){2}',
replace: function (match, prefix, content) {
return '<del>' + content + '</del>';
}
}
];
};
if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
window.showdown.extensions.github = github;
}
if (typeof module !== 'undefined') {
module.exports = github;
}
}());
//# sourceMappingURL=showdown-github.js.map

View File

@ -0,0 +1,112 @@
/*! showdown-table 17-06-2015 */
/*
* Basic table support with re-entrant parsing, where cell content
* can also specify markdown.
*
* Tables
* ======
*
* | Col 1 | Col 2 |
* |======== |====================================================|
* |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
* | Plain | Value |
*
*/
(function () {
'use strict';
var table = function (converter) {
var tables = {}, style = 'text-align:left;', filter;
tables.th = function (header) {
if (header.trim() === '') {
return '';
}
var id = header.trim().replace(/ /g, '_').toLowerCase();
return '<th id="' + id + '" style="' + style + '">' + header + '</th>';
};
tables.td = function (cell) {
return '<td style="' + style + '">' + converter.makeHtml(cell) + '</td>';
};
tables.ths = function () {
var out = '',
i = 0,
hs = [].slice.apply(arguments);
for (i; i < hs.length; i += 1) {
out += tables.th(hs[i]) + '\n';
}
return out;
};
tables.tds = function () {
var out = '', i = 0, ds = [].slice.apply(arguments);
for (i; i < ds.length; i += 1) {
out += tables.td(ds[i]) + '\n';
}
return out;
};
tables.thead = function () {
var out,
hs = [].slice.apply(arguments);
out = '<thead>\n';
out += '<tr>\n';
out += tables.ths.apply(this, hs);
out += '</tr>\n';
out += '</thead>\n';
return out;
};
tables.tr = function () {
var out,
cs = [].slice.apply(arguments);
out = '<tr>\n';
out += tables.tds.apply(this, cs);
out += '</tr>\n';
return out;
};
filter = function (text) {
var i = 0, lines = text.split('\n'), line, hs, out = [];
for (i; i < lines.length; i += 1) {
line = lines[i];
if (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
var tbl = [];
tbl.push('<table>');
hs = line.substring(1, line.length - 1).split('|');
tbl.push(tables.thead.apply(this, hs));
line = lines[++i];
if (!line.trim().match(/^[|][-=|: ]+[|]$/)) {
line = lines[--i];
} else {
line = lines[++i];
tbl.push('<tbody>');
while (line.trim().match(/^[|].*[|]$/)) {
line = line.trim();
tbl.push(tables.tr.apply(this, line.substring(1, line.length - 1).split('|')));
line = lines[++i];
}
tbl.push('</tbody>');
tbl.push('</table>');
out.push(tbl.join('\n'));
continue;
}
}
out.push(line);
}
return out.join('\n');
};
return [
{
type: 'lang',
filter: filter
}
];
};
if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
window.showdown.extensions.table = table;
}
if (typeof module !== 'undefined') {
module.exports = table;
}
}());
//# sourceMappingURL=showdown-table.js.map

5143
share/src/main/web/showdown.js Executable file

File diff suppressed because it is too large Load Diff

114
tengine/pom.xml Normal file
View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>alfmarkdown-tengine</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.inteligr8.alfresco.module</groupId>
<artifactId>alfmarkdown</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<name>Alfmarkdown Alfresco T-Engine</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<alfresco.transform-base.version>2.3.6</alfresco.transform-base.version>
<spring-boot.version>2.3.5.RELEASE</spring-boot.version>
<commonmark.version>0.17.0</commonmark.version>
<flexmark.version>0.62.2</flexmark.version>
<docker.image.registry>docker.yateslong.us</docker.image.registry>
<docker.image.name>inteligr8/${project.artifactId}</docker.image.name>
</properties>
<dependencies>
<dependency>
<groupId>com.inteligr8.alfresco</groupId>
<artifactId>beedk-ate-springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-task-list-items</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-image-attributes</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark-ext-ins</artifactId>
<version>${commonmark.version}</version>
</dependency>
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-all</artifactId>
<version>${flexmark.version}</version>
</dependency>
<dependency>
<groupId>com.inteligr8.alfresco</groupId>
<artifactId>beedk-ate-springboot-test</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.inteligr8</groupId>
<artifactId>junit4-ext</artifactId>
<version>[1.0,2.0)</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>com.inteligr8.alfresco:beedk-ate-springboot-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8.alfresco:beedk-ate-docker-tile:1.0-SNAPSHOT</tile>
<tile>com.inteligr8:maven-private-deploy-tile:[1.0.0,2.0.0)</tile>
</tiles>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,28 @@
FROM docker.yateslong.us/inteligr8/ubuntu-jdk:20.04-11
# Set default user information
ARG JAR_FILE
ARG APPGROUPNAME=alfresco
ARG APPGROUPID=1000
ARG APPUSERNAME=ate
ARG APPUSERID=33001
ENV JAVA_OPTS="-Xmx128m"
ENV JAR_PATH=/usr/local/bin/${project.artifactId}.jar
COPY ${JAR_FILE} ${JAR_PATH}
# Install your engine's dependencies here
#RUN apt update && \
# apt -y install
RUN groupadd -g ${APPGROUPID} ${APPGROUPNAME} && \
useradd -u ${APPUSERID} -G ${APPGROUPNAME} ${APPUSERNAME} && \
chown ${APPUSERNAME}:${APPGROUPNAME} ${JAR_PATH}
EXPOSE 8090
USER ${APPUSERNAME}
ENTRYPOINT java ${JAVA_OPTS} -jar ${JAR_PATH}

View File

@ -0,0 +1,69 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package com.inteligr8.alfresco.module.alfmarkdown;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.event.EventListener;
import io.micrometer.core.instrument.MeterRegistry;
@SpringBootApplication
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
@EnableConfigurationProperties()
@ImportResource({"classpath*:application-context.xml"})
public class Application {
private final Logger logger = LoggerFactory.getLogger(Application.class);
@Value("${container.name}")
private String containerName;
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("containerName", this.containerName);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void startup() {
this.logger.info("Starting application components... Done");
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "transform.alfmarkdown." + CommonmarkConfig.ID)
public class CommonmarkConfig {
static final String ID = "commonmark";
private List<String> defaultExtensions;
public List<String> getDefaultExtensions() {
return this.defaultExtensions;
}
void setDefaultExtensions(List<String> defaultExtensions) {
this.defaultExtensions = defaultExtensions;
}
}

View File

@ -0,0 +1,183 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.executors.Transformer;
import org.commonmark.Extension;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.Renderer;
import org.commonmark.renderer.html.HtmlRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
@Component(CommonmarkConfig.ID)
public class CommonmarkTransformer implements Transformer {
private final Logger logger = LoggerFactory.getLogger(CommonmarkTransformer.class);
private final List<String> classSearchPrefixes = Arrays.asList("", "org.commonmark.ext.{name}.", "org.commonmark.ext.gfm.{name}.");
private final Pattern extClassNamePattern = Pattern.compile("[\\.]?(([A-Za-z0-9]+)Extension|[A-Za-z0-9]+)$");
@Autowired
private CommonmarkConfig config;
@PostConstruct
public void init() throws Exception {
if (this.logger.isDebugEnabled())
this.logger.debug("init()");
}
@Override
public String getTransformerId() {
return CommonmarkConfig.ID;
}
@Override
public void extractMetadata(String transformName, String sourceMimetype, String targetMimetype, Map<String, String> transformOptions, File sourceFile, File targetFile)
throws IOException {
if (this.logger.isTraceEnabled())
this.logger.trace("extractMetadata('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')");
throw new TransformException(HttpStatus.NOT_IMPLEMENTED.value(), "This transformer does not support meta-data extraction");
}
@Override
public void transform(String transformName, String sourceMimetype, String targetMimetype, Map<String, String> transformOptions, File sourceFile, File targetFile)
throws IOException {
if (this.logger.isTraceEnabled())
this.logger.trace("transform('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')");
if (!MediaType.TEXT_MARKDOWN_VALUE.equals(sourceMimetype))
throw new TransformException(HttpStatus.BAD_REQUEST.value(), "This transformer does not support source data of the '" + sourceMimetype + "' type");
List<Extension> extensions = this.gatherExtensions(transformOptions);
Parser parser = Parser.builder().extensions(extensions).build();
Renderer renderer;
switch (targetMimetype) {
case MediaType.TEXT_HTML_VALUE:
renderer = HtmlRenderer.builder().extensions(extensions).build();
break;
default:
throw new TransformException(HttpStatus.BAD_REQUEST.value(), "This transformer does not support target data of the '" + targetMimetype + "' type");
}
FileWriter fwriter = new FileWriter(targetFile, false);
try {
FileReader freader = new FileReader(sourceFile);
try {
Node mddoc = parser.parseReader(freader);
renderer.render(mddoc, fwriter);
} finally {
freader.close();
}
} finally {
fwriter.close();
}
}
private List<Extension> gatherExtensions(Map<String, String> transformOptions) {
// include default extensions
Set<String> extClassNames = new HashSet<>();
if (this.config.getDefaultExtensions() != null)
extClassNames.addAll(this.config.getDefaultExtensions());
// include/exclude based on passed in extensions
String extClassNamesRaw = transformOptions.get(RequestParamConstants.EXT_CLASS_NAMES);
if (extClassNamesRaw != null) {
for (String extClassName : extClassNamesRaw.split(",")) {
extClassName = extClassName.trim();
if (extClassName.length() > 0) {
if (extClassName.startsWith("!")) {
// exclude those that start with !
extClassNames.remove(extClassName.substring(1));
} else {
// include the rest
extClassNames.add(extClassName);
}
}
}
}
List<Extension> exts = new ArrayList<>(extClassNames.size());
// create the extension classes using reflection
for (String extClassName : extClassNames) {
Class<?> extClass = this.findClass(extClassName);
if (extClass != null) {
Extension ext = this.createExtension(extClass);
if (ext != null)
exts.add(ext);
}
}
return exts;
}
private Class<?> findClass(String className) {
Matcher matcher = this.extClassNamePattern.matcher(className);
String extName = matcher.find() ? matcher.group(2) : null;
String extPackageName = extName != null ? this.camel2package(extName) : null;
for (String classPrefix : this.classSearchPrefixes) {
if (extPackageName != null)
classPrefix = classPrefix.replaceAll("\\{name\\}", extPackageName);
try {
Class<?> extClass = Class.forName(classPrefix + className);
return extClass;
} catch (ClassNotFoundException cnfe) {
// suppress
}
}
return null;
}
private Extension createExtension(Class<?> extClass) {
try {
// finding public static method, so using "DeclaredMethod" instead of "Method"
Method createMethod = extClass.getDeclaredMethod("create");
// calling public static method, so no instance (null)
return (Extension)createMethod.invoke(null);
} catch (NoSuchMethodException nsme) {
this.logger.warn("The '" + extClass.getName() + "' extension class must have a public static 'create' method");
} catch (InvocationTargetException ite) {
this.logger.warn("The '" + extClass.getName() + "' extension class 'create' method encountered an unexpected exception: " + ite.getMessage());
} catch (IllegalAccessException iae) {
this.logger.warn("The '" + extClass.getName() + "' extension class 'create' method is not public: " + iae.getMessage());
}
return null;
}
private String camel2package(String str) {
StringJoiner joiner = new StringJoiner(".");
Pattern pattern = Pattern.compile("[A-Z][^A-Z]+");
Matcher matcher = pattern.matcher(str);
while (matcher.find())
joiner.add(matcher.group().toLowerCase());
return joiner.toString();
}
}

View File

@ -0,0 +1,29 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "transform.alfmarkdown")
public class Config {
private FlexmarkConfig flexmark;
private CommonmarkConfig commonmark;
public FlexmarkConfig getFlexmark() {
return this.flexmark;
}
void setFlexmark(FlexmarkConfig flexmark) {
this.flexmark = flexmark;
}
public CommonmarkConfig getCommonmark() {
return this.commonmark;
}
void setCommonmark(CommonmarkConfig commonmark) {
this.commonmark = commonmark;
}
}

View File

@ -0,0 +1,33 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "transform.alfmarkdown." + FlexmarkConfig.ID)
public class FlexmarkConfig {
static final String ID = "flexmark";
private String defaultProfile;
private List<String> defaultExtensions;
public String getDefaultProfile() {
return this.defaultProfile;
}
void setDefaultProfile(String defaultProfile) {
this.defaultProfile = defaultProfile;
}
public List<String> getDefaultExtensions() {
return this.defaultExtensions;
}
void setDefaultExtensions(List<String> defaultExtensions) {
this.defaultExtensions = defaultExtensions;
}
}

View File

@ -0,0 +1,179 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.executors.Transformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.parser.ParserEmulationProfile;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.ast.IRender;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.util.misc.Extension;
@Component(FlexmarkConfig.ID)
public class FlexmarkTransformer implements Transformer {
private final Logger logger = LoggerFactory.getLogger(FlexmarkTransformer.class);
private final List<String> classSearchPrefixes = Arrays.asList("", "com.vladsch.flexmark.ext.{name}.", "com.vladsch.flexmark.ext.");
private final Pattern extClassNamePattern = Pattern.compile("[\\.]?(([A-Za-z0-9]+)Extension|[A-Za-z0-9]+)$");
@Autowired
private FlexmarkConfig config;
@PostConstruct
public void init() throws Exception {
if (this.logger.isDebugEnabled())
this.logger.debug("init()");
}
@Override
public String getTransformerId() {
return FlexmarkConfig.ID;
}
@Override
public void extractMetadata(String transformName, String sourceMimetype, String targetMimetype, Map<String, String> transformOptions, File sourceFile, File targetFile)
throws IOException {
if (this.logger.isTraceEnabled())
this.logger.trace("extractMetadata('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')");
throw new TransformException(HttpStatus.NOT_IMPLEMENTED.value(), "This transformer does not support meta-data extraction");
}
@Override
public void transform(String transformName, String sourceMimetype, String targetMimetype, Map<String, String> transformOptions, File sourceFile, File targetFile)
throws IOException {
if (this.logger.isTraceEnabled())
this.logger.trace("transform('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')");
if (!MediaType.TEXT_MARKDOWN_VALUE.equals(sourceMimetype))
throw new TransformException(HttpStatus.BAD_REQUEST.value(), "This transformer does not support source data of the '" + sourceMimetype + "' type");
String profile = transformOptions.getOrDefault(RequestParamConstants.PROFILE, this.config.getDefaultProfile());
MutableDataSet options = new MutableDataSet();
options.setFrom(ParserEmulationProfile.valueOf(profile.toUpperCase()));
options.set(Parser.EXTENSIONS, this.gatherExtensions(transformOptions));
Parser parser = Parser.builder(options).build();
IRender renderer;
switch (targetMimetype) {
case MediaType.TEXT_HTML_VALUE:
renderer = HtmlRenderer.builder(options).build();
break;
default:
throw new TransformException(HttpStatus.BAD_REQUEST.value(), "This transformer does not support target data of the '" + targetMimetype + "' type");
}
FileWriter fwriter = new FileWriter(targetFile, false);
try {
FileReader freader = new FileReader(sourceFile);
try {
Document mddoc = parser.parseReader(freader);
renderer.render(mddoc, fwriter);
} finally {
freader.close();
}
} finally {
fwriter.close();
}
}
private List<Extension> gatherExtensions(Map<String, String> transformOptions) {
// include default extensions
Set<String> extClassNames = new HashSet<>();
if (this.config.getDefaultExtensions() != null)
extClassNames.addAll(this.config.getDefaultExtensions());
// include/exclude based on passed in extensions
String extClassNamesRaw = transformOptions.get(RequestParamConstants.EXT_CLASS_NAMES);
if (extClassNamesRaw != null) {
for (String extClassName : extClassNamesRaw.split("[,\\n]")) {
extClassName = extClassName.trim();
if (extClassName.length() > 0) {
if (extClassName.startsWith("!")) {
// exclude those that start with !
extClassNames.remove(extClassName.substring(1));
} else {
// include the rest
extClassNames.add(extClassName);
}
}
}
}
List<Extension> exts = new ArrayList<>(extClassNames.size());
// create the extension classes using reflection
for (String extClassName : extClassNames) {
Class<?> extClass = this.findClass(extClassName);
if (extClass != null) {
Extension ext = this.createExtension(extClass);
if (ext != null)
exts.add(ext);
}
}
return exts;
}
private Class<?> findClass(String className) {
Matcher matcher = this.extClassNamePattern.matcher(className);
String extName = matcher.find() ? matcher.group(2).toLowerCase() : null;
for (String classPrefix : this.classSearchPrefixes) {
if (extName != null)
classPrefix = classPrefix.replaceAll("\\{name\\}", extName);
try {
Class<?> extClass = Class.forName(classPrefix + className);
return extClass;
} catch (ClassNotFoundException cnfe) {
// suppress
}
}
return null;
}
private Extension createExtension(Class<?> extClass) {
try {
// finding public static method, so using "DeclaredMethod" instead of "Method"
Method createMethod = extClass.getDeclaredMethod("create");
// calling public static method, so no instance (null)
return (Extension)createMethod.invoke(null);
} catch (NoSuchMethodException nsme) {
this.logger.warn("The '" + extClass.getName() + "' extension class must have a public static 'create' method");
} catch (InvocationTargetException ite) {
this.logger.warn("The '" + extClass.getName() + "' extension class 'create' method encountered an unexpected exception: " + ite.getMessage());
} catch (IllegalAccessException iae) {
this.logger.warn("The '" + extClass.getName() + "' extension class 'create' method is not public: " + iae.getMessage());
}
return null;
}
}

View File

@ -0,0 +1,9 @@
package com.inteligr8.alfresco.module.alfmarkdown;
public interface RequestParamConstants {
public static final String ENGINE = "engine";
public static final String PROFILE = "profile";
public static final String EXT_CLASS_NAMES = "extensions";
}

View File

@ -0,0 +1,181 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2020 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*
* Copyright (C) 2020 - 2021 Inteligr8
*/
package com.inteligr8.alfresco.module.alfmarkdown;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.AbstractTransformerController;
import org.alfresco.transformer.executors.Transformer;
import org.alfresco.transformer.probes.ProbeTestTransform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
/**
* Controller for the Spring Boot transformer.
*
* Status Codes:
*
* 200 Success
* 400 Bad Request: Request parameter <name> is missing (missing mandatory parameter)
* 400 Bad Request: Request parameter <name> is of the wrong type
* 400 Bad Request: Transformer exit code was not 0 (possible problem with the source file)
* 400 Bad Request: The source filename was not supplied
* 500 Internal Server Error: (no message with low level IO problems)
* 500 Internal Server Error: The target filename was not supplied (should not happen as targetExtension is checked)
* 500 Internal Server Error: Transformer version check exit code was not 0
* 500 Internal Server Error: Transformer version check failed to create any output
* 500 Internal Server Error: Could not read the target file
* 500 Internal Server Error: The target filename was malformed (should not happen because of other checks)
* 500 Internal Server Error: Transformer failed to create an output file (the exit code was 0, so there should be some content)
* 500 Internal Server Error: Filename encoding error
* 507 Insufficient Storage: Failed to store the source file
*/
@Controller
public class TransformerController extends AbstractTransformerController {
private final Logger logger = LoggerFactory.getLogger(TransformerController.class);
private final Pattern fileext = Pattern.compile("\\.([^\\.]+)$");
private final MediaType defaultTarget = MediaType.TEXT_HTML;
@Autowired
private List<Transformer> transformers;
@Value("${transform.alfmarkdown.version}")
private String version;
@Value("${transform.alfmarkdown.defaultEngine}")
private String defaultEngine;
private Map<String, Transformer> engineMap;
private ProbeTestTransform probe;
@Override
public String getTransformerName() {
return "alfmarkdown";
}
@Override
public String version() {
return this.version;
}
@PostConstruct
public void registerEngines() {
this.engineMap = new HashMap<>();
for (Transformer transformer : this.transformers) {
if (this.logger.isInfoEnabled())
this.logger.info("Registered transformer/engine: " + transformer.getTransformerId());
this.engineMap.put(transformer.getTransformerId(), transformer);
}
}
@PostConstruct
public void initProbe() {
this.probe = new ProbeTestTransform(this, "quick.md", "quick.html",
500L, 500L, 150, 16384L, 10L, 300L) {
@Override
protected void executeTransformCommand(File sourceFile, File targetFile) {
if (logger.isTraceEnabled())
logger.trace("getProbeTestTransform().executeTransformCommand('" + sourceFile + "', '" + targetFile + "')");
Transformer transformer = transformers.get(new Random().nextInt(2));
transformer.transform(MediaType.TEXT_MARKDOWN_VALUE, MediaType.TEXT_HTML_VALUE, Collections.emptyMap(), sourceFile, targetFile);
}
};
}
@Override
public ProbeTestTransform getProbeTestTransform() {
if (this.logger.isTraceEnabled())
this.logger.trace("getProbeTestTransform()");
return this.probe;
}
@Override
protected String getTransformerName(final File sourceFile, final String sourceMimetype, final String targetMimetype, final Map<String, String> transformOptions) {
if (this.logger.isTraceEnabled())
this.logger.trace("getTransformerName('" + sourceFile + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions + ")");
// does not matter what value is returned, as it is not used because there is only one.
return this.getTransformerName();
}
@Override
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype, Map<String, String> transformOptions, File sourceFile, File targetFile) {
if (this.logger.isTraceEnabled())
this.logger.trace("transformImpl('" + transformName + "', '" + sourceMimetype + "', '" + targetMimetype + "', " + transformOptions.keySet() + ", '" + sourceFile + "', '" + targetFile + "')");
if (sourceMimetype == null) {
Matcher matcher = this.fileext.matcher(sourceFile.getAbsolutePath());
sourceMimetype = matcher.find() ? this.ext2mime(matcher.group(1)) : null;
}
if (targetMimetype == null) {
Matcher matcher = this.fileext.matcher(targetFile.getAbsolutePath());
targetMimetype = matcher.find() ? this.ext2mime(matcher.group(1)) : this.defaultTarget.toString();
}
String engine = transformOptions.getOrDefault(RequestParamConstants.ENGINE, this.defaultEngine);
if (!this.engineMap.containsKey(engine))
throw new TransformException(HttpStatus.BAD_REQUEST.value(), "This transformer does not support the following engine: " + engine);
try {
this.engineMap.get(engine).transform(transformName, sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
} catch (Exception e) {
this.logger.error("The transformation encountered an unexpected issue", e);
throw new TransformException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "The transformer encountered an unexpected");
}
}
private String ext2mime(String ext) {
switch (ext.toLowerCase()) {
// add applicable extensions here
case "md":
case "markdown": return MediaType.TEXT_MARKDOWN_VALUE;
case "html":
case "htm": return MediaType.TEXT_HTML_VALUE;
case "text":
case "txt": return MediaType.TEXT_PLAIN_VALUE;
case "pdf": return MediaType.APPLICATION_PDF_VALUE;
default: return null;
}
}
}

View File

@ -0,0 +1,16 @@
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean autowire-candidate="true" class="org.alfresco.transformer.clients.AlfrescoSharedFileStoreClient" />
<bean autowire-candidate="true" class="org.springframework.web.client.RestTemplate" />
<bean autowire-candidate="true" class="org.alfresco.transform.client.model.TransformRequestValidator" />
<bean autowire-candidate="true" class="org.alfresco.transformer.TransformRegistryImpl" />
<context:component-scan base-package="com.inteligr8.alfresco.module.alfmarkdown" />
</beans>

View File

@ -0,0 +1,36 @@
queue:
engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:com.inteligr8.alfresco.module.alfmarkdown.acs}
transform:
core:
config:
location: classpath:this_engine_config.json
alfmarkdown:
version: ${project.version}
defaultEngine: flexmark
commonmark:
defaultExtensions:
- ImageAttributesExtension
- TaskListItemsExtension
- TablesExtension
- InsExtension
flexmark:
defaultProfile: github
defaultExtensions:
- AdmonitionExtension
- DefinitionExtension
- EmojiExtension
- EnumeratedReferenceExtension
- FootnoteExtension
- InsExtension
- MediaTagsExtension
- SubscriptExtension
- SuperscriptExtension
- TablesExtension
- TaskListExtension
- TypographicExtension
- YouTubeLinkExtension
logging:
level:
com.inteligr8.alfresco.module.alfmarkdown: ${LOG_LEVEL:info}

View File

@ -0,0 +1 @@
Just a simple markdown file, which is just a simple text file.

View File

@ -0,0 +1,26 @@
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div>
<h2>alfmarkdown Test Transformation</h2>
<form method="POST" enctype="multipart/form-data" action="/transform">
<table>
<tr><td><div style="text-align:right">file *</div></td><td><input type="file" name="file" /></td></tr>
<tr><td><div style="text-align:right">targetExtension *</div></td><td><input type="text" name="targetExtension" value="" /></td></tr>
<tr><td><div style="text-align:right">engine</div></td><td><select name="engine">
<option value="commonmark">commonmark</option>
<option value="flexmark" selected>flexmark</option>
</select></td></tr>
<tr><td><div style="text-align:right">profile</div></td><td><input type="text" name="profile" value="" /></td></tr>
<tr><td><div style="text-align:right">extensions</div></td><td><textarea name="extensions" rows="5"></textarea></tr>
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
</table>
</form>
</div>
<div>
<a href="/log">Log entries</a>
</div>
</body>
</html>

View File

@ -0,0 +1,20 @@
{
"transformOptions": {
"alfmarkdownOptions": [
{"value": {"name": "engine"}},
{"value": {"name": "profile"}},
{"value": {"name": "extensions"}}
]
},
"transformers": [
{
"transformerName": "alfmarkdown",
"supportedSourceAndTargetList": [
{"sourceMediaType": "text/markdown", "priority": 10, "targetMediaType": "text/html" }
],
"transformOptions": [
"alfmarkdownOptions"
]
}
]
}

View File

@ -0,0 +1,18 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import org.alfresco.transformer.executors.Transformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class CommonmarkTransformerTest extends TransformerTest {
@Autowired
@Qualifier(FlexmarkConfig.ID)
protected Transformer transformer;
@Override
public Transformer getTransformer() {
return this.transformer;
}
}

View File

@ -0,0 +1,18 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import org.alfresco.transformer.executors.Transformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class FlexmarkTransformerTest extends TransformerTest {
@Autowired
@Qualifier(FlexmarkConfig.ID)
protected Transformer transformer;
@Override
public Transformer getTransformer() {
return this.transformer;
}
}

View File

@ -0,0 +1,174 @@
/*
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
* -
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* -
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
* -
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package com.inteligr8.alfresco.module.alfmarkdown;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.HttpStatusCodeException;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestIT {
private final Logger logger = LoggerFactory.getLogger(HttpRequestIT.class);
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
protected String baseUrl;
@PostConstruct
public void init() {
this.baseUrl = "http://localhost:" + this.port;
}
@Test
public void testRootPath() {
String result = this.restTemplate.getForObject(this.baseUrl, String.class);
if (this.logger.isDebugEnabled())
this.logger.debug("testRootPath(): result: " + result);
Assert.assertNotNull("A result from the HTTP GET was expected", result);
Document htmldoc = Jsoup.parse(result);
Assert.assertNotNull("An HTML compliant result was expected: " + result.substring(0, 50), htmldoc);
Elements elements = htmldoc.select("html body h2");
Assert.assertFalse("The HTML body is expected to have an h2 element: html: " + htmldoc.toString(), elements.isEmpty());
Assert.assertEquals("The HTML body is expected to have just one h2 element", 1, elements.size());
Assert.assertEquals("The HTML body header is not what was expected", "alfmarkdown Test Transformation", elements.html());
elements = htmldoc.select("html input");
Set<String> inputs = new HashSet<String>();
for (Element element : elements)
inputs.add(element.attr("name"));
Assert.assertTrue("The HTML is expected to have a form input for 'file': " + inputs.toString(), inputs.contains("file"));
Assert.assertTrue("The HTML is expected to have a form input for 'targetExtension': " + inputs.toString(), inputs.contains("targetExtension"));
}
@Test
public void testLogPath() {
String result = this.restTemplate.getForObject(this.baseUrl + "/log", String.class);
if (this.logger.isDebugEnabled())
this.logger.debug("testLogPath(): result: " + result);
Assert.assertNotNull("A result from the HTTP GET was expected", result);
Document htmldoc = Jsoup.parse(result);
Assert.assertNotNull("An HTML compliant result was expected: " + result.substring(0, 50), htmldoc);
Elements elements = htmldoc.select("html body div h2");
Assert.assertFalse("The HTML is expected to have an html/body/div/h2 element: html: " + htmldoc.select("html").toString(), elements.isEmpty());
Assert.assertEquals("The HTML is expected to have just one html/body/div/h2 element", 1, elements.size());
Assert.assertEquals("The HTML body header is not what was expected", "alfmarkdown Log Entries", elements.html());
}
@Test
public void testNoPath() {
try {
ResponseEntity<String> response = this.restTemplate.getForEntity(this.baseUrl + "/doesnotexist", String.class);
Assert.assertEquals("An unexpected path must return a 404 error", 404, response.getStatusCodeValue());
} catch (HttpStatusCodeException hsce) {
Assert.assertEquals("An unexpected path must return a 404 error", 404, hsce.getRawStatusCode());
}
}
@Test
public void testServiceGet() {
try {
ResponseEntity<String> response = this.restTemplate.getForEntity(this.baseUrl + "/transform", String.class);
Assert.assertEquals("An unexpected path must return a 405 error", 405, response.getStatusCodeValue());
} catch (HttpStatusCodeException hsce) {
Assert.assertEquals("An unexpected path must return a 405 error", 405, hsce.getRawStatusCode());
}
}
@Test
public void testServiceNoFile() {
try {
ResponseEntity<String> response = this._testService(null, "trgt");
Assert.assertEquals("An unexpected path must return a 400 error", 400, response.getStatusCodeValue());
} catch (HttpStatusCodeException hsce) {
Assert.assertEquals("An unexpected path must return a 400 error", 400, hsce.getRawStatusCode());
}
}
@Test @Ignore
public void testServiceNoTargetExtension() {
try {
ResponseEntity<String> response = this._testService("quick.src", null);
Assert.assertEquals("An unexpected path must return a 400 error", 400, response.getStatusCodeValue());
} catch (HttpStatusCodeException hsce) {
Assert.assertEquals("An unexpected path must return a 400 error", 400, hsce.getRawStatusCode());
}
}
@Test @Ignore
public void testServiceQuick() {
this._testService("quick.src", "trgt");
}
protected ResponseEntity<String> _testService(String filename, String targetExtension) {
LinkedMultiValueMap<String, Object> parameters = new LinkedMultiValueMap<>();
if (filename != null)
parameters.add("file", new ClassPathResource(filename));
if (targetExtension != null)
parameters.add("targetExtension", targetExtension);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> entity = new HttpEntity<>(parameters, headers);
return this.restTemplate.postForEntity(this.baseUrl + "/transform", entity, String.class);
}
}

View File

@ -0,0 +1,30 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import org.alfresco.transformer.AbstractTransformerController;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.inteligr8.junit4.AssertRegex;
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = TransformerController.class)
public class TransformerControllerTest {
@Autowired
protected AbstractTransformerController controller;
@Test
public void tryTransformerName() {
Assert.assertEquals("alfmarkdown", this.controller.getTransformerName());
}
@Test
public void tryVersion() {
AssertRegex.assertMatches("[0-9]+\\.[0-9]+(\\.[0-9]+|-SNAPSHOT)", this.controller.version());
}
}

View File

@ -0,0 +1,96 @@
package com.inteligr8.alfresco.module.alfmarkdown;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.alfresco.transform.exceptions.TransformException;
import org.alfresco.transformer.executors.Transformer;
import org.jsoup.Jsoup;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import com.inteligr8.junit4.AssertRegex;
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = TransformerController.class)
public abstract class TransformerTest {
private final Logger logger = LoggerFactory.getLogger(TransformerTest.class);
public abstract Transformer getTransformer();
@Test
public void tryTransformerId() {
AssertRegex.assertMatches("flexmark|commonmark", this.getTransformer().getTransformerId());
}
@Test(expected = TransformException.class)
public void tryExtractMetadata() throws Exception {
this.getTransformer().extractMetadata("does-not-matter", "does-not-matter", "does-not-matter", Collections.emptyMap(), null, null);
}
@Test
public void tryTransformUnsupportedMedia() throws Exception {
List<String[]> mediaTypePairs = Arrays.asList(
new String[] {MediaType.TEXT_PLAIN_VALUE, MediaType.TEXT_PLAIN_VALUE},
new String[] {MediaType.TEXT_PLAIN_VALUE, MediaType.TEXT_MARKDOWN_VALUE},
new String[] {MediaType.TEXT_MARKDOWN_VALUE, MediaType.TEXT_PLAIN_VALUE},
new String[] {MediaType.TEXT_HTML_VALUE, MediaType.TEXT_MARKDOWN_VALUE},
new String[] {MediaType.TEXT_MARKDOWN_VALUE, MediaType.TEXT_MARKDOWN_VALUE}
);
for (String[] mediaTypePair : mediaTypePairs) {
try {
this.getTransformer().transform(mediaTypePair[0], mediaTypePair[1], Collections.emptyMap(), null, null);
Assert.fail();
} catch (TransformException te) {
try {
Assert.assertEquals(te.getMessage(), HttpStatus.BAD_REQUEST.value(), te.getStatusCode());
} catch (AssertionError ae) {
this.logger.error(ae.getMessage(), te);
throw ae;
}
}
}
}
@Test
public void tryTransformQuick() throws IOException, URISyntaxException {
File targetFile = this.transform(Collections.emptyMap(), new File(this.getClass().getResource("/quick.md").toURI()));
try {
Assert.assertEquals(70L, targetFile.length());
// is valid html
Jsoup.parse(targetFile, "utf-8");
} finally {
targetFile.delete();
}
}
private File transform(Map<String, String> transformOptions, File sourceFile) throws IOException, TransformException {
File htmlFile = File.createTempFile("test-", ".html");
try {
this.getTransformer().transform(MediaType.TEXT_MARKDOWN_VALUE, MediaType.TEXT_HTML_VALUE, transformOptions, sourceFile, htmlFile);
return htmlFile;
} catch (RuntimeException re) {
htmlFile.delete();
throw re;
} catch (Error e) {
htmlFile.delete();
throw e;
}
}
}

View File

@ -0,0 +1,36 @@
queue:
engineRequestQueue: ${TRANSFORM_ENGINE_REQUEST_QUEUE:com.inteligr8.alfresco.module.alfmarkdown.acs}
transform:
core:
config:
location: classpath:this_engine_config.json
alfmarkdown:
version: ${project.version}
defaultEngine: flexmark
commonmark:
defaultExtensions:
- ImageAttributesExtension
- TaskListItemsExtension
- TablesExtension
- InsExtension
flexmark:
defaultProfile: github
defaultExtensions:
- AdmonitionExtension
- DefinitionExtension
- EmojiExtension
- EnumeratedReferenceExtension
- FootnoteExtension
- InsExtension
- MediaTagsExtension
- SubscriptExtension
- SuperscriptExtension
- TablesExtension
- TaskListExtension
- TypographicExtension
- YouTubeLinkExtension
logging:
level:
com.inteligr8.alfresco.module.alfmarkdown: ${LOG_LEVEL:trace}