diff --git a/src/main/java/me/coley/c2h/Code2Html.java b/src/main/java/me/coley/c2h/Code2Html.java
index c8a0b06..e3f90c8 100644
--- a/src/main/java/me/coley/c2h/Code2Html.java
+++ b/src/main/java/me/coley/c2h/Code2Html.java
@@ -15,11 +15,11 @@
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.util.Pair;
-import jregex.Matcher;
import jregex.Pattern;
import me.coley.c2h.config.*;
import me.coley.c2h.config.model.*;
import me.coley.c2h.ui.RuleCell;
+import me.coley.c2h.util.Regex;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.controlsfx.validation.ValidationSupport;
@@ -45,8 +45,8 @@
*/
public class Code2Html extends Application implements Callable {
// Base values
- private static String css = "";
- private static String js = "";
+ public static String BASE_CSS = "";
+ public static String BASE_JS = "";
// Command line options/args
@Option(names = {"-c", "--config"}, description = "Config to with languages and themes")
private File clConfig;
@@ -58,8 +58,12 @@ public class Code2Html extends Application implements Callable {
private boolean clClipboard;
@Option(names = {"-o", "--out"}, description = "The file to output converted HTML to")
private File clOutput;
+ @Option(names = {"-i", "--inline"}, description = "Option to make CSS inline with the HTML elements")
+ private boolean clInline;
@CommandLine.Parameters(index = "0", description = "The file to convert to styled HTML")
private File clInput;
+ // Other options
+ private boolean inline;
// Boolean indicating if CLI has priority over GUI
private boolean cliExecution;
// Controls
@@ -77,11 +81,10 @@ public class Code2Html extends Application implements Callable {
// Config
private ConfigHelper helper;
-
public static void main(String[] args) {
try {
- css = IOUtils.toString(Code2Html.class.getResourceAsStream("/code.css"), UTF_8);
- js = IOUtils.toString(Code2Html.class.getResourceAsStream("/code.js"), UTF_8);
+ BASE_CSS = IOUtils.toString(Code2Html.class.getResourceAsStream("/code.css"), UTF_8);
+ BASE_JS = IOUtils.toString(Code2Html.class.getResourceAsStream("/code.js"), UTF_8);
} catch(Exception e) {
e.printStackTrace();
System.err.println("Failed to load default resources: css/js");
@@ -134,7 +137,7 @@ public Void call() {
helper = new ConfigHelper(configuration, language, theme);
// Input reading & parsing
String text = FileUtils.readFileToString(clInput, UTF_8);
- String converted = helper.convert(text);
+ String converted = helper.convert(text, clInline);
// Output
Platform.runLater(() -> {
if(clClipboard) {
@@ -195,7 +198,7 @@ public void start(Stage stage) {
txtJS.setFont(Font.font("monospace"));
txtHTML.setEditable(false);
updateCSS();
- txtJS.setText(js);
+ txtJS.setText(BASE_JS);
txtInput.textProperty().addListener((ob, o, n) -> {
// Update HTML
updateHTML();
@@ -210,21 +213,9 @@ public void start(Stage stage) {
if(!old.equalsIgnoreCase(cur)) {
// Iterate over css tags (by matching via regex)
for(Rule rule : helper.getRules()) {
- String r = "(\\.({TITLE}" + rule.getName() + ")\\s*\\{({BODY}[^}]*))\\}";
- Pattern pattern = new Pattern(r);
- Matcher matcher = pattern.matcher(cur);
- if(!matcher.find())
- return;
- String body = matcher.group("BODY");
- // Parse the body of the css class and update the regex-rule style map.
- r = "({key}\\S+):\\s*({value}.+)(?=;)";
- pattern = new Pattern(r);
- matcher = pattern.matcher(body);
- while(matcher.find()) {
- String key = matcher.group("key");
- String value = matcher.group("value");
+ Regex.getCssProperties(cur, "." + rule.getName()).forEach((key, value) -> {
helper.getTheme().update(rule.getName(), key, value);
- }
+ });
}
}
// Update HTML
@@ -309,8 +300,17 @@ public void start(Stage stage) {
});
mnFile.getItems().addAll(miConfigLoad);
mnFile.getItems().addAll(miConfigSave);
+ // TODO: Swap out menu-item for checkbox
+ Menu mnOptions = new Menu("Options");
+ CheckMenuItem miOptionInline = new CheckMenuItem("Inline HTML style");
+ miOptionInline.selectedProperty().addListener((observable, oldValue, newValue) -> {
+ this.inline = newValue.booleanValue();
+ updateHTML();
+ });
+ mnOptions.getItems().addAll(miOptionInline);
+ // inline
MenuBar menuBar = new MenuBar();
- menuBar.getMenus().addAll(mnFile, mnLang, mnTheme);
+ menuBar.getMenus().addAll(mnFile, mnLang, mnTheme, mnOptions);
// Layout
SplitPane pane = new SplitPane(txtInput, tabs);
SplitPane vert = new SplitPane(pane, browser);
@@ -682,7 +682,7 @@ private void updateTitle() {
* Update CSS text.
*/
private void updateCSS() {
- txtCSS.setText(helper.getPatternCSS() + css);
+ txtCSS.setText(helper.getPatternCSS() + BASE_CSS);
}
/**
@@ -693,12 +693,14 @@ private void updateHTML() {
return;
}
String text = txtInput.getText().replace("\t", " ");
- String html = helper.convert(text);
+ String html = helper.convert(text, inline);
String style = txtCSS.getText();
StringBuilder sbWeb = new StringBuilder();
- sbWeb.append("");
+ sbWeb.append("");
+ if (!inline) {
+ sbWeb.append("");
+ }
+ sbWeb.append("");
sbWeb.append(html);
sbWeb.append("");
browser.getEngine().loadContent(sbWeb.toString());
diff --git a/src/main/java/me/coley/c2h/config/ConfigHelper.java b/src/main/java/me/coley/c2h/config/ConfigHelper.java
index 5f33854..b92b0d9 100644
--- a/src/main/java/me/coley/c2h/config/ConfigHelper.java
+++ b/src/main/java/me/coley/c2h/config/ConfigHelper.java
@@ -4,9 +4,12 @@
import jregex.Pattern;
import lombok.Getter;
import lombok.Setter;
+import me.coley.c2h.Code2Html;
import me.coley.c2h.config.model.*;
+import me.coley.c2h.util.Regex;
import java.util.List;
+import java.util.Map;
import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
@@ -67,14 +70,14 @@ public void addRule(Rule rule) {
* @param text
* Text to convert into HTML.
*
+ * @param inline
* @return HTML of the text with matched attributes of the {@link #language current language}.
*/
- public String convert(String text) {
+ public String convert(String text, boolean inline) {
Matcher matcher = getPattern().matcher(text);
StringBuilder sb = new StringBuilder();
int lastEnd = 0;
while(matcher.find()) {
- String styleClass = getClassFromGroup(matcher);
int start = matcher.start();
int end = matcher.end();
// append text not matched
@@ -84,17 +87,43 @@ public String convert(String text) {
}
// append match
String matched = escapeHtml4(text.substring(start, end));
- sb.append("" + matched + "");
+ if (inline) {
+ String styleRules = getInlineStyleFromGroup(matcher);
+ sb.append("" + matched + "");
+ } else {
+ String styleClass = getClassFromGroup(matcher);
+ sb.append("" + matched + "");
+ }
lastEnd = end;
}
// Append ending text not matched
sb.append(escapeHtml4(text.substring(lastEnd)));
// Apply line formatting to each line
StringBuilder fmt = new StringBuilder();
- for(String line : sb.toString().split("\n"))
- fmt.append("" + line + "\n");
- // Wrap in pre tags and slap it in an HTML page
- return "" + fmt.toString() + "
";
+ if(inline) {
+ StringBuilder sbLineStyle = new StringBuilder();
+ StringBuilder sbLinePreStyle = new StringBuilder();
+ Regex.getCssProperties(Code2Html.BASE_CSS, "pre .line").forEach((key, value) -> {
+ sbLineStyle.append(key + ":" + value + ";");
+ });
+ Regex.getCssProperties(Code2Html.BASE_CSS, "pre .line::before").forEach((key, value) -> {
+ sbLinePreStyle.append(key + ":" + value + ";");
+ });
+ int lineNum = 1;
+ for(String line : sb.toString().split("\n"))
+ fmt.append("" + (lineNum++) + "" + line + "\n");
+ // Wrap in pre tags and slap it in an HTML page
+ StringBuilder sbPreStyle = new StringBuilder();
+ Regex.getCssProperties(Code2Html.BASE_CSS, "pre").forEach((key, value) -> {
+ sbPreStyle.append(key + ":" + value + ";");
+ });
+ return "" + fmt.toString() + "
";
+ } else {
+ for(String line : sb.toString().split("\n"))
+ fmt.append("" + line + "\n");
+ // Wrap in pre tags and slap it in an HTML page
+ return "" + fmt.toString() + "
";
+ }
}
/**
@@ -149,4 +178,24 @@ public String getClassFromGroup(Matcher matcher) {
return rule.getName();
return null;
}
+
+ /**
+ * Fetch the CSS style to be used by the matched group.
+ *
+ * @param matcher
+ * Matcher that has found a group.
+ *
+ * @return CSS inline style.
+ */
+ public String getInlineStyleFromGroup(Matcher matcher) {
+ for(Rule rule : getRules())
+ if(matcher.group(rule.getPatternGroupName()) != null) {
+ StringBuilder sbStyle = new StringBuilder();
+ theme.getStylesForRule(rule.getName())
+ .forEach(style ->
+ sbStyle.append(style.getKey() + ":" + style.getValue() + ";"));
+ return sbStyle.toString();
+ }
+ return "";
+ }
}
diff --git a/src/main/java/me/coley/c2h/util/Regex.java b/src/main/java/me/coley/c2h/util/Regex.java
new file mode 100644
index 0000000..a494691
--- /dev/null
+++ b/src/main/java/me/coley/c2h/util/Regex.java
@@ -0,0 +1,43 @@
+package me.coley.c2h.util;
+
+import jregex.Matcher;
+import jregex.Pattern;
+import org.apache.commons.text.StringEscapeUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility for miscellaneous regex actions.
+ *
+ * @author Matt
+ */
+public class Regex {
+ /**
+ * @param cssText
+ * Text containing CSS to match.
+ * @param cssRule
+ * Rule to extract properties from.
+ *
+ * @return Map of property names to values.
+ */
+ public static Map getCssProperties(String cssText, String cssRule) {
+ Map map = new HashMap<>();
+ String regex = "(({TITLE}" + cssRule + ")\\s*\\{({BODY}[^}]*))\\}";
+ Pattern pattern = new Pattern(regex);
+ Matcher matcher = pattern.matcher(cssText);
+ if(!matcher.find())
+ return map;
+ String body = matcher.group("BODY");
+ // Parse the body of the css class and update the regex-rule style map.
+ regex = "({key}\\S+):\\s*({value}.+)(?=;)";
+ pattern = new Pattern(regex);
+ matcher = pattern.matcher(body);
+ while(matcher.find()) {
+ String key = matcher.group("key");
+ String value = matcher.group("value");
+ map.put(key, value);
+ }
+ return map;
+ }
+}
diff --git a/src/main/resources/code.css b/src/main/resources/code.css
index 82dd80b..d7ef33b 100644
--- a/src/main/resources/code.css
+++ b/src/main/resources/code.css
@@ -14,6 +14,7 @@ pre * { font-family: monospace; }
/* show line numbers */
pre .line { display: inline-block; }
pre .line::before {
+ user-select: none;
counter-increment: ln;
content: counter(ln);
display: inline-block;