From b1e76f597c7e2dac8f6fc1c1c9cc2491e5ab3f6e Mon Sep 17 00:00:00 2001 From: xiaol Date: Thu, 18 Dec 2025 13:21:23 -0600 Subject: [PATCH 1/5] add table support of flexmark --- .gitignore | 1 + .../lib/flexmark-ext-tables-0.64.8.jar | Bin 0 -> 47409 bytes .../LogrPortal/nbproject/project.properties | 4 ++- src/java/LogrPortal/nbproject/project.xml | 4 +++ .../logr/portal/utilities/MarkdownParser.java | 4 ++- .../LogrPortal/web/resources/css/logbook.css | 25 +++++++++++++++++- 6 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/java/LogrPortal/lib/flexmark-ext-tables-0.64.8.jar diff --git a/.gitignore b/.gitignore index cb6708344..7d8381853 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .vscode .DS_Store src/python/.loglogin +.loglogin # Compiled files *.pyc diff --git a/src/java/LogrPortal/lib/flexmark-ext-tables-0.64.8.jar b/src/java/LogrPortal/lib/flexmark-ext-tables-0.64.8.jar new file mode 100644 index 0000000000000000000000000000000000000000..9201e31bfe142e7437a115d3970cc7cd85e84b7d GIT binary patch literal 47409 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±A%s~+@(OL86lAN&T%xdv-_PV<{BY=5Z7Z;<`1913=MDvJ7O_M(patMSde(i zu#%?u9d{d&3m=^(%uHNw#F=BmW6A~$Yo+lMP7mB!NV*c$?v1+e#sJK1bsM<3mtP0v z{I+p7@)lw44C0U$aC~Z@Kc^I?kVu83y@CinB1+N;yJo94jU(Y1Y(;_mbFpoVG*PXr zX4h>Vx20F}26m!x9MjsUkx&ai3#DLm$lXt|7@E2KXeq(X)L(G9o(pDmH3MY!qq;>f zfFGb{$<*&DVwn%&%&2iD9a+n)Fh0uiGdU^r#@tbsRKJ0uG>4!!qf5V0>#V)y?qqlw zzImG}au1%Q?c`>Igx8j5Si3hS^$w;(n`gpd1CKZ{uHnfPGv{0CN{=n4fnrl;epXlMzNgdPkO6@TJEQPZ!3A78$=4g#cUl zIKpQB8gsRnxl|yprYtYZ!{Y+3pclelVkQn9aF$73LUxUURS+)5;$Az`uES{#rhiJz z64Rm5YHk&;ZVZ$4snU5#*k$*QdF<@kXXLh6aOH8Z&&Ru9uIB$dgπQF~)Mc^e0q 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.reference.flexmark-util-html-0.64.8.jar} WEB-INF/lib + + ${file.reference.flexmark-ext-tables-0.64.8.jar} + WEB-INF/lib + diff --git a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java index 5e8a81081..ff4d9526d 100644 --- a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java +++ b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java @@ -21,6 +21,7 @@ import com.vladsch.flexmark.util.misc.Extension; import com.vladsch.flexmark.util.sequence.BasedSequence; import com.vladsch.flexmark.util.sequence.Escaping; +import com.vladsch.flexmark.ext.tables.TablesExtension; import gov.anl.aps.logr.common.constants.CdbPropertyValue; import java.util.HashSet; @@ -79,7 +80,8 @@ public class MarkdownParser { private static MutableDataHolder options = new MutableDataSet() .set(Parser.EXTENSIONS, Arrays.asList( new Extension[]{ - LogrFlexmarkExtension.create() + LogrFlexmarkExtension.create(), + TablesExtension.create() } )); diff --git a/src/java/LogrPortal/web/resources/css/logbook.css b/src/java/LogrPortal/web/resources/css/logbook.css index 4cd29136d..68638bb77 100644 --- a/src/java/LogrPortal/web/resources/css/logbook.css +++ b/src/java/LogrPortal/web/resources/css/logbook.css @@ -133,7 +133,30 @@ pre:has([class^="language-"]) { } .logEntry img { - max-width: 450px; + max-width: 450px; +} + +/* Markdown table styles */ +.logEntry table { + border-collapse: collapse; + width: 100%; + margin: 1em 0; +} + +.logEntry th, +.logEntry td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; +} + +.logEntry th { + background-color: #f2f2f2; + font-weight: bold; +} + +.logEntry tr:nth-child(even) { + background-color: #f9f9f9; } .activeLogEntry { From 4e423b70c018e3bfb59fbad051f1a9399a350aa1 Mon Sep 17 00:00:00 2001 From: xiaol Date: Fri, 30 Jan 2026 12:38:16 -0600 Subject: [PATCH 2/5] update the deployment scripts --- sbin/cdb_create_configuration_openssl.sh | 18 +++---- sbin/cdb_create_db.sh | 2 +- sbin/cdb_deploy_mysqld.sh | 2 +- support/bin/install_netbeans.sh | 2 +- .../utilities/plugin_configuration.py | 18 +++---- .../utilities/plugin_java_parser.py | 2 +- .../logr_plugins/utilities/plugin_manager.py | 49 +++++++++---------- .../utilities/plugin_python_parser.py | 2 +- 8 files changed, 47 insertions(+), 48 deletions(-) diff --git a/sbin/cdb_create_configuration_openssl.sh b/sbin/cdb_create_configuration_openssl.sh index cd8f48b59..9df68b510 100755 --- a/sbin/cdb_create_configuration_openssl.sh +++ b/sbin/cdb_create_configuration_openssl.sh @@ -13,26 +13,26 @@ # MY_DIR=`dirname $0` && cd $MY_DIR && MY_DIR=`pwd` -if [ -z "${CDB_ROOT_DIR}" ]; then - CDB_ROOT_DIR=$MY_DIR/.. +if [ -z "${LOGR_ROOT_DIR}" ]; then + LOGR_ROOT_DIR=$MY_DIR/.. fi -CDB_ENV_FILE=${CDB_ROOT_DIR}/setup.sh -if [ ! -f ${CDB_ENV_FILE} ]; then - echo "Environment file ${CDB_ENV_FILE} does not exist." +LOGR_ENV_FILE=${LOGR_ROOT_DIR}/setup.sh +if [ ! -f ${LOGR_ENV_FILE} ]; then + echo "Environment file ${LOGR_ENV_FILE} does not exist." exit 2 fi -. ${CDB_ENV_FILE} > /dev/null +. ${LOGR_ENV_FILE} > /dev/null -CDB_ETC_DIR=$CDB_INSTALL_DIR/etc +LOGR_ETC_DIR=$LOGR_INSTALL_DIR/etc -OPENSSL_CONFIG_FILE=$CDB_ETC_DIR/cdb.openssl.cnf +OPENSSL_CONFIG_FILE=$LOGR_ETC_DIR/cdb.openssl.cnf if [ -f $OPENSSL_CONFIG_FILE ]; then echo "Configuration file $OPENSSL_CONFIG_FILE has already been created" exit 0; fi -OPEN_SSL_TEMPLATE_FILE=$CDB_ROOT_DIR/etc/cdb.openssl.cnf.template +OPEN_SSL_TEMPLATE_FILE=$LOGR_ROOT_DIR/etc/cdb.openssl.cnf.template echo "Creating the cdb openSSL configuration file." read -p "Enter the organizational name [company]: " SSL_ORG_NAME diff --git a/sbin/cdb_create_db.sh b/sbin/cdb_create_db.sh index 040ae74c7..afe4edd76 100755 --- a/sbin/cdb_create_db.sh +++ b/sbin/cdb_create_db.sh @@ -281,7 +281,7 @@ if [ -z "$adminWithLocalPassword" ]; then read -sp "Enter password for local portal admin (username: logr): [leave blank for no local password] " LOGR_LOCAL_SYSTEM_ADMIN_PASSWORD echo "" if [ ! -z "$LOGR_LOCAL_SYSTEM_ADMIN_PASSWORD" ]; then - adminCryptPassword=`python -c "from cdb.common.utility.cryptUtility import CryptUtility; print(str(CryptUtility.cryptPasswordWithPbkdf2('$CDB_LOCAL_SYSTEM_ADMIN_PASSWORD')))"` + adminCryptPassword=`python -c "from cdb.common.utility.cryptUtility import CryptUtility; print(str(CryptUtility.cryptPasswordWithPbkdf2('$LOGR_LOCAL_SYSTEM_ADMIN_PASSWORD')))"` echo "update user_info set password = '$adminCryptPassword' where username='logr'" > temporaryAdminCommand.sql execute $mysqlCmd temporaryAdminCommand.sql fi diff --git a/sbin/cdb_deploy_mysqld.sh b/sbin/cdb_deploy_mysqld.sh index 69513b654..ce8f885b9 100755 --- a/sbin/cdb_deploy_mysqld.sh +++ b/sbin/cdb_deploy_mysqld.sh @@ -24,7 +24,7 @@ fi . ${LOGR_ENV_FILE} > /dev/null # Use first argument as db name, if provided -LOGR_DB_NAME=${LOGR_DB_NAME:=cdb} +LOGR_DB_NAME=${LOGR_DB_NAME:=logr} if [ ! -z "$1" ]; then LOGR_DB_NAME=$1 fi diff --git a/support/bin/install_netbeans.sh b/support/bin/install_netbeans.sh index 3a9755596..8ff73e496 100755 --- a/support/bin/install_netbeans.sh +++ b/support/bin/install_netbeans.sh @@ -8,7 +8,7 @@ CDB_HOSTNAME=`hostname -f` NETBEANS_VERSION=16 NETBEANS_ZIP_FILE=netbeans-$NETBEANS_VERSION-bin.zip -DOWNLOAD_URL=https://dlcdn.apache.org/netbeans/netbeans/$NETBEANS_VERSION/$NETBEANS_ZIP_FILE +DOWNLOAD_URL=https://archive.apache.org/dist/netbeans/netbeans/$NETBEANS_VERSION/$NETBEANS_ZIP_FILE currentDir=`pwd` cd `dirname $0`/.. && topDir=`pwd` diff --git a/tools/developer_tools/logr_plugins/utilities/plugin_configuration.py b/tools/developer_tools/logr_plugins/utilities/plugin_configuration.py index ed0f8912d..f6b890952 100644 --- a/tools/developer_tools/logr_plugins/utilities/plugin_configuration.py +++ b/tools/developer_tools/logr_plugins/utilities/plugin_configuration.py @@ -28,23 +28,23 @@ def update_plugin_configuration(self, plugin_name, destination_path, configurati ext = ext_split[-1] # Verify that file is not simply called the same as extension adn if ext_split.__len__() > 1 and ext.upper() == configuration_extension.upper(): - print '\n\nUpdating configuration for plugin: %s (%s)' % (plugin_name, listing) + print('\n\nUpdating configuration for plugin: %s (%s)' % (plugin_name, listing)) plugin_listing_path = '%s/%s' % (destination_path, listing) default_configuration = open(plugin_listing_path).read() plugin_configuration_directory = "%s/%s" % (self.cdb_plugin_configuration_storage, plugin_name) plugin_stored_configuration_file = "%s/%s" % (plugin_configuration_directory, listing) if os.path.exists(plugin_stored_configuration_file): - print "Using stored configuration file: %s" % plugin_stored_configuration_file + print("Using stored configuration file: %s" % plugin_stored_configuration_file) else: - print "\n\nNo configuration exists, follow prompts\n" + print("\n\nNo configuration exists, follow prompts\n") resulting_configuration = '' for configuration_line in default_configuration.split('\n'): if configuration_line.startswith('#'): - print 'Configuration Comment: %s' % configuration_line[1:] + print('Configuration Comment: %s' % configuration_line[1:]) resulting_configuration += configuration_line elif configuration_line.startswith('['): - print "Section: %s" % configuration_line + print("Section: %s" % configuration_line) resulting_configuration += configuration_line else: configuration_split = configuration_line.split('=') @@ -56,7 +56,7 @@ def update_plugin_configuration(self, plugin_name, destination_path, configurati if configuration_split.__len__() == 2: config_default_value = configuration_split[1] - config_value = raw_input("%s [%s]: " % (config_key, config_default_value)) + config_value = input("%s [%s]: " % (config_key, config_default_value)) if config_value is None or config_value == '': config_value = config_default_value new_config_line = "%s=%s" % (config_key, config_value) @@ -76,7 +76,7 @@ def update_plugin_configuration(self, plugin_name, destination_path, configurati # Update the configuration stored. shutil.copyfile(plugin_stored_configuration_file, plugin_listing_path) - print 'New configuration stored in deployment: %s' % plugin_listing_path + print('New configuration stored in deployment: %s' % plugin_listing_path) @classmethod def backup_original_plugin_configurations(cls, plugin_storage_path, configuration_extension): @@ -98,7 +98,7 @@ def backup_original_plugin_configurations(cls, plugin_storage_path, configuratio if not os.path.exists(configuration_backup_dir): os.makedirs(configuration_backup_dir) configuration_backup_path = "%s/%s" % (configuration_backup_dir, listing) - print "Storing a default plugin configuration file %s to %s: " % (listing, configuration_backup_path) + print("Storing a default plugin configuration file %s to %s: " % (listing, configuration_backup_path)) shutil.copyfile(configuration_storage_path, configuration_backup_path) return configuration_backup_dir @@ -119,6 +119,6 @@ def restore_configuration(cls, configuration_backup_dir, plugin_storage_path): for listing in directory_listings: configuration_storage_path = "%s/%s" % (plugin_storage_path, listing) configuration_backup_storage_path = "%s/%s" % (configuration_backup_dir, listing) - print "Reverting backup file %s to %s" % (listing, configuration_storage_path) + print("Reverting backup file %s to %s" % (listing, configuration_storage_path)) shutil.move(configuration_backup_storage_path, configuration_storage_path) diff --git a/tools/developer_tools/logr_plugins/utilities/plugin_java_parser.py b/tools/developer_tools/logr_plugins/utilities/plugin_java_parser.py index 51d8c5452..6651371f9 100644 --- a/tools/developer_tools/logr_plugins/utilities/plugin_java_parser.py +++ b/tools/developer_tools/logr_plugins/utilities/plugin_java_parser.py @@ -5,7 +5,7 @@ """ import os -from plugin_configuration import PluginConfiguration +from .plugin_configuration import PluginConfiguration JAVA_PLUGIN_PACKAGE="gov.anl.aps.logr.portal.plugins.support" diff --git a/tools/developer_tools/logr_plugins/utilities/plugin_manager.py b/tools/developer_tools/logr_plugins/utilities/plugin_manager.py index 53fe678d6..68fad43a0 100644 --- a/tools/developer_tools/logr_plugins/utilities/plugin_manager.py +++ b/tools/developer_tools/logr_plugins/utilities/plugin_manager.py @@ -3,7 +3,7 @@ Copyright (c) UChicago Argonne, LLC. All rights reserved. See LICENSE file. """ -from utilities.plugin_python_parser import PluginPythonParser +from .plugin_python_parser import PluginPythonParser try: # attempt to import unique package of cdb python web service to ensure loaded environment @@ -12,17 +12,16 @@ import os, sys directory = os.path.dirname(__file__) fullPath = os.path.abspath(directory + "/../../../..") - print >> sys.stderr, "Environment not loaded. Please run `source %s/setup.sh` before running this script." % ( - fullPath) + print("Environment not loaded. Please run `source %s/setup.sh` before running this script." % fullPath, file=sys.stderr) exit(1) import os import sys -from plugin_java_parser import PluginJavaParser -from plugin_xhtml_parser import PluginXhtmlParser +from .plugin_java_parser import PluginJavaParser +from .plugin_xhtml_parser import PluginXhtmlParser -from objects.cdb_plugin import CdbPlugin +from .objects.cdb_plugin import CdbPlugin LOGR_INSTALL_DIRECTORY = os.environ['LOGR_INSTALL_DIR'] LOGR_DIST_DIRECTORY = os.environ['LOGR_ROOT_DIR'] @@ -62,11 +61,11 @@ def __select_stored_plugin_directory(self): options.append(LOGR_INSTALL_PLUGIN_DIRECTORY) options.append('Specify different directory.') - print 'Select directory for storage of cdb plugins: ' + print('Select directory for storage of cdb plugins: ') for i in range(0, options.__len__()): - print '%i - %s' % (i, options[i]) + print('%i - %s' % (i, options[i])) - selection = raw_input("%i %s [%i]: " % (i, options[i], default_option)) + selection = input("%i %s [%i]: " % (i, options[i], default_option)) if selection is None or selection == '': selection = default_option @@ -76,7 +75,7 @@ def __select_stored_plugin_directory(self): exit(1) if selection == 2: - result = raw_input("Please enter the path to directory with all plug-ins: ") + result = input("Please enter the path to directory with all plug-ins: ") else: result = options[selection] @@ -139,7 +138,7 @@ def __deploy_portal_plugin(self, selection): def __prompt_plugin_action(self, actionPrompt, actionMethod): self.list_plugins() - selection = raw_input("%s [All]: " % actionPrompt) + selection = input("%s [All]: " % actionPrompt) if selection == "" or selection == "All": selection = None else: @@ -147,11 +146,11 @@ def __prompt_plugin_action(self, actionPrompt, actionMethod): actionMethod(selection) - print "\n\nCompleted: result plugin list." + print("\n\nCompleted: result plugin list.") self.list_plugins() def update_auto_generated_files(self, update_configuration=True): - print 'Updating auto-generated CDB plugin files' + print('Updating auto-generated CDB plugin files') self.__update_autogenerated_files(update_configuration) def __update_autogenerated_files(self, update_configuration=True): @@ -194,11 +193,11 @@ def __update_autogenerated_files(self, update_configuration=True): # Create a __init__.py file for all python plugins. init_file_path = "%s/%s" % (LOGR_PYTHON_PLUGIN_PATH, '__init__.py') init_file = os.open(init_file_path, os.O_CREAT|os.O_WRONLY) - os.write(init_file, "#!/usr/bin/env python\n") - os.write(init_file, "\"\"\"\n") - os.write(init_file, "Copyright (c) UChicago Argonne, LLC. All rights reserved.\n") - os.write(init_file, "See LICENSE file.\n") - os.write(init_file, "\"\"\"") + os.write(init_file, b"#!/usr/bin/env python\n") + os.write(init_file, b"\"\"\"\n") + os.write(init_file, b"Copyright (c) UChicago Argonne, LLC. All rights reserved.\n") + os.write(init_file, b"See LICENSE file.\n") + os.write(init_file, b"\"\"\"") os.close(init_file) @staticmethod @@ -254,13 +253,13 @@ def __print_selection_list(self, selection_list, title): listItemFormat = '*%4s - %-' + str(width - 36) + 's %-6s %-6s %-12s*' - print '\nSaved plugins are located in plug-in directory: %s' % self.plugin_storage_directory - print 'for xhtml, java, python (s = stored d=deployed)' + print('\nSaved plugins are located in plug-in directory: %s' % self.plugin_storage_directory) + print('for xhtml, java, python (s = stored d=deployed)') - print "\n%s %s %s" % (header_before, title, header_after) - print listItemFormat % ('#', 'Plugin Name', 'Xhtml', 'Java', 'Python') + print("\n%s %s %s" % (header_before, title, header_after)) + print(listItemFormat % ('#', 'Plugin Name', 'Xhtml', 'Java', 'Python')) column_header_seperator = '-' * (width-2) - print '*%s*' % (column_header_seperator) + print('*%s*' % (column_header_seperator)) for i in range(0, selection_list.__len__()): plugin = selection_list[i] xhtml = '' @@ -281,8 +280,8 @@ def __print_selection_list(self, selection_list, title): xhtml += 'd' - print listItemFormat % (str(i), plugin.plugin_name, xhtml, java, python) - print '*' * width + print(listItemFormat % (str(i), plugin.plugin_name, xhtml, java, python)) + print('*' * width) if __name__ == '__main__': plugin_manager = PluginManager() diff --git a/tools/developer_tools/logr_plugins/utilities/plugin_python_parser.py b/tools/developer_tools/logr_plugins/utilities/plugin_python_parser.py index 6d9c624fb..dcfffe85a 100644 --- a/tools/developer_tools/logr_plugins/utilities/plugin_python_parser.py +++ b/tools/developer_tools/logr_plugins/utilities/plugin_python_parser.py @@ -4,7 +4,7 @@ See LICENSE file. """ -from plugin_configuration import PluginConfiguration +from .plugin_configuration import PluginConfiguration CONFIGURATION_FILE_EXTENSION = "cfg" From c58437f4c6581c4d647ba0dc945a80418cc4fc93 Mon Sep 17 00:00:00 2001 From: xiaol Date: Fri, 30 Jan 2026 15:58:03 -0600 Subject: [PATCH 3/5] adjust table's css styles --- .../LogrPortal/web/resources/css/logbook.css | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/java/LogrPortal/web/resources/css/logbook.css b/src/java/LogrPortal/web/resources/css/logbook.css index 68638bb77..2f43ea6b8 100644 --- a/src/java/LogrPortal/web/resources/css/logbook.css +++ b/src/java/LogrPortal/web/resources/css/logbook.css @@ -141,22 +141,20 @@ pre:has([class^="language-"]) { border-collapse: collapse; width: 100%; margin: 1em 0; + font-size: 14px; + line-height: 1.5; } .logEntry th, .logEntry td { border: 1px solid #ddd; - padding: 8px; - text-align: left; + padding: 10px 12px; } .logEntry th { - background-color: #f2f2f2; - font-weight: bold; -} - -.logEntry tr:nth-child(even) { - background-color: #f9f9f9; + background-color: #f5f5f5; + font-weight: 600; + color: #333; } .activeLogEntry { @@ -183,7 +181,7 @@ div.logbookSection { .markdown-example-field { background: white; width: 400px; - height: 700px; + height: 850px; } .markdown-example-field > pre { From fb11ea5209124b423644345a414b28f798ae6f5a Mon Sep 17 00:00:00 2001 From: xiaol Date: Fri, 30 Jan 2026 15:58:07 -0600 Subject: [PATCH 4/5] add table example to markdown help --- .../gov/anl/aps/logr/portal/utilities/MarkdownParser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java index ff4d9526d..3fc20c85f 100644 --- a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java +++ b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java @@ -61,6 +61,11 @@ public class MarkdownParser { + "monospaced code content goes here\n" + "```\n" + "\n\n" + + "### Table\n\n" + + "| Left | Center | Right |\n" + + "| :------- | :------: | -------: |\n" + + "| Cell 1 | Cell 2 | Cell 3 |\n" + + "\n\n" + "# Heading Levels:\n" + "# Level 1 Heading\n" + "## Level 2 Heading\n" From 446ea1a30314ba328ac02a034e8926348740809f Mon Sep 17 00:00:00 2001 From: xiaol Date: Tue, 3 Feb 2026 16:02:23 -0600 Subject: [PATCH 5/5] revise the markdown example --- .../aps/logr/portal/utilities/MarkdownParser.java | 13 +++++-------- src/java/LogrPortal/web/resources/css/logbook.css | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java index 3fc20c85f..78048395c 100644 --- a/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java +++ b/src/java/LogrPortal/src/java/gov/anl/aps/logr/portal/utilities/MarkdownParser.java @@ -62,17 +62,14 @@ public class MarkdownParser { + "```\n" + "\n\n" + "### Table\n\n" - + "| Left | Center | Right |\n" - + "| :------- | :------: | -------: |\n" - + "| Cell 1 | Cell 2 | Cell 3 |\n" + + "| Column1 | Column2 | Column3 |\n" + + "| --- | --- | --- |\n" + + "| Cell 1 | Cell 2 | Cell 3 |\n" + "\n\n" - + "# Heading Levels:\n" + + "### Heading Levels\n" + "# Level 1 Heading\n" + "## Level 2 Heading\n" - + "### Level 3 Heading\n" - + "#### Level 4 Heading\n" - + "##### Level 5 Heading\n" - + "###### Level 6 Heading\n"; + + "### Level 3 Heading\n"; private static String contextRoot = null; diff --git a/src/java/LogrPortal/web/resources/css/logbook.css b/src/java/LogrPortal/web/resources/css/logbook.css index 2f43ea6b8..c57d36421 100644 --- a/src/java/LogrPortal/web/resources/css/logbook.css +++ b/src/java/LogrPortal/web/resources/css/logbook.css @@ -181,7 +181,7 @@ div.logbookSection { .markdown-example-field { background: white; width: 400px; - height: 850px; + height: 750px; } .markdown-example-field > pre {