Added code highlighting and copy button

Update .gitignore, composer.php, and 15 more files...
This commit is contained in:
2022-11-20 21:22:12 +01:00
parent 30b1c55687
commit 4135ff6398
17 changed files with 2351 additions and 30 deletions

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@
# Static resources
resources/FontAwesomePro/
resources/HighlightJS/
*.exe
*.url

View File

@@ -90,6 +90,7 @@ abstract class ComposerElementModifiers {
const BUTTON_THICK = ["thick", "btn-lg"];
const BUTTON_ROUNDED = ["rounded", "btn-rounded"];
const BUTTON_CIRCLE = ["circle", "rounded-circle"];
const BUTTON_DOWNLOAD_PRIMARY = ["download-primary", "btn-primary"];
// Horizontal ruler
const HR_SUBTLE = ["subtle", "subtle"];
@@ -422,6 +423,8 @@ class ComposerElement {
// Code's parameters
private ?array $code;
private ?string $codeLanguage;
private bool $codeCopyable;
// Button's parameters
private ?string $color;
@@ -432,8 +435,8 @@ class ComposerElement {
function __construct(string $type, ?array $modifiers, ?string $link, ?array $parts, ?string $content,
bool $localize, ?int $padding, ?int $margin, ?int $size, ?array $head, ?array $body,
int $colspan, int $rowspan, ?int $indent, ?array $code, ?string $color, ?string $source,
?string $thumbnail) {
int $colspan, int $rowspan, ?int $indent, ?array $code, ?string $codeLanguage,
bool $codeCopyable, ?string $color, ?string $source, ?string $thumbnail) {
$this->type = $type;
$this->modifiers = $modifiers;
$this->link = $link;
@@ -456,6 +459,8 @@ class ComposerElement {
$this->rowspan = $rowspan;
$this->indent = $indent;
$this->code = $code;
$this->codeLanguage = $codeLanguage;
$this->codeCopyable = $codeCopyable;
$this->color = $color;
$this->source = $source;
$this->thumbnail = $thumbnail;
@@ -488,6 +493,8 @@ class ComposerElement {
key_exists("rowspan", $json_data) ? $json_data["rowspan"] : 1,
key_exists("indent", $json_data) ? $json_data["indent"] : null,
key_exists("code", $json_data) ? $json_data["code"] : null,
key_exists("language", $json_data) ? $json_data["language"] : null,
key_exists("copyable", $json_data) ? $json_data["copyable"] : false,
key_exists("color", $json_data) ? $json_data["color"] : null,
key_exists("source", $json_data) ? $json_data["source"] : null,
key_exists("thumbnail", $json_data) ? $json_data["thumbnail"] : null,
@@ -603,6 +610,9 @@ class ComposerElement {
case ComposerElementTypes::H1:
case ComposerElementTypes::H2:
case ComposerElementTypes::H3:
// Defining the text's indent level.
$_paragraph_ident_level = is_null($this->indent) ? 0 : $this->indent;
// Defining the text's size.
$_headingFontSize = ($this->type == ComposerElementTypes::H3 ? '18' : (
$this->type == ComposerElementTypes::H2 ? '20' : '22'
@@ -610,7 +620,7 @@ class ComposerElement {
// Composing heading.
$htmlCode .= '<' . strtolower($this->type) . ' class="font-weight-semi-bold font-size-' .
$_headingFontSize . ' m-0">' . $this->get_inner_html($content_root) . '</' . strtolower($this->type) .
$_headingFontSize . ' m-0 ml-md-' . ($_paragraph_ident_level * 5) . '">' . $this->get_inner_html($content_root) . '</' . strtolower($this->type) .
'>';
break;
@@ -652,20 +662,30 @@ class ComposerElement {
// Defining the code's indent level.
$_paragraph_ident_level = is_null($this->indent) ? 0 : $this->indent;
// Defining the highlight language.
$_language_class = is_null($this->codeLanguage) ? "nohighlight" : "language-" . $this->codeLanguage;
// Opening the code element.
// Note: The "mt-10" may have to be removed if it clashes with 'no-margin-top' !
$htmlCode .= '<code class="code ' . $this->get_modifiers_classes() .
' mt-10 ml-md-' . ($_paragraph_ident_level * 5) . '">';
$htmlCode .= '<div class="code ' . $this->get_modifiers_classes() .
' mt-10 position-relative ml-md-' . ($_paragraph_ident_level * 5) . ' ' . $_language_class . '">';
// Adding code lines.
if(!is_null($this->code)) {
foreach($this->code as $code_line) {
$htmlCode .= htmlspecialchars($code_line) . '<br>';
//$htmlCode .= htmlspecialchars($code_line) . '<br>'; // Old method (Not compatible with hljs)
$htmlCode .= '<span class="code-line">' .
str_replace(" ", "&nbsp;", htmlspecialchars($code_line)) .
'</span><br>';
}
}
if($this->codeCopyable) {
$htmlCode .= '<div class="container-card-fold primary fold-top-right js-code-copy"><i class="fad fa-copy"></i></div>';
}
// Closing code element.
$htmlCode .= '</code>';
$htmlCode .= '</div>';
break;

View File

@@ -9,7 +9,7 @@
"en": "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.<br>This tool is intended to replace the tedious task of having to use the <code>mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.",
"fr": "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemins des ports COM.<br>Cet outil a pour bût de faciliter cette tâche sans avoir à utiliser la commande <code>mode</code> ou le <i>Gestionnaire de périphérique</i>."
},
"image": "/resources/Azias/imgs/lscom/lscom-dotnet.png",
"image": "/resources/Azias/imgs/lscom/lscom-v2-text-01-bkgd-cli.png",
"tags": ["application", "tool" ,"lscom", "dotnet", "windows"]
},
{
@@ -84,7 +84,7 @@
"en": "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.<br>This tool is intended to replace the tedious task of having to use the <code>mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.",
"fr": "Un petit utilitaire pour invité de commande qui permet de facilement lister les noms, noms formatés et chemins des ports COM.<br>Cet outil a pour bût de faciliter cette tâche sans avoir à utiliser la commande <code>mode</code> ou le <i>Gestionnaire de périphérique</i>."
},
"image": "/resources/Azias/imgs/lscom/lscom-v2-text-01-bkgd-cli.png",
"image": "/resources/Azias/imgs/lscom/lscom-legacy-simple.png",
"tags": ["application", "tool" ,"lscom", "purebasic", "windows"]
}
]

View File

@@ -55,6 +55,7 @@ if($content_has_error) {
}
?>
<link href="/resources/GliderJs/1.7.6/glider.min.css" rel="stylesheet" />
<link href="/resources/HighlightJS/11.6.0/styles/atom-one-dark.min.css" rel="stylesheet" />
</head>
<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars dark-mode" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true">
<?php include 'body-root.php'; ?>
@@ -175,6 +176,9 @@ if($content_has_error) {
</div>
<script src="/resources/HalfMoon/1.1.1/js/halfmoon.min.js"></script>
<script src="/resources/GliderJs/1.7.6/glider.min.js"></script>
<script src="/resources/Azias/js/nibblepoker.lu.js"></script>
<script src="/resources/HighlightJS/11.6.0/highlight.min.js"></script>
<script src="/resources/HighlightJS/11.6.0/languages/csharp.min.js"></script>
<script src="/resources/Azias/js/nibblepoker.lu.js"></script>
<script src="/resources/Azias/js/code-highlighter.js"></script>
</body>
</html>

View File

@@ -102,6 +102,7 @@
{
"type": "code", "indent": 2,
"modifiers": ["horizontal-scroll", "code-block"],
"language": "csharp", "copyable": true,
"code": [
"// Preparing options and root verb.",
"Option OptionHelp = new('h', \"help\", \"\", OptionFlags.StopsParsing);",
@@ -119,12 +120,12 @@
"",
"// Using the results",
"if(OptionHelp.WasUsed()) {",
" Console.WriteLine(HelpText.GetFullHelpText(RootVerb, \",app.exe\",));",
" Console.WriteLine(HelpText.GetFullHelpText(RootVerb, \"app.exe\"));",
"}",
"",
"if(OptionVerbose.WasUsed() && OptionVerbose.Occurrences >= 2) {",
" // We count the number of occurences to enable more logging.",
" Console.WriteLine(\"Activating super-verbose mode !\",);",
" Console.WriteLine(\"Activating super-verbose mode !\");",
"}"
]
}

View File

@@ -27,6 +27,13 @@
"requirements.text.none.mp": "None",
"requirements.text.none.fs": "None",
"requirements.text.none.fp": "None",
"packages.title": "Packages",
"packages.single.title": "Single Builds",
"packages.single.1": "Lighter builds that only contain the exe and required licenses.<br>You will need to install the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a>.",
"packages.self.title": "Self-Contained Builds",
"packages.self.1": "Larger builds that contain the exe and the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a> as well as the required licenses.",
"packages.msi.title": "MSI Installers",
"packages.msi.1": "Windows installers that contain the relevant \"Self-Contained\" build with an option to automatically update existing installations and add the program to the <kbd>%PATH%</kbd>.<br>The install location is <kbd>%ProgramFiles%\\NibblePoker\\lscom\\</kbd> and cannot be changed. <i>(This will be possible in future releases)</i>",
"links.title": "Links"
},
"fr": {
@@ -55,6 +62,13 @@
"requirements.text.none.mp": "Aucuns",
"requirements.text.none.fs": "Aucune",
"requirements.text.none.fp": "Aucunes",
"packages.title": "Paquets",
"packages.single.title": "???&nbsp;&nbsp;<i class=\"text-super-muted\">(Single)</i>",
"packages.single.1": "Lighter builds that only contain the exe and required licenses.<br>You will need to install the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a>.",
"packages.self.title": "???&nbsp;&nbsp;<i class=\"text-super-muted\">(Self-Contained)</i>",
"packages.self.1": "Larger builds that contain the exe and the <a href=\"https://dotnet.microsoft.com/en-us/download\">.NET 6.0 Runtime</a> as well as the required licenses.",
"packages.msi.title": "Installateurs MSI",
"packages.msi.1": "Windows installers that contain the relevant \"Self-Contained\" build with an option to automatically update existing installations and add the program to the <kbd>%PATH%</kbd>.<br>The install location is <kbd>%ProgramFiles%\\NibblePoker\\lscom\\</kbd> and cannot be changed. <i>(This will be possible in future releases)</i>",
"links.title": "Liens"
}
},
@@ -207,6 +221,20 @@
]
},
{
"type": "container", "padding": 20,
"modifiers": ["no-bottom-padding", "no-top-margin"],
"parts": [
{"type": "h1", "content": "packages.title"},
{"type": "h3", "indent": 2, "content": "packages.single.title"},
{"type": "paragraph", "indent": 4, "content": "packages.single.1", "modifiers": ["no-top-margin"]},
{"type": "h3", "indent": 2, "content": "packages.self.title"},
{"type": "paragraph", "indent": 4, "content": "packages.self.1", "modifiers": ["no-top-margin"]},
{"type": "h3", "indent": 2, "content": "packages.msi.title"},
{"type": "paragraph", "indent": 4, "content": "packages.msi.1", "modifiers": ["no-top-margin"]}
]
},
{
"type": "container", "padding": 20,
"modifiers": ["_no-top-padding"],
@@ -232,11 +260,11 @@
"type": "raw",
"parts": [{
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_AnyCPU.zip",
"modifiers": ["thin"],
"modifiers": ["thin", "download-primary"],
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_AnyCPU.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_AnyCPU.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -251,7 +279,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x64_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x64_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -261,11 +289,11 @@
"type": "raw",
"parts": [{
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x64_SelfContained.zip",
"modifiers": ["thin"],
"modifiers": ["thin", "download-primary"],
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x64_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x64_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -274,11 +302,11 @@
"type": "raw",
"parts": [{
"type": "button", "link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/ListComPort_v3.0.0_x64.msi",
"modifiers": ["thin"],
"modifiers": ["thin", "download-primary"],
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x64.msi</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-archive\"></i> ListComPort_v3.0.0_x64.msi</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -293,7 +321,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x86_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x86_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -307,7 +335,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x86_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_x86_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -320,7 +348,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_x86.msi</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-archive\"></i> ListComPort_v3.0.0_x86.msi</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -335,7 +363,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_arm64_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm64_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -349,7 +377,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_arm64_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm64_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -364,7 +392,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_arm_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm_Single.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -378,7 +406,7 @@
"parts": [{
"type": "raw",
"localize": false,
"content": "<span class=\"text-monospace\">ListComPort_v3.0.0_arm_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> ListComPort_v3.0.0_arm_SelfContained.zip</span><i class=\"fas fa-download ml-10\"></i>"
}]
}]
}
@@ -412,12 +440,12 @@
{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/DotNet-ListComPort-3.0.0.zip",
"content": "<span class=\"text-monospace\">3.0.0.zip</span><i class=\"fas fa-download ml-10\"></i>",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 3.0.0.zip</span><i class=\"fas fa-download ml-10\"></i>",
"localize": false
},{
"type": "button", "modifiers": ["thin"],
"link": "https://files.nibblepoker.lu/downloads/DotNet-ListComPort/3.0.0/DotNet-ListComPort-3.0.0.tar.gz",
"content": "<span class=\"text-monospace\">3.0.0.tar.gz</span><i class=\"fas fa-download ml-10\"></i>",
"content": "<span class=\"text-monospace\"><i class=\"fad fa-file-archive\"></i> 3.0.0.tar.gz</span><i class=\"fas fa-download ml-10\"></i>",
"localize": false
}
]

View File

@@ -145,7 +145,7 @@
"type": "raw",
"parts": [{
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_eng_x64.exe",
"modifiers": ["thin"],
"modifiers": ["thin", "download-primary"],
"parts": [{
"type": "raw",
"localize": false,
@@ -159,7 +159,7 @@
"type": "raw",
"parts": [{
"type": "button", "link": "https://files.nibblepoker.lu/downloads/PB-ListComPort/2.1.0/lscom_fra_x64.exe",
"modifiers": ["thin"],
"modifiers": ["thin", "download-primary"],
"parts": [{
"type": "raw",
"localize": false,

View File

@@ -33,3 +33,5 @@ These files are required and need to be installed manually for the website to wo
* Apache 2.4 & PHP 8.1 or newer
* Font Awesome Pro v5.15.3
* `/resources/FontAwesomePro/`
* Highlight.js v11.6.0
* `/resources/HighlightJS/`

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,49 @@
// Highlights the code blocks when included on a page.
// This command is separated in its own file since highlight.js isn't on every page and because I can't use JS
// in a script element without using an external .js file.
Array.from(document.getElementsByClassName("code")).forEach(eCodeContainer => {
let language = null;
eCodeContainer.classList.forEach(cCodeContainer => {
if(cCodeContainer.startsWith("language-")) {
language = cCodeContainer;
}
});
if(language !== null) {
Array.from(eCodeContainer.children).forEach(eCodeLine => {
if(eCodeLine.classList.contains("code-line")) {
eCodeLine.classList.add(language);
hljs.highlightElement(eCodeLine);
}
});
}
});
// Adding the action to copy the code to elements with the "js-code-copy" class.
// The search works by searching the closest parent with the "code" class or that is a "code" element, and then
// reading each of its children with the "code-line" class.
Array.from(document.getElementsByClassName("js-code-copy")).forEach(eCodeCopyButton => {
let eParentCodeBlock = eCodeCopyButton;
while(eParentCodeBlock != null &&!eParentCodeBlock.classList.contains("code") &&
eParentCodeBlock.nodeName.toLowerCase() !== "code") {
eParentCodeBlock = eParentCodeBlock.parentElement;
}
if(eParentCodeBlock != null) {
let code = "";
Array.from(eParentCodeBlock.children).forEach(eCodeLine => {
if(eCodeLine.classList.contains("code-line")) {
code += eCodeLine.textContent + "\n"
}
});
eCodeCopyButton.onclick = function() {
navigator.clipboard.writeText(code);
};
}
});

View File

@@ -24,6 +24,7 @@
transition-timing-function: cubic-bezier(.47,1.64,.41,.8);
user-select: none;
cursor: pointer;
&.primary {
color: var(--dm-button-primary-text-color);
@@ -92,4 +93,19 @@
}
}
}
&.fold-top-right {
top: 0;
clip-path: polygon(0 0, 100% 0, 100% 100%);
i {
top: 0.3em;
right: 0.3rem;
}
&:hover i {
top: 0.4rem;
right: 0.4rem;
}
}
}

View File

@@ -0,0 +1,3 @@
.code-line {
background: transparent !important;
}

View File

@@ -25,3 +25,6 @@
@import 'halfmoon/element/hr';
@import 'halfmoon/element/image';
@import 'halfmoon/element/video';
/* Highlight.JS */
@import 'highlightjs/fixes';