From 92e8af31c3cac04638daa03dd397080160856246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=88=9A=28noham=29=C2=B2?= <100566912+NohamR@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:07:11 +0100 Subject: [PATCH] Initial commit --- .gitattributes | 2 + .github/workflows/deploy.yml | 84 ++++++++++++++++ LICENSE | 21 ++++ README.md | 79 +++++++++++++++ demo/archetypes/default.md | 5 + demo/content/posts/asm.md | 154 +++++++++++++++++++++++++++++ demo/hugo.toml | 3 + module/assets/css/extended/asm.css | 110 +++++++++++++++++++++ module/layouts/shortcodes/asm.html | 90 +++++++++++++++++ 9 files changed, 548 insertions(+) create mode 100644 .gitattributes create mode 100644 .github/workflows/deploy.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 demo/archetypes/default.md create mode 100644 demo/content/posts/asm.md create mode 100644 demo/hugo.toml create mode 100644 module/assets/css/extended/asm.css create mode 100644 module/layouts/shortcodes/asm.html diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..45590df --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,84 @@ +name: Deploy Hugo Demo to GitHub Pages + +on: + push: + paths-ignore: + - "LICENSE" + - "README.md" + branches: + - main + - master + workflow_dispatch: + inputs: + hugoVersion: + description: "Hugo Version" + required: false + default: "0.146.0" + +# Allow one concurrent deployment +concurrency: + group: "pages" + cancel-in-progress: true + +# Default to bash +defaults: + run: + shell: bash + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +jobs: + # Build job + build: + runs-on: ubuntu-latest + env: + HUGO_VERSION: ${{ github.event.inputs.hugoVersion || '0.146.0' }} + steps: + - name: Install Hugo CLI + run: | + wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ + && sudo dpkg -i ${{ runner.temp }}/hugo.deb + + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Pages + id: pages + uses: actions/configure-pages@v5 + + - name: Copy module files to demo + run: | + mkdir -p demo/layouts/shortcodes + mkdir -p demo/assets/css/extended + cp module/layouts/shortcodes/asm.html demo/layouts/shortcodes/ + cp module/assets/css/extended/asm.css demo/assets/css/extended/ + + - name: Build with Hugo + working-directory: ./demo + run: | + hugo \ + --buildDrafts --gc --minify \ + --baseURL "${{ steps.pages.outputs.base_url }}" + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./demo/public + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..569cd5f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 √(noham)² + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e338a8 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# hugo-asm-shortcode + +A Hugo shortcode for displaying assembly code blocks with syntax highlighting, hex bytes, and memory addresses. + +## Features + +- **Syntax highlighting** for x86 (NASM) and ARM assembly +- **Three display modes:** + - `raw` - Assembly with syntax highlighting only + - `hex` - Hex bytes + assembly instruction + - `full` - Address + hex bytes + assembly instruction +- **Capitalization option** for hex bytes and addresses +- **Dark/light mode** compatible + +## Installation + +### As a Hugo Module + +Add to your `hugo.toml`: + +```toml +[module] + [[module.imports]] + path = "github.com/NohamR/hugo-asm-shortcode" +``` + +### Manual Installation + +Copy the contents of `module/` to your Hugo site: +- `layouts/shortcodes/asm.html` → your site's `layouts/shortcodes/` +- `assets/css/extended/asm.css` → your site's `assets/css/extended/` + +## Usage + +### Raw Mode (syntax highlighting only) + +```go-html-template +{{* asm mode="raw" arch="x86" */>}} +mov rax, 1 +xor rdi, rdi +syscall +{{* /asm */>}} +``` + +### Hex Mode (hex bytes + instruction) + +```go-html-template +{{* asm mode="hex" arch="x86" */>}} +48 c7 c0 01 00 00 00 | mov rax, 1 +48 31 ff | xor rdi, rdi +0f 05 | syscall +{{* /asm */>}} +``` + +### Full Mode (address + hex + instruction) + +```go-html-template +{{* asm mode="full" arch="x86" */>}} +00401000 | 48 c7 c0 01 00 00 00 | mov rax, 1 +00401007 | 48 31 ff | xor rdi, rdi +0040100a | 0f 05 | syscall +{{* /asm */>}} +``` + +### Parameters + +| Parameter | Default | Description | +|--------------|---------|--------------------------------------------------| +| `mode` | `raw` | Display mode: `raw`, `hex`, or `full` | +| `arch` | `x86` | Architecture: `x86` or `arm` | +| `capitalize` | `false` | Uppercase hex bytes and addresses when `true` | + +## Demo + +See the `demo/` folder for a complete Hugo site example. + +## License + +MIT License - see [LICENSE](LICENSE) for details. diff --git a/demo/archetypes/default.md b/demo/archetypes/default.md new file mode 100644 index 0000000..25b6752 --- /dev/null +++ b/demo/archetypes/default.md @@ -0,0 +1,5 @@ ++++ +date = '{{ .Date }}' +draft = true +title = '{{ replace .File.ContentBaseName "-" " " | title }}' ++++ diff --git a/demo/content/posts/asm.md b/demo/content/posts/asm.md new file mode 100644 index 0000000..aac7091 --- /dev/null +++ b/demo/content/posts/asm.md @@ -0,0 +1,154 @@ +--- +title: "Adding ASM code blocks" +date: 2026-02-01 +summary: "How to add assembly code blocks in Hugo using custom shortcodes" +aliases: ["/posts/asm/"] +tags: ["hugo", "asm", "assembly", "code blocks"] +author: "Noham" +showToc: true +TocOpen: false +draft: true +hidemeta: false +comments: true +disableHLJS: false +disableShare: false +hideSummary: false +searchHidden: true +ShowReadingTime: true +ShowBreadCrumbs: true +ShowPostNavLinks: true +ShowWordCount: true +ShowRssButtonInSectionTermList: true +UseHugoToc: true +--- + +### x86 basic example +```go-html-template +{{* asm mode="raw" arch="x86" */>}} +mov rax, 1 +xor rdi, rdi +syscall +{{* /asm */>}} +``` + +{{< asm mode="raw" arch="x86" >}} +mov rax, 1 +xor rdi, rdi +syscall +{{< /asm >}} + +### ARM64 basic example +```go-html-template +{{* asm mode="raw" arch="arm" */>}} +mov w0, #1 +mov w1, #1 +add w2, w0, w1 +ret +{{* /asm */>}} +``` + +{{< asm mode="raw" arch="arm" >}} +mov w0, #1 +mov w1, #1 +add w2, w0, w1 +ret +{{< /asm >}} + + +### x86 + hex example +```go-html-template +{{* asm mode="hex" arch="x86" */>}} +48 c7 c0 01 00 00 00 | mov rax, 1 +48 31 ff | xor rdi, rdi +0f 05 | syscall +{{* /asm */>}} +``` + +{{< asm mode="hex" arch="x86" >}} +48 c7 c0 01 00 00 00 | mov rax, 1 +48 31 ff | xor rdi, rdi +0f 05 | syscall +{{< /asm >}} + +### Hex with capitalization +```go-html-template +{{* asm mode="hex" capitalize="true" */>}} +48 c7 c0 01 00 00 00 | mov rax, 1 +{{* /asm */>}} +``` + +{{< asm mode="hex" capitalize="true" >}} +48 c7 c0 01 00 00 00 | mov rax, 1 +{{< /asm >}} + +### Full example +```go-html-template +{{* asm mode="full" arch="arm" */>}} +00000000 | 20 00 80 52 | mov w0, #1 +00000004 | 21 00 80 52 | mov w1, #1 +00000008 | c0 03 5f d6 | ret +{{* /asm */>}} +``` + +{{< asm mode="full" arch="arm" >}} +00000000 | 20 00 80 52 | mov w0, #1 +00000004 | 21 00 80 52 | mov w1, #1 +00000008 | c0 03 5f d6 | ret +{{< /asm >}} + +### Full with capitalization +```go-html-template +{{* asm mode="full" arch="x86" capitalize="true" */>}} +00401000 | 48 c7 c0 01 00 00 00 | mov rax, 1 +00401007 | 48 31 ff | xor rdi, rdi +0040100a | 0f 05 | syscall +{{* /asm */>}} +``` + +{{< asm mode="full" arch="x86" capitalize="true" >}} +00401000 | 48 c7 c0 01 00 00 00 | mov rax, 1 +00401007 | 48 31 ff | xor rdi, rdi +0040100a | 0f 05 | syscall +{{< /asm >}} + +### ARM64 with hex bytes +```go-html-template +{{* asm mode="hex" arch="arm" */>}} +20 00 80 52 | mov w0, #1 +21 00 80 52 | mov w1, #1 +42 00 01 0b | add w2, w2, w1 +c0 03 5f d6 | ret +{{* /asm */>}} +``` + +{{< asm mode="hex" arch="arm" >}} +20 00 80 52 | mov w0, #1 +21 00 80 52 | mov w1, #1 +42 00 01 0b | add w2, w2, w1 +c0 03 5f d6 | ret +{{< /asm >}} + +### Longer x86 function example +```go-html-template +{{* asm mode="full" arch="x86" */>}} +00401000 | 55 | push rbp +00401001 | 48 89 e5 | mov rbp, rsp +00401004 | 48 83 ec 10 | sub rsp, 0x10 +00401008 | 89 7d fc | mov [rbp-0x4], edi +0040100b | 8b 45 fc | mov eax, [rbp-0x4] +0040100e | 83 c0 01 | add eax, 0x1 +00401011 | c9 | leave +00401012 | c3 | ret +{{* /asm */>}} +``` + +{{< asm mode="full" arch="x86" >}} +00401000 | 55 | push rbp +00401001 | 48 89 e5 | mov rbp, rsp +00401004 | 48 83 ec 10 | sub rsp, 0x10 +00401008 | 89 7d fc | mov [rbp-0x4], edi +0040100b | 8b 45 fc | mov eax, [rbp-0x4] +0040100e | 83 c0 01 | add eax, 0x1 +00401011 | c9 | leave +00401012 | c3 | ret +{{< /asm >}} diff --git a/demo/hugo.toml b/demo/hugo.toml new file mode 100644 index 0000000..7e568b8 --- /dev/null +++ b/demo/hugo.toml @@ -0,0 +1,3 @@ +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' diff --git a/module/assets/css/extended/asm.css b/module/assets/css/extended/asm.css new file mode 100644 index 0000000..af226d7 --- /dev/null +++ b/module/assets/css/extended/asm.css @@ -0,0 +1,110 @@ +/* Assembly code block styling */ +.asm-raw { + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; +} + +.asm-raw pre { + margin: 0; + padding: 1em; +} + +.asm-hex, +.asm-full { + position: relative; + font-family: 'Consolas', 'Monaco', 'Courier New', monospace; + line-height: 1.6; +} + +.asm-hex pre, +.asm-full pre { + margin: 0; + padding: 1em; + overflow-x: auto; + background: var(--hljs-bg) !important; + color: var(--content); +} + +.asm-hex code, +.asm-full code { + display: block; + background: transparent; + color: inherit; + padding: 0; +} + +.asm-line { + display: block; + white-space: pre; +} + +/* Address styling */ +.address { + color: #858585; + margin-right: 1em; + display: inline-block; + min-width: 10ch; + user-select: none; +} + +.address::after { + content: ':'; + margin-left: 0.2em; +} + +/* Hex bytes styling */ +.hex-bytes { + color: #569cd6; + margin-right: 1.5em; + display: inline-block; + min-width: 20ch; + font-weight: 500; +} + +/* Instruction styling */ +.instruction { + color: #ce9178; +} + +/* Ensure highlighted code displays inline */ +.asm-hex .line, +.asm-full .line { + display: inline; +} + +.asm-hex .cl, +.asm-full .cl { + display: inline; +} + +/* Syntax highlighting enhancements for instructions */ +.instruction::before { + content: ''; +} + +/* Dark mode compatibility */ +.dark .asm-hex pre, +.dark .asm-full pre { + background: var(--hljs-bg) !important; + color: var(--content); +} + +/* Light mode */ +@media (prefers-color-scheme: light) { + body:not(.dark) .asm-hex pre, + body:not(.dark) .asm-full pre { + background: var(--hljs-bg) !important; + color: var(--content); + } + + body:not(.dark) .address { + color: #666; + } + + body:not(.dark) .hex-bytes { + color: #0451a5; + } + + body:not(.dark) .instruction { + color: #a31515; + } +} diff --git a/module/layouts/shortcodes/asm.html b/module/layouts/shortcodes/asm.html new file mode 100644 index 0000000..652bcf0 --- /dev/null +++ b/module/layouts/shortcodes/asm.html @@ -0,0 +1,90 @@ +{{- /* Assembly code block shortcode - supports multiple display modes */ -}} +{{- /* Parameters: + - mode: "raw" (syntax highlighted), "hex" (hex + asm), "full" (addr + hex + asm) + - arch: "x86" or "arm" (default: "x86") + - capitalize: "true" to uppercase hex bytes and addresses (default: "false") +*/ -}} + +{{- $mode := .Get "mode" | default "raw" -}} +{{- $arch := .Get "arch" | default "x86" -}} +{{- $capitalize := .Get "capitalize" | default "false" -}} +{{- $content := .Inner | strings.TrimSpace -}} + +
{{- range split $content "\n" -}}
+{{- if . -}}
+
+ {{- $parts := split . "|" -}}
+ {{- if eq (len $parts) 2 -}}
+ {{- /* Extract and optionally capitalize hex bytes */ -}}
+ {{- $hexBytes := index $parts 0 | strings.TrimSpace -}}
+ {{- if eq $capitalize "true" -}}
+ {{- $hexBytes = upper $hexBytes -}}
+ {{- end -}}
+ {{- /* Extract instruction and apply syntax highlighting */ -}}
+ {{- $instruction := index $parts 1 | strings.TrimSpace -}}
+ {{- $lang := cond (eq $arch "arm") "armasm" "nasm" -}}
+ {{- $highlighted := highlight $instruction $lang "" -}}
+ {{- /* Strip wrapper divs from highlighted output */ -}}
+{{ $hexBytes }}{{ $highlighted | replaceRE "]*>]*>" "" | replaceRE "
" "" | safeHTML }}
+ {{- else -}}
+{{ . }}
+ {{- end -}}
+
+{{- end -}}
+{{- end -}}
+
+ {{- range split $content "\n" -}}
+{{- if . -}}
+
+ {{- $parts := split . "|" -}}
+ {{- if eq (len $parts) 3 -}}
+ {{- /* Extract address and hex bytes */ -}}
+ {{- $address := index $parts 0 | strings.TrimSpace -}}
+ {{- $hexBytes := index $parts 1 | strings.TrimSpace -}}
+ {{- /* Optionally capitalize address and hex bytes */ -}}
+ {{- if eq $capitalize "true" -}}
+ {{- $address = upper $address -}}
+ {{- $hexBytes = upper $hexBytes -}}
+ {{- end -}}
+ {{- /* Extract instruction and apply syntax highlighting */ -}}
+ {{- $instruction := index $parts 2 | strings.TrimSpace -}}
+ {{- $lang := cond (eq $arch "arm") "armasm" "nasm" -}}
+ {{- $highlighted := highlight $instruction $lang "" -}}
+ {{- /* Strip wrapper divs from highlighted output */ -}}
+{{ $address }}{{ $hexBytes }}{{ $highlighted | replaceRE "]*>]*>" "" | replaceRE "
" "" | safeHTML }}
+ {{- else -}}
+{{ . }}
+ {{- end -}}
+
+{{- end -}}
+{{- end -}}
+
+