package com.twasyl.slideshowfx.content.extension.code; import com.twasyl.slideshowfx.content.extension.AbstractContentExtension; import com.twasyl.slideshowfx.content.extension.ResourceType; import com.twasyl.slideshowfx.content.extension.code.controllers.CodeContentExtensionController; import com.twasyl.slideshowfx.markup.IMarkup; import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; import javafx.fxml.FXMLLoader; import javafx.scene.layout.Pane; import java.io.IOException; import java.util.StringJoiner; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.util.regex.Pattern.MULTILINE; /** * The CodeContentExtension extends the AbstractContentExtension. It allows to build a content containing code to insert * inside a SlideshowFX presentation. * This extension uses PrismJS in order to manage programming language syntax coloration. * This extension supports HTML and Textile markup languages. * * @author Thierry Wasylczenko * @version 1.1 * @since SlideshowFX 1.0 */ public class CodeContentExtension extends AbstractContentExtension { private static final Logger LOGGER = Logger.getLogger(CodeContentExtension.class.getName()); protected static final String LINE_NUMBERS_CSS_CLASS = "line-numbers"; protected CodeContentExtensionController controller; public CodeContentExtension() { super("CODE", CodeContentExtension.class.getResource("/com/twasyl/slideshowfx/content/extension/code/resources/prism.zip"), FontAwesomeIcon.CODE, "Insert code", "Insert code"); final String baseURL = "prism/"; // Add URL this.putResource(ResourceType.CSS_FILE, baseURL.concat("prism.css")); this.putResource(ResourceType.JAVASCRIPT_FILE, baseURL.concat("prism.js")); } @Override public Pane getUI() { FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("/com/twasyl/slideshowfx/content/extension/code/fxml/CodeContentExtension.fxml")); Pane root = null; try { loader.setClassLoader(getClass().getClassLoader()); root = loader.load(); this.controller = loader.getController(); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Can not load UI for CodeContentExtension", e); } return root; } @Override public String buildContentString(IMarkup markup) { final StringBuilder builder = new StringBuilder(); if(markup == null || "HTML".equals(markup.getCode())) { builder.append(this.buildDefaultContentString()); } else if("TEXTILE".equals(markup.getCode())) { builder.append(this.buildTextileContentString()); } else if("MARKDOWN".equals(markup.getCode()) && !this.controller.isShowingLineNumbers()) { builder.append(this.buildMarkdownContentString()); } else { builder.append(this.buildDefaultContentString()); } return builder.toString(); } @Override public String buildDefaultContentString() { final StringBuilder builder = new StringBuilder(); builder.append("<pre").append(this.buildDefaultCssClass()).append("><code").append(this.buildDefaultCssClass()) .append(">") .append(this.controller.getCode()) .append("</code></pre>"); return builder.toString(); } protected String buildDefaultCssClass() { final String prefix = " class=\""; final String suffix = "\""; final StringJoiner cssClass = new StringJoiner(" ", prefix, suffix); if(this.controller.getLanguage() != null) cssClass.add(this.controller.getLanguage().getCssClass()); if(this.controller.isShowingLineNumbers()) cssClass.add(LINE_NUMBERS_CSS_CLASS); return cssClass.length() == (prefix + suffix).length() ? "" : cssClass.toString(); } protected String buildTextileContentString() { final StringBuilder builder = new StringBuilder("bc").append(this.buildTextileCssClass()) .append(codeContainsBlankLines(this.controller.getCode()) ? ".." : ".") .append(" ") .append(this.controller.getCode()); return builder.toString(); } protected String buildTextileCssClass() { final StringJoiner cssClass = new StringJoiner(" ", "(", ")"); if(this.controller.getLanguage() != null) cssClass.add(this.controller.getLanguage().getCssClass()); if(this.controller.isShowingLineNumbers()) cssClass.add(LINE_NUMBERS_CSS_CLASS); return cssClass.length() == 2 ? "" : cssClass.toString(); } protected String buildMarkdownContentString() { final StringBuilder builder = new StringBuilder("```"); if(this.controller.getLanguage() != null) { builder.append(this.controller.getLanguage().getCssClass()); } builder.append("\n").append(this.controller.getCode()).append("\n```"); return builder.toString(); } protected boolean codeContainsBlankLines(final String code) { final Pattern pattern = Pattern.compile("^\\s*$", MULTILINE); final Matcher matcher = pattern.matcher(code); return matcher.find(); } }