diff --git a/conf/booksample/book.asc b/conf/booksample/book.asc index bd3e4d4ae..2bcd83c88 100644 --- a/conf/booksample/book.asc +++ b/conf/booksample/book.asc @@ -20,4 +20,8 @@ include::chapter-01.asc[] include::chapter-02.asc[] -include::chapter-03.asc[] \ No newline at end of file +include::chapter-03.asc[] + +include::chapter-04.asc[] + +include::chapter-05.asc[] \ No newline at end of file diff --git a/conf/booksample/chapter-04.asc b/conf/booksample/chapter-04.asc new file mode 100644 index 000000000..ed4609d25 --- /dev/null +++ b/conf/booksample/chapter-04.asc @@ -0,0 +1,31 @@ +== Chapter 04 - Using UML Diagrams + +.UML http://plantuml.sourceforge.net/ +[uml,file="uml-diagram.png"] +-- +abstract class AbstractList +abstract AbstractCollection +interface List +interface Collection + +List <|-- AbstractList +Collection <|-- AbstractCollection + +Collection <|- List +AbstractCollection <|- AbstractList +AbstractList <|-- ArrayList + +class ArrayList { + Object[] elementData + size() +} + +enum TimeUnit { + DAYS + HOURS + MINUTES +} + +annotation SuppressWarnings +-- + diff --git a/conf/booksample/chapter-05.asc b/conf/booksample/chapter-05.asc new file mode 100644 index 000000000..414d42784 --- /dev/null +++ b/conf/booksample/chapter-05.asc @@ -0,0 +1,48 @@ +== Chapter 05 - Using Mathematical Formulas + +http://www.mathjax.org/[MathJax] is an open source JavaScript display engine for mathematics that works in all browsers. + +.Tex Example +[math,file="tex-formula.png"] +-- +\begin{align} +\dot{x} & = \sigma(y-x) \\ +\dot{y} & = \rho x - y - xz \\ +\dot{z} & = -\beta z + xyz +\end{align} +-- + +You can use Tex or MathML languages for describing mathematical formulas in AsciidocFX. AsciidocFX converts this textual formulas as png image. + +.MathML Example +[math,file="mathml-formula.png"] +-- + + x + = + + + + + b + ± + + + b + 2 + + + 4 + a + c + + + + 2 + a + + + + . + +-- \ No newline at end of file diff --git a/src/main/java/com/kodcu/controller/AsciiDocController.java b/src/main/java/com/kodcu/controller/AsciiDocController.java index ddc3085de..e50c06fba 100644 --- a/src/main/java/com/kodcu/controller/AsciiDocController.java +++ b/src/main/java/com/kodcu/controller/AsciiDocController.java @@ -11,6 +11,7 @@ import com.kodcu.other.Current; import com.kodcu.other.IOHelper; import com.kodcu.other.Item; +import com.kodcu.other.Tuple; import com.kodcu.service.*; import com.sun.javafx.application.HostServicesDelegate; import de.jensd.fx.fontawesome.AwesomeDude; @@ -24,16 +25,19 @@ import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.concurrent.Worker; +import javafx.embed.swing.SwingFXUtils; import javafx.event.ActionEvent; import javafx.event.Event; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.Scene; +import javafx.scene.SnapshotParameters; import javafx.scene.control.*; import javafx.scene.control.cell.TextFieldTreeCell; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.image.WritableImage; import javafx.scene.input.*; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Priority; @@ -61,6 +65,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -71,6 +76,7 @@ import org.springframework.web.socket.handler.TextWebSocketHandler; import org.w3c.dom.svg.SVGDocument; +import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.net.URISyntaxException; @@ -86,6 +92,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; import static java.nio.file.StandardOpenOption.*; @@ -198,6 +205,7 @@ public class AsciiDocController extends TextWebSocketHandler implements Initiali return Objects.nonNull(file) ? file.toPath() : null; }; private Map shortCuts; + private WebView fileTreeView; private DirectoryChooser newDirectoryChooser(String title) { DirectoryChooser directoryChooser = new DirectoryChooser(); @@ -438,6 +446,135 @@ private void generateHtml(ActionEvent event) { htmlBookService.produceXhtml5(previewEngine, currentPath, configPath); } + public String createFileTree(String tree, String type, String fileName, String width, String height) throws IOException { + + Objects.requireNonNull(fileName); + + if (!fileName.endsWith(".png") && !"ascii".equalsIgnoreCase(type)) + return ""; + + if ("ascii".equalsIgnoreCase(type)) { + return tree; + } + // default: png + else { + + if (!current.currentPath().isPresent()) + saveDoc(); + + Path path = current.currentPath().get().getParent(); + Path treePath = path.resolve("images/").resolve(fileName); + + Integer cacheHit = current.getCache().get(fileName); + + int hashCode = (fileName + type + tree + width + height).hashCode(); + if (Objects.isNull(cacheHit) || hashCode != cacheHit) { + + TreeView> fileView = new TreeView<>(); + fileView.setLayoutX(-9999); + fileView.setLayoutY(-9999); + rootAnchor.getChildren().add(fileView); + + try { + List strings = Arrays.asList(tree.split("\n")); + List>> treeItems = strings.stream() + .map(s -> { + int level = StringUtils.countOccurrencesOf(s, "#"); + String value = s.replace(" ", "").replace("#", ""); + return new Tuple(level, value); + }) + .map(t->{ + Node icon = awesomeService.getIcon(Paths.get(t.getValue())); + TreeItem> treeItem = new TreeItem<>(t,icon); + treeItem.setExpanded(true); + + return treeItem; + }) + .collect(Collectors.toList()); + + + for (int index = 0; index < treeItems.size(); index++) { + + TreeItem> currentItem = treeItems.get(index); + Tuple currentItemValue = currentItem.getValue(); + + if (Objects.isNull(fileView.getRoot())) { + fileView.setRoot(currentItem); + continue; + } + + TreeItem> lastItem = treeItems.get(index - 1); + int lastPos = lastItem.getValue().getKey(); + + if (currentItemValue.getKey() > lastPos) { + + lastItem.getChildren().add(currentItem); + continue; + } + + if (currentItemValue.getKey() == lastPos) { + + TreeItem> parent = lastItem.getParent(); + if(Objects.isNull(parent)) + parent = fileView.getRoot(); + parent.getChildren().add(currentItem); + continue; + } + + if (currentItemValue.getKey() < lastPos) { + + List>> collect = treeItems.stream() + .filter(t -> t.getValue().getKey() == currentItemValue.getKey()) + .collect(Collectors.toList()); + + if(collect.size()>0){ + TreeItem> treeItem = collect.get(collect.size() - 1); + TreeItem> parent = treeItem.getParent(); + + if(Objects.isNull(parent)) + parent = fileView.getRoot(); + parent.getChildren().add(currentItem); + } + continue; + } + + } + + fileView.setPrefHeight(treeItems.size() * 30); + + try{ + fileView.setPrefWidth(Double.valueOf(width)); + } + catch (Exception e){} + + try{ + fileView.setPrefHeight(Double.valueOf(height)); + } + catch (Exception e){} + + + Files.createDirectories(path.resolve("images")); + + WritableImage writableImage = fileView.snapshot(new SnapshotParameters(), null); + ImageIO.write(SwingFXUtils.fromFXImage(writableImage, null), "png", treePath.toFile()); + + lastRenderedChangeListener.changed(null, lastRendered.getValue(), lastRendered.getValue()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + current.getCache().put(fileName, hashCode); + + String treeRelativePath = Paths.get("images") + "/" + treePath.getFileName(); + + return treeRelativePath; + } +/////// + + } + @Override public void initialize(URL url, ResourceBundle rb) { @@ -485,15 +622,26 @@ public void initialize(URL url, ResourceBundle rb) { mathjaxView.setVisible(false); rootAnchor.getChildren().add(mathjaxView); + fileTreeView = new WebView(); + fileTreeView.setVisible(false); + rootAnchor.getChildren().add(fileTreeView); + WebEngine mathjaxEngine = mathjaxView.getEngine(); mathjaxEngine.getLoadWorker().stateProperty().addListener((observableValue1, state, state2) -> { JSObject window = (JSObject) mathjaxEngine.executeScript("window"); if (window.getMember("app").equals("undefined")) - window.setMember("app", this); + window.setMember("app", this); }); // + WebEngine fileTreeViewEngine = fileTreeView.getEngine(); + fileTreeViewEngine.getLoadWorker().stateProperty().addListener((observableValue1, state, state2) -> { + JSObject window = (JSObject) fileTreeViewEngine.executeScript("window"); + if (window.getMember("app").equals("undefined")) + window.setMember("app", this); + }); - mathjaxView.getEngine().load(String.format("http://localhost:%d/mathjax.html", tomcatPort)); + mathjaxEngine.load(String.format("http://localhost:%d/mathjax.html", tomcatPort)); + fileTreeViewEngine.load(String.format("http://localhost:%d/tree.html", tomcatPort)); previewEngine = previewView.getEngine(); previewEngine.load(String.format("http://localhost:%d/index.html", tomcatPort)); @@ -501,7 +649,7 @@ public void initialize(URL url, ResourceBundle rb) { previewEngine.getLoadWorker().stateProperty().addListener((observableValue1, state, state2) -> { JSObject window = (JSObject) previewEngine.executeScript("window"); if (window.getMember("app").equals("undefined")) - window.setMember("app", this); + window.setMember("app", this); }); previewEngine.getLoadWorker().exceptionProperty().addListener((ov, t, t1) -> { @@ -1075,12 +1223,24 @@ private WebView createWebView() { boolean success = false; if (dragboard.hasFiles()) { - Optional block = parserService.toImageBlock(dragboard.getFiles()); + + List dragboardFiles = dragboard.getFiles(); + + if(dragboardFiles.size()==1){ + Path path = dragboardFiles.get(0).toPath(); + if(Files.isDirectory(path)){ + Stream list = IOHelper.list(path); + current.insertEditorValue(list.map(Path::toString).collect(Collectors.joining("\n"))); + success =true; + } + } + + Optional block = parserService.toImageBlock(dragboardFiles); if (block.isPresent()) { current.insertEditorValue(block.get()); success = true; } else { - block = parserService.toIncludeBlock(dragboard.getFiles()); + block = parserService.toIncludeBlock(dragboardFiles); if (block.isPresent()) { current.insertEditorValue(block.get()); success = true; @@ -1111,7 +1271,7 @@ private WebView createWebView() { if (window.getMember("app").equals("undefined")) window.setMember("app", this); - if(newValue== Worker.State.SUCCEEDED) + if (newValue == Worker.State.SUCCEEDED) applySohrtCuts(); }); @@ -1123,7 +1283,7 @@ private WebView createWebView() { private void applySohrtCuts() { Set keySet = shortCuts.keySet(); for (String key : keySet) { - current.currentEngine().executeScript(String.format("addNewCommand('%s','%s')",key,shortCuts.get(key))); + current.currentEngine().executeScript(String.format("addNewCommand('%s','%s')", key, shortCuts.get(key))); } } @@ -1195,11 +1355,10 @@ public ResponseEntity images(HttpServletRequest request, @PathVariable(" Path imageFile = null; - if(current.currentPath().isPresent()){ + if (current.currentPath().isPresent()) { imageFile = current.currentPath().map(Path::getParent).get().resolve(uri); - } - else{ - imageFile= workingDirectory.get().resolve(uri); + } else { + imageFile = workingDirectory.get().resolve(uri); } try { diff --git a/src/main/java/com/kodcu/other/IOHelper.java b/src/main/java/com/kodcu/other/IOHelper.java index 81b35ca26..bf32b4a6f 100644 --- a/src/main/java/com/kodcu/other/IOHelper.java +++ b/src/main/java/com/kodcu/other/IOHelper.java @@ -13,6 +13,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.stream.Stream; /** * Created by usta on 09.05.2014. @@ -96,4 +97,13 @@ public static String pathToUrl(Path path) { } return null; } + + public static Stream list(Path path) { + try { + return Files.list(path); + } catch (IOException e) { + e.printStackTrace(); + } + return Stream.empty(); + } } diff --git a/src/main/java/com/kodcu/other/Tuple.java b/src/main/java/com/kodcu/other/Tuple.java new file mode 100644 index 000000000..1a14128a8 --- /dev/null +++ b/src/main/java/com/kodcu/other/Tuple.java @@ -0,0 +1,39 @@ +package com.kodcu.other; + +/** + * Created by usta on 21.12.2014. + */ +public class Tuple { + + private K key; + private V value; + + public Tuple() { + } + + public Tuple(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } + + @Override + public String toString() { + return value.toString(); + } +} diff --git a/src/main/java/com/kodcu/service/AwesomeService.java b/src/main/java/com/kodcu/service/AwesomeService.java index 1d5bf3712..091ef8344 100644 --- a/src/main/java/com/kodcu/service/AwesomeService.java +++ b/src/main/java/com/kodcu/service/AwesomeService.java @@ -20,13 +20,31 @@ public class AwesomeService { private PathResolverService pathResolver; public Node getIcon(Path path) { - AwesomeIcon awesomeIcon = null; + AwesomeIcon awesomeIcon = AwesomeIcon.FILE; if (Files.isDirectory(path)) awesomeIcon = AwesomeIcon.FOLDER_ALT; else if (pathResolver.isAsciidoc(path)) awesomeIcon = AwesomeIcon.FILE_TEXT_ALT; else if (pathResolver.isImage(path)) awesomeIcon = AwesomeIcon.FILE_PICTURE_ALT; + else if (pathResolver.isPDF(path)) + awesomeIcon = AwesomeIcon.FILE_PDF_ALT; + else if (pathResolver.isPPT(path)) + awesomeIcon = AwesomeIcon.FILE_POWERPOINT_ALT; + else if (pathResolver.isDocx(path)) + awesomeIcon = AwesomeIcon.FILE_WORD_ALT; + else if (pathResolver.isExcel(path)) + awesomeIcon = AwesomeIcon.FILE_EXCEL_ALT; + else if (pathResolver.isArchive(path)) + awesomeIcon = AwesomeIcon.ARCHIVE; + else if (pathResolver.isVideo(path)) + awesomeIcon = AwesomeIcon.FILE_VIDEO_ALT; + else if (pathResolver.isHTML(path)) + awesomeIcon = AwesomeIcon.HTML5; + else if (pathResolver.isCSS(path)) + awesomeIcon = AwesomeIcon.CSS3; + else if (pathResolver.isBash(path)) + awesomeIcon = AwesomeIcon.TERMINAL; Label iconLabel = AwesomeDude.createIconLabel(awesomeIcon, "14.0"); return iconLabel; } diff --git a/src/main/java/com/kodcu/service/PathResolverService.java b/src/main/java/com/kodcu/service/PathResolverService.java index f419d20fa..1dd7d2392 100644 --- a/src/main/java/com/kodcu/service/PathResolverService.java +++ b/src/main/java/com/kodcu/service/PathResolverService.java @@ -23,10 +23,17 @@ public class PathResolverService { Arrays.asList("book.asc", "book.txt", "book.asciidoc", "book.adoc", "book.ad"); PathMatcher pdfMatcher = FileSystems.getDefault().getPathMatcher("glob:**.pdf"); - PathMatcher htmlMatcher = FileSystems.getDefault().getPathMatcher("glob:**.html"); + PathMatcher htmlMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{html,html}"); PathMatcher docBookMatcher = FileSystems.getDefault().getPathMatcher("glob:**.xml"); PathMatcher ascMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{asc,asciidoc,ad,adoc,txt}"); PathMatcher imageMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{png,svg,jpg,bmp,gif}"); + PathMatcher pptMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{ppt,pptx}"); + PathMatcher docxMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{doc,docx}"); + PathMatcher excelMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{xls,xlsx}"); + PathMatcher archieveMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{zip,jar,tar,rar,tar.gz}"); + PathMatcher videoMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{cda,avi,flv,mkv,mov,mp4,mpeg,mpg,ogv,webm,divx,wmv}"); + PathMatcher cssMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{css,css3,scss,less}"); + PathMatcher terminalMatcher = FileSystems.getDefault().getPathMatcher("glob:**.{bat,sh,cmd}"); private Map rootExists = new HashMap<>(); @@ -100,4 +107,32 @@ public Path resolve(Path currentPath) { return null; } + + public boolean isPPT(Path path) { + return false; + } + + public boolean isDocx(Path path) { + return docxMatcher.matches(path); + } + + public boolean isExcel(Path path) { + return excelMatcher.matches(path); + } + + public boolean isArchive(Path path) { + return archieveMatcher.matches(path); + } + + public boolean isVideo(Path path) { + return videoMatcher.matches(path); + } + + public boolean isCSS(Path path) { + return cssMatcher.matches(path); + } + + public boolean isBash(Path path) { + return terminalMatcher.matches(path); + } } diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html index 4e0ca63db..966dc6055 100644 --- a/src/main/resources/public/index.html +++ b/src/main/resources/public/index.html @@ -51,6 +51,7 @@ + diff --git a/src/main/resources/public/js/asciidoctor-tree-block.js b/src/main/resources/public/js/asciidoctor-tree-block.js new file mode 100644 index 000000000..fc87a3a69 --- /dev/null +++ b/src/main/resources/public/js/asciidoctor-tree-block.js @@ -0,0 +1,50 @@ +/* Generated by Opal 0.6.3 */ +(function($opal) { + var $a, self = $opal.top, $scope = $opal, nil = $opal.nil, $breaker = $opal.breaker, $slice = $opal.slice, $klass = $opal.klass, $hash2 = $opal.hash2; + + if ($scope.RUBY_ENGINE['$==']("opal")) {}; + self.$include((($a = $opal.Object._scope.Asciidoctor) == null ? $opal.cm('Asciidoctor') : $a)); + return (function($base, $super) { + function $TreeBlock(){}; + var self = $TreeBlock = $klass($base, $super, 'TreeBlock', $TreeBlock); + + var def = self._proto, $scope = self._scope; + + self.$use_dsl(); + + self.$named("tree"); + + self.$on_context("open"); + + self.$parse_content_as("literal"); + + return (def.$process = function(parent, reader, attrs) { + var $a, self = this, content = nil, type = nil, title = nil, filename = nil, width = nil, height = nil; + + content = nil; + type = "" + (attrs['$[]']("type")); + title = "" + (attrs['$[]']("title")); + filename = "" + (attrs['$[]']("filename")); + width = "" + (attrs['$[]']("width")); + height = "" + (attrs['$[]']("height")); + + content = app.createFileTree(reader.$read(),type,filename,width,height); + + if ((($a = (type['$==']("ascii"))) !== nil && (!$a._isBoolean || $a == true))) { + return self.$create_pass_block(parent, content, attrs, $hash2(["subs"], {"subs": nil})) + } else { + return self.$create_image_block(parent, $hash2(["target", "title"], {"target": content, "title": title})) + }; + }, nil) && 'process'; + })(self, ($scope.Extensions)._scope.BlockProcessor); +})(Opal); +/* Generated by Opal 0.6.3 */ +(function($opal) { + var $a, $b, TMP_1, self = $opal.top, $scope = $opal, nil = $opal.nil, $breaker = $opal.breaker, $slice = $opal.slice; + + if ($scope.RUBY_ENGINE['$==']("opal")) { + }; + return ($a = ($b = $scope.Extensions).$register, $a._p = (TMP_1 = function(){var self = TMP_1._s || this; + + return self.$block($scope.TreeBlock)}, TMP_1._s = self, TMP_1), $a).call($b); +})(Opal); diff --git a/src/main/resources/public/js/index.js b/src/main/resources/public/js/index.js index 23ac31dec..0303f2bde 100644 --- a/src/main/resources/public/js/index.js +++ b/src/main/resources/public/js/index.js @@ -2,64 +2,83 @@ var defaultLanguage = undefined; function getDefaultLanguage() { if (!defaultLanguage) defaultLanguage = app.getConfig().getDefaultLanguage(); - return "lang=" + defaultLanguage; + return defaultLanguage; } function convertBasicHtml(content) { + var options = Opal.hash2(['backend', 'safe', 'attributes'], { backend: 'html5', safe: 'safeMode', - attributes: 'showtitle icons=font@ source-highlighter=highlight.js platform=opal platform-opal env=browser env-browser ' + getDefaultLanguage() + attributes: 'showtitle icons=font@ source-highlighter=highlight.js platform=opal platform-opal env=browser env-browser ' }); - return Opal.Asciidoctor.$convert(content, options); + var doc = Opal.Asciidoctor.$load(content,options); + + doc.attributes.keys["lang"] = doc.attributes.keys["lang"] || getDefaultLanguage(); + + return doc.$convert(); } function convertHtmlBook(content) { + var options = Opal.hash2(['backend', 'safe', 'attributes', "header_footer"], { backend: 'html5', safe: 'safeMode', - attributes: 'showtitle icons=font@ source-highlighter=highlight.js platform=opal platform-opal env=browser env-browser ' + getDefaultLanguage() + attributes: 'showtitle icons=font@ source-highlighter=highlight.js platform=opal platform-opal env=browser env-browser ' , 'header_footer': true }); - var rendered = Opal.Asciidoctor.$render(content, options); - return rendered; + var doc = Opal.Asciidoctor.$load(content,options); + + doc.attributes.keys["lang"] = doc.attributes.keys["lang"] || getDefaultLanguage(); + + return doc.$render(); } function convertHtmlArticle(content) { - var hash2 = Opal.hash2(['attributes', 'header_footer'], + + var options = Opal.hash2(['attributes', 'header_footer'], { - 'attributes': ['backend=html5', 'doctype=article', getDefaultLanguage()], + 'attributes': ['backend=html5', 'doctype=article'], 'header_footer': true }); - var rendered = Opal.Asciidoctor.$render(content, hash2); - return rendered; + var doc = Opal.Asciidoctor.$load(content,options); + + doc.attributes.keys["lang"] = doc.attributes.keys["lang"] || getDefaultLanguage(); + + return doc.$render(); } function convertDocbook(content, includeHeader) { - var hash2 = Opal.hash2(['attributes', 'header_footer'], + var options = Opal.hash2(['attributes', 'header_footer'], { - 'attributes': ['backend=docbook5', 'doctype=book', getDefaultLanguage()], + 'attributes': ['backend=docbook5', 'doctype=book'], 'header_footer': includeHeader }); - var rendered = Opal.Asciidoctor.$render(content, hash2); - return rendered; + var doc = Opal.Asciidoctor.$load(content, options); + + doc.attributes.keys["lang"] = doc.attributes.keys["lang"] || getDefaultLanguage(); + + return doc.$render(); } function convertDocbookArticle(content) { - var hash2 = Opal.hash2(["lang", 'attributes', 'header_footer'], + var options = Opal.hash2(["lang", 'attributes', 'header_footer'], { - 'attributes': ['backend=docbook5', 'doctype=article', getDefaultLanguage()], + 'attributes': ['backend=docbook5', 'doctype=article'], 'header_footer': true }); - var rendered = Opal.Asciidoctor.$render(content, hash2); - return rendered; + var doc = Opal.Asciidoctor.$load(content,options); + + doc.attributes.keys["lang"] = doc.attributes.keys["lang"] || getDefaultLanguage(); + + return doc.$render(); } function scrollTo60(position) { diff --git a/src/main/resources/public/tree.html b/src/main/resources/public/tree.html new file mode 100644 index 000000000..9f08db56e --- /dev/null +++ b/src/main/resources/public/tree.html @@ -0,0 +1,56 @@ + + + + + + + + + + + + \ No newline at end of file