elements with "language-" class prefix:
5 | var nodes = document.querySelectorAll("pre code[class^='language-']");
6 | microlight.reset(nodes);
7 | });
--------------------------------------------------------------------------------
/markdown-blog/index.md:
--------------------------------------------------------------------------------
1 | # Welcome to SkunkHTML!
2 |
3 | This is an ultra-simple blog generator built on Markdown files. Just fork this repository, and GitHub Actions will automatically create your blog. To add a new post, simply create another Markdown file with a date in its filename 🦨 — Markdown in, GitHub Pages out! No coding!
4 |
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Documentation:
2 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: "github-actions"
7 | directory: "/.github/workflows"
8 | schedule:
9 | interval: "weekly"
10 |
11 | - package-ecosystem: "nuget"
12 | directory: "/"
13 | schedule:
14 | interval: "weekly"
15 |
--------------------------------------------------------------------------------
/markdown-blog/links.md:
--------------------------------------------------------------------------------
1 | # Links
2 |
3 | Below are the most important links related to SkunkHTML:
4 |
5 | * SkunkHTML repository on GitHub
6 | [https://github.com/mg0x7BE/skunk-html](https://github.com/mg0x7BE/skunk-html)
7 | * Discussions
8 | [https://github.com/mg0x7BE/skunk-html/discussions](https://github.com/mg0x7BE/skunk-html/discussions)
9 | * Issues
10 | [https://github.com/mg0x7BE/skunk-html/issues](https://github.com/mg0x7BE/skunk-html/issues)
--------------------------------------------------------------------------------
/skunk-html.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net10.0
6 | skunk_html
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/html/script_giscus.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{title.html content}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to GitHub Pages
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | build_and_deploy:
12 | runs-on: ubuntu-latest
13 | permissions:
14 | pages: write
15 | id-token: write
16 | steps:
17 | - name: Checkout repository
18 | uses: actions/checkout@v6
19 |
20 | - name: Setup .NET
21 | uses: actions/setup-dotnet@v5
22 | with:
23 | dotnet-version: 9
24 |
25 | - name: Build project
26 | run: dotnet build skunk-html.fsproj
27 |
28 | - name: Run F# code to generate HTML
29 | run: dotnet run --project skunk-html.fsproj
30 |
31 | - name: Upload artifact
32 | uses: actions/upload-pages-artifact@v4
33 | with:
34 | path: "./skunk-html-output"
35 |
36 | - name: Deploy to GitHub Pages
37 | id: deployment
38 | uses: actions/deploy-pages@v4
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/css/tweaks.css:
--------------------------------------------------------------------------------
1 | nav a img {
2 |
3 | border-style: outset;
4 | border-color: var(--color-link);
5 | border-width: 1px;
6 | box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
7 | }
8 |
9 |
10 |
11 | blockquote,
12 | blockquote p {
13 | display: block;
14 | font-size: medium;
15 | line-height: var(--line-height);
16 | text-align: var(--justify-normal);
17 | border-right: none;
18 | border-left: 0.25rem solid var(--color-accent);
19 | padding: 0 0 0 1rem;
20 | margin-left: 0;
21 | max-width: 100%;
22 | }
23 |
24 | blockquote p {
25 | border-left: none;
26 | }
27 |
28 | blockquote footer {
29 | color: var(--color-text);
30 | display: block;
31 | font-size: small;
32 | line-height: var(--line-height);
33 | padding: 1.5rem 0;
34 | }
35 |
36 | a {
37 | text-decoration: none;
38 | word-break: break-word;
39 | }
40 |
41 | * {
42 | scrollbar-width: auto;
43 | }
44 |
45 | nav {
46 | margin-bottom: 1rem;
47 | }
48 |
49 | p img,
50 | pre,
51 | pre code,
52 | pre samp {
53 | max-width: 100%;
54 | }
55 |
56 | table td[align],
57 | table th[align] {
58 | text-align: left !important;
59 | }
60 |
61 | table td[align="center"],
62 | table th[align="center"] {
63 | text-align: center !important;
64 | }
65 |
66 | table td[align="right"],
67 | table th[align="right"] {
68 | text-align: right !important;
69 | }
--------------------------------------------------------------------------------
/markdown-blog/2024-12-26.md:
--------------------------------------------------------------------------------
1 | # Setup guide
2 |
3 | It's not an exaggeration - you really can build your own website in less than 60 seconds using SkunkHTML. You just need to know where to click.
4 |
5 | ### 1. Login to GitHub
6 |
7 | Log in to GitHub and fork SkunkHTML [repository](https://github.com/mg0x7BE/skunk-html):
8 |
9 | 
10 |
11 | ### 2. Name your repo
12 |
13 | Name your new repository. If you haven't used GitHub Pages before, name it `.github.io` (where `` is your GitHub username). This way your new site will be available at `http://.github.io`.
14 |
15 | 
16 |
17 | If you already have this address taken because you're using another site, you can use any name, for example `just-a-test`. Then the site will be available at `http://.github.io/just-a-test`.
18 |
19 | ### 3. Enable workflows
20 |
21 | Make sure that workflows are enabled in the Actions tab. If not, be sure to enable them:
22 |
23 | 
24 |
25 | ### 4. Enable GitHub Pages
26 |
27 | GitHub Pages is the service responsible for hosting your website on GitHub (for free). We need to enable it too:
28 |
29 | 
30 |
31 | ### 5. Run your new workflow.
32 |
33 | If your workflow hasn't had any runs before, run it:
34 |
35 | 
36 |
37 | If you already had a website before, it's possible that the workflow ran but didn't work because GitHub Pages wasn't enabled in this repo yet. In that case, simply run it again now:
38 |
39 | 
40 |
41 | ### 6. Done!
42 |
43 | Done! Your new site should appear shortly at the address that corresponds to your repository name (see step 2).
--------------------------------------------------------------------------------
/Program.fs:
--------------------------------------------------------------------------------
1 | open System.IO
2 | open SkunkUtils
3 | open SkunkHtml
4 |
5 | []
6 | let main argv =
7 | argv |> ignore
8 |
9 | if not (Directory.Exists(Config.markdownDir)) then
10 | printfn $"Markdown directory does not exist : {Config.markdownDir}"
11 | failwith "Markdown directory not found"
12 |
13 | if not (Directory.Exists(Config.outputDir)) then
14 | printfn $"Creating {Path.GetFileName Config.outputDir} folder"
15 | Directory.CreateDirectory(Config.outputDir)
16 | |> ignore
17 |
18 | let header = Disk.readFile (Path.Combine(Config.htmlDir, "header.html"))
19 | let footer = Disk.readFile (Path.Combine(Config.htmlDir, "footer.html"))
20 |
21 | let allMarkdownFiles = Directory.GetFiles(Config.markdownDir, "*.md")
22 |
23 | let blogArticleFiles =
24 | allMarkdownFiles
25 | |> Array.filter isArticle
26 |
27 | let listOfAllBlogArticles =
28 | blogArticleFiles
29 | |> Array.map (fun file ->
30 | let date = Path.GetFileNameWithoutExtension(file)
31 | let title = extractTitleFromMarkdownFile(file)
32 | let urlFriendlyTitle = Url.toUrlFriendly title
33 | (date, title, $"{urlFriendlyTitle}.html"))
34 | |> Array.sortByDescending (fun (date, _, _) -> date)
35 | |> Array.toList
36 |
37 | let createBlogArticlePages () =
38 | blogArticleFiles
39 | |> Array.iter (createPage header footer)
40 |
41 | let createOtherPages () =
42 | allMarkdownFiles
43 | |> Array.filter (fun file -> not (isArticle file))
44 | |> Array.filter (fun file -> Path.GetFileName(file) <> Config.frontPageMarkdownFileName)
45 | |> Array.iter (createPage header footer)
46 |
47 | createIndexPage header footer listOfAllBlogArticles
48 | createOtherPages ()
49 | createBlogArticlePages ()
50 |
51 |
52 | Disk.copyFolderToOutput Config.fontsDir Config.outputFontsDir
53 | Disk.copyFolderToOutput Config.cssDir Config.outputCssDir
54 | Disk.copyFolderToOutput Config.imagesDir Config.outputImagesDir
55 | Disk.copyFolderToOutput Config.assetsDir Config.outputAssetsDir
56 | Disk.copyFolderToOutput Config.scriptsDir Config.outputScriptsDir
57 |
58 | printf "\nBuild complete. Your site is ready for deployment!"
59 | 0
60 |
--------------------------------------------------------------------------------
/SkunkUtils.fs:
--------------------------------------------------------------------------------
1 | module SkunkUtils
2 |
3 | module Config =
4 | open System.IO
5 |
6 | let sourceDir = __SOURCE_DIRECTORY__
7 |
8 | let markdownDir = Path.Combine(sourceDir, "markdown-blog")
9 | let htmlDir = Path.Combine(sourceDir, "html")
10 | let outputDir = Path.Combine(sourceDir, "skunk-html-output")
11 |
12 | let cssDir = Path.Combine(sourceDir, "css")
13 | let outputCssDir = Path.Combine(outputDir, "css")
14 |
15 | let fontsDir = Path.Combine(sourceDir, "fonts")
16 | let outputFontsDir = Path.Combine(outputDir, "fonts")
17 |
18 | let imagesDir = Path.Combine(markdownDir, "images")
19 | let outputImagesDir = Path.Combine(outputDir, "images")
20 |
21 | let assetsDir = Path.Combine(sourceDir, "assets")
22 | let outputAssetsDir = Path.Combine(outputDir, "assets")
23 |
24 | let scriptsDir = Path.Combine(sourceDir, "scripts")
25 | let outputScriptsDir = Path.Combine(outputDir, "scripts")
26 |
27 | let frontPageMarkdownFileName = "index.md"
28 |
29 | module Disk =
30 | open System.IO
31 |
32 | let readFile (path: string) =
33 | path
34 | |> File.Exists
35 | |> function
36 | | true -> File.ReadAllText(path)
37 | | false -> ""
38 |
39 | let writeFile (path: string) (content: string) =
40 | File.WriteAllText(path, content)
41 | printfn $"Generated: {Path.GetFileName path} -> {path}\n"
42 |
43 | let copyFolderToOutput (sourceFolder: string) (destinationFolder: string) =
44 | if not (Directory.Exists(sourceFolder)) then
45 | printfn $"Source folder does not exist: {sourceFolder}"
46 | else
47 | if not (Directory.Exists(destinationFolder)) then
48 | Directory.CreateDirectory(destinationFolder)
49 | |> ignore
50 |
51 | Directory.GetFiles(sourceFolder)
52 | |> Array.iter (fun file ->
53 | let fileName = Path.GetFileName(file)
54 | let destFile = Path.Combine(destinationFolder, fileName)
55 | printfn $"Copying: {fileName} -> {destFile}"
56 | File.Copy(file, destFile, true))
57 |
58 | module Url =
59 | open System.Text.RegularExpressions
60 |
61 | let toUrlFriendly (input: string) =
62 | input.ToLowerInvariant()
63 | |> fun text -> Regex.Replace(text, @"[^\w\s]", "") // Remove all non-alphanumeric characters
64 | |> fun text -> Regex.Replace(text, @"\s+", "-") // Replace spaces with hyphens
--------------------------------------------------------------------------------
/markdown-blog/2024-12-27.md:
--------------------------------------------------------------------------------
1 | # Customization
2 |
3 | OK, you've read the [Setup guide](setup-guide.html) and [Blogging with Markdown](blogging-with-markdown.html). You have your site online, everything works beautifully but you're wondering how to adapt it to your needs. It's very simple, we just need to change a few things.
4 |
5 | ## Title
6 |
7 | The site title, which appears as the browser tab name, can be found in the `/html/` folder in the `title.html` file.
8 |
9 | ## Avatar and icons
10 |
11 | The avatar at the top can be found in the `/assets/` folder as `avatar.jpg`. You can replace it with another one. Next to it are icons for various browsers and devices, such as favicon.svg. You can replace these files with others.
12 |
13 | You can also use a different set of images and formats. In that case, make sure to update the header in the `/html/` folder in the `head.html` file. If you google for "favicon generator" you'll find millions of sites that generate these types of assets for different devices.
14 |
15 | ## More sections!
16 |
17 | You can find how to create blog posts in the [Blogging with Markdown](blogging-with-markdown.html) article. However, if you'd like to add a new tab (next to "Home" and "Links"), you just need to create a new markdown file and add a reference to it in the `header.html` file in the `/html/` folder.
18 |
19 | For example, create a file called `whatever.md` with this content:
20 |
21 | ```
22 | # Favorite food
23 | This page will contain a list of my favorite dishes
24 | ```
25 |
26 | When you save this file in the `/markdown-blog/` folder, the build process will generate a `favorite-food.html` (file name based on the title inside the file).
27 |
28 | So the only thing left to do is add a link in the `header.html` file in the `/html/` folder:
29 |
30 | ```html
31 |
36 | ```
37 | ## Colors and CSS
38 |
39 | If you'd like to play with colors and CSS changes, you'll find everything in the `/css/` folder. There are two files:
40 |
41 | - `styles.css` is the original, unmodified MVP.css v1.17 - https://github.com/andybrewer/mvp
42 | - `tweaks.css` contains small tweaks that override the above settings in several places. You can modify this freely or even delete it and simply insert your own styles.
43 |
44 | You can find references to these files in the `/html/` folder in `head.html`. You can completely replace these CSS files with something else.
45 |
46 | You can see how such a modified site might look here: https://mg0x7BE.github.io/
47 |
48 |
49 | ## Blog comments system
50 |
51 | SkunkHTML integrates beautifully with [giscus](https://giscus.app/).
52 | It allows to add comments under each blog post. Everything about this topic can be found on the giscus website. All you need to know is that you'll find the configuration script in the `/html/` folder in the `script_giscus.html` file. It's currently commented out. Remove the arrows and adjust it according to what's described on the giscus website.
53 |
54 | As above, you can see an example of such integration at https://mg0x7BE.github.io/
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | 
4 | 
5 | 
6 | 
7 |
8 | # SkunkHTML
9 |
10 | Automatically generate a website on GitHub Pages using Markdown files.
11 |
12 | 
13 |
14 | Markdown in, GitHub Pages out!
15 |
16 | ## SkunkHTML setup
17 | Your own Markdown blog on GitHub.
18 |
19 | 1. Fork [SkunkHTML](https://github.com/mg0x7BE/skunk-html) repository on GitHub.
20 | 2. Enable GitHub Pages in the repository settings (choose GitHub Actions as the source).
21 | 3. Done. Your blog is online. Example: https://mg0x7BE.github.io/skunk-html/
22 |
23 | Upload Markdown (.md) files to publish new posts.
24 |
25 | ## How it works
26 |
27 | When a Markdown (.md) file is created and placed in the `/markdown-blog/` folder, the rest happens automatically. GitHub Actions detects changes pushed to the repository, triggers the build process, and deploys the updated site.
28 |
29 | ## Some technical details
30 |
31 | - Blog articles and other content are written in Markdown, allowing for easy content creation and management. These Markdown files are automatically converted to HTML during the build process using F# and the [FSharp.Formatting](https://github.com/fsprojects/FSharp.Formatting) library.
32 |
33 | - The deployment process is fully automated using [GitHub Actions](https://github.com/features/actions). Any changes to this repository are immediately reflected on the live site.
34 |
35 | - [Giscus](https://giscus.app/) comment system is supported.
36 |
37 | - The repository is 100% ready to work directly on GitHub without the need to download it locally. Simply fork it to create your own website. Don't forget to enable GitHub Pages in repo! (Settings ➔ Pages ➔ Build and deployment: "GitHub Actions").
38 |
39 | ## Folder structure
40 |
41 | - `/`: Root directory of the project.
42 |
43 | - `.github/workflows/`: GitHub Actions workflow file. Responsible for automatically generating final website on GitHub Pages
44 | - `assets/`: Files used across the entire site, such as the avatar, favicon, and other shared resources.
45 | - `css/`: CSS files for the site.
46 | - `fonts/`: Custom fonts go here.
47 | - `html/`: HTML fragments used throughout the site, such as the title and footer.
48 | - `markdown-blog/`: Directory containing the Markdown files for articles and other content. Blog articles are identified by file names that start with a digit.
49 | - `images/`: Images used in the articles.
50 | - `scripts/`: Syntax highlighting script and optionally other custom scripts..
51 | - `skunk-html-output/`: Directory that will be created during the build process, with the generated HTML files.
52 |
53 | - `LICENSE`: License file for the project.
54 | - `Program.fs`: F# program that handles the generation of HTML from Markdown
55 | - `README.md`: This file.
56 | - `skunk-html.fsproj`: Project file
57 |
58 | ## Examples
59 |
60 | Detailed examples can be found at: https://mg0x7BE.github.io/skunk-html
61 |
62 | ## Contributing
63 |
64 | Suggestions, bug reports, and pull requests welcome. Use discussions, issues, or PRs.
65 |
66 | ## License
67 |
68 | This project is licensed under the terms of the [Unlicense](https://en.wikipedia.org/wiki/Unlicense).
69 |
70 | ## Dependencies
71 |
72 | - [MVP.css](https://github.com/andybrewer/mvp) for styling
73 | - [microlight.js](https://github.com/asvd/microlight) for syntax highlighting
74 | - [FSharp.Formatting](https://github.com/fsprojects/FSharp.Formatting) library for Markdown processing
75 |
76 | ## Optional self-hosting and custom build
77 |
78 | To build locally:
79 |
80 | 1. [Download](https://dotnet.microsoft.com/en-us/download) and install .NET on Linux / macOS / Windows
81 | 2. Run the following commands
82 | ```
83 | git clone https://github.com/mg0x7BE/skunk-html.git
84 | cd skunk-html
85 | dotnet restore
86 | dotnet run
87 | ```
88 | 3. Done. Your site is in the `skunk-html-output` folder.
89 |
--------------------------------------------------------------------------------
/SkunkHtml.fs:
--------------------------------------------------------------------------------
1 | module SkunkHtml
2 | open SkunkUtils
3 | open System.IO
4 | open FSharp.Formatting.Markdown
5 |
6 | let generateFinalHtml (head: string) (header: string) (footer: string) (content: string) (script: string) =
7 | $"""
8 |
9 |
10 |
11 | {head}
12 |
13 |
14 |
15 | {header}
16 |
17 |
18 | {content}
19 |
20 |
21 |
24 |
27 |
28 |
29 | """
30 |
31 | let head (titleSuffix: string) =
32 | let headTemplate =
33 | Path.Combine(Config.htmlDir, "head.html")
34 | |> Disk.readFile
35 |
36 | let titleTemplate =
37 | Path.Combine(Config.htmlDir, "title.html")
38 | |> Disk.readFile
39 |
40 | headTemplate.Replace("{{title.html content}}", titleTemplate + titleSuffix)
41 |
42 | let isArticle (file: string) =
43 | System.Char.IsDigit(Path.GetFileName(file).[0])
44 |
45 | let highlightingScript =
46 | Path.Combine(Config.htmlDir, "script_syntax_highlighting.html")
47 | |> Disk.readFile
48 |
49 | let extractTitleFromMarkdownFile (markdownFilePath: string) =
50 | File.ReadAllLines(markdownFilePath)
51 | |> Array.tryFind _.StartsWith("# ")
52 | |> Option.defaultValue "# No Title"
53 | |> _.TrimStart('#').Trim()
54 |
55 | let createPage (header: string) (footer: string) (markdownFilePath: string) =
56 | let title = extractTitleFromMarkdownFile(markdownFilePath)
57 | let fileName = Url.toUrlFriendly title
58 | let outputHtmlFilePath = Path.Combine(Config.outputDir, fileName + ".html")
59 | let markdownContent = File.ReadAllText(markdownFilePath)
60 |
61 | let htmlContent =
62 | match isArticle markdownFilePath with
63 | | false -> Markdown.ToHtml(markdownContent)
64 | | true ->
65 | let date = Path.GetFileNameWithoutExtension(markdownFilePath)
66 |
67 | let publicationDate =
68 | $"""Published on
"""
69 |
70 | let giscusScript =
71 | Path.Combine(Config.htmlDir, "script_giscus.html")
72 | |> Disk.readFile
73 |
74 | let mainHtmlContent = Markdown.ToHtml(
75 | markdownContent
76 | + "\n\n"
77 | + publicationDate
78 | + "\n\n"
79 | )
80 | mainHtmlContent + giscusScript
81 |
82 | let finalHtmlContent =
83 | generateFinalHtml (head (" - " + title)) header footer htmlContent highlightingScript
84 |
85 | printfn $"Processing {Path.GetFileName markdownFilePath} ->"
86 | Disk.writeFile outputHtmlFilePath finalHtmlContent
87 |
88 | let createIndexPage (header: string) (footer: string) (listOfAllBlogArticles: (string * string * string) list) =
89 | let frontPageMarkdownFilePath = Path.Combine(Config.markdownDir, Config.frontPageMarkdownFileName)
90 |
91 | let frontPageContentHtml =
92 | if File.Exists(frontPageMarkdownFilePath) then
93 | printfn $"Processing {Path.GetFileName frontPageMarkdownFilePath} ->"
94 | Markdown.ToHtml(File.ReadAllText(frontPageMarkdownFilePath))
95 | else
96 | printfn $"Warning! File {Config.frontPageMarkdownFileName} does not exist! The main page will only contain blog entries, without a welcome message"
97 | ""
98 |
99 | let listOfAllBlogArticlesContentHtml =
100 | listOfAllBlogArticles
101 | |> List.map (fun (date, title, link) -> $"""{date}: {title} """)
102 | |> String.concat "\n"
103 |
104 | let content =
105 | $"""
106 | {frontPageContentHtml}
107 |
108 | blog entries
109 |
110 | {listOfAllBlogArticlesContentHtml}
111 |
112 |
113 | """
114 |
115 | let frontPageHtmlContent = generateFinalHtml (head "") header footer content highlightingScript
116 | let indexHtmlFilePath = Path.Combine(Config.outputDir, "index.html")
117 |
118 | Disk.writeFile indexHtmlFilePath frontPageHtmlContent
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]utput/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | # but not Directory.Build.rsp, as it configures directory-level build defaults
87 | !Directory.Build.rsp
88 | *.sbr
89 | *.tlb
90 | *.tli
91 | *.tlh
92 | *.tmp
93 | *.tmp_proj
94 | *_wpftmp.csproj
95 | *.log
96 | *.tlog
97 | *.vspscc
98 | *.vssscc
99 | .builds
100 | *.pidb
101 | *.svclog
102 | *.scc
103 |
104 | # Chutzpah Test files
105 | _Chutzpah*
106 |
107 | # Visual C++ cache files
108 | ipch/
109 | *.aps
110 | *.ncb
111 | *.opendb
112 | *.opensdf
113 | *.sdf
114 | *.cachefile
115 | *.VC.db
116 | *.VC.VC.opendb
117 |
118 | # Visual Studio profiler
119 | *.psess
120 | *.vsp
121 | *.vspx
122 | *.sap
123 |
124 | # Visual Studio Trace Files
125 | *.e2e
126 |
127 | # TFS 2012 Local Workspace
128 | $tf/
129 |
130 | # Guidance Automation Toolkit
131 | *.gpState
132 |
133 | # ReSharper is a .NET coding add-in
134 | _ReSharper*/
135 | *.[Rr]e[Ss]harper
136 | *.DotSettings.user
137 |
138 | # TeamCity is a build add-in
139 | _TeamCity*
140 |
141 | # DotCover is a Code Coverage Tool
142 | *.dotCover
143 |
144 | # AxoCover is a Code Coverage Tool
145 | .axoCover/*
146 | !.axoCover/settings.json
147 |
148 | # Coverlet is a free, cross platform Code Coverage Tool
149 | coverage*.json
150 | coverage*.xml
151 | coverage*.info
152 |
153 | # Visual Studio code coverage results
154 | *.coverage
155 | *.coveragexml
156 |
157 | # NCrunch
158 | _NCrunch_*
159 | .*crunch*.local.xml
160 | nCrunchTemp_*
161 |
162 | # MightyMoose
163 | *.mm.*
164 | AutoTest.Net/
165 |
166 | # Web workbench (sass)
167 | .sass-cache/
168 |
169 | # Installshield output folder
170 | [Ee]xpress/
171 |
172 | # DocProject is a documentation generator add-in
173 | DocProject/buildhelp/
174 | DocProject/Help/*.HxT
175 | DocProject/Help/*.HxC
176 | DocProject/Help/*.hhc
177 | DocProject/Help/*.hhk
178 | DocProject/Help/*.hhp
179 | DocProject/Help/Html2
180 | DocProject/Help/html
181 |
182 | # Click-Once directory
183 | publish/
184 |
185 | # Publish Web Output
186 | *.[Pp]ublish.xml
187 | *.azurePubxml
188 | # Note: Comment the next line if you want to checkin your web deploy settings,
189 | # but database connection strings (with potential passwords) will be unencrypted
190 | *.pubxml
191 | *.publishproj
192 |
193 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
194 | # checkin your Azure Web App publish settings, but sensitive information contained
195 | # in these scripts will be unencrypted
196 | PublishScripts/
197 |
198 | # NuGet Packages
199 | *.nupkg
200 | # NuGet Symbol Packages
201 | *.snupkg
202 | # The packages folder can be ignored because of Package Restore
203 | **/[Pp]ackages/*
204 | # except build/, which is used as an MSBuild target.
205 | !**/[Pp]ackages/build/
206 | # Uncomment if necessary however generally it will be regenerated when needed
207 | #!**/[Pp]ackages/repositories.config
208 | # NuGet v3's project.json files produces more ignorable files
209 | *.nuget.props
210 | *.nuget.targets
211 |
212 | # Microsoft Azure Build Output
213 | csx/
214 | *.build.csdef
215 |
216 | # Microsoft Azure Emulator
217 | ecf/
218 | rcf/
219 |
220 | # Windows Store app package directories and files
221 | AppPackages/
222 | BundleArtifacts/
223 | Package.StoreAssociation.xml
224 | _pkginfo.txt
225 | *.appx
226 | *.appxbundle
227 | *.appxupload
228 |
229 | # Visual Studio cache files
230 | # files ending in .cache can be ignored
231 | *.[Cc]ache
232 | # but keep track of directories ending in .cache
233 | !?*.[Cc]ache/
234 |
235 | # Others
236 | ClientBin/
237 | ~$*
238 | *~
239 | *.dbmdl
240 | *.dbproj.schemaview
241 | *.jfm
242 | *.pfx
243 | *.publishsettings
244 | orleans.codegen.cs
245 |
246 | # Including strong name files can present a security risk
247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
248 | #*.snk
249 |
250 | # Since there are multiple workflows, uncomment next line to ignore bower_components
251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
252 | #bower_components/
253 |
254 | # RIA/Silverlight projects
255 | Generated_Code/
256 |
257 | # Backup & report files from converting an old project file
258 | # to a newer Visual Studio version. Backup files are not needed,
259 | # because we have git ;-)
260 | _UpgradeReport_Files/
261 | Backup*/
262 | UpgradeLog*.XML
263 | UpgradeLog*.htm
264 | ServiceFabricBackup/
265 | *.rptproj.bak
266 |
267 | # SQL Server files
268 | *.mdf
269 | *.ldf
270 | *.ndf
271 |
272 | # Business Intelligence projects
273 | *.rdl.data
274 | *.bim.layout
275 | *.bim_*.settings
276 | *.rptproj.rsuser
277 | *- [Bb]ackup.rdl
278 | *- [Bb]ackup ([0-9]).rdl
279 | *- [Bb]ackup ([0-9][0-9]).rdl
280 |
281 | # Microsoft Fakes
282 | FakesAssemblies/
283 |
284 | # GhostDoc plugin setting file
285 | *.GhostDoc.xml
286 |
287 | # Node.js Tools for Visual Studio
288 | .ntvs_analysis.dat
289 | node_modules/
290 |
291 | # Visual Studio 6 build log
292 | *.plg
293 |
294 | # Visual Studio 6 workspace options file
295 | *.opt
296 |
297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
298 | *.vbw
299 |
300 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
301 | *.vbp
302 |
303 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
304 | *.dsw
305 | *.dsp
306 |
307 | # Visual Studio 6 technical files
308 | *.ncb
309 | *.aps
310 |
311 | # Visual Studio LightSwitch build output
312 | **/*.HTMLClient/GeneratedArtifacts
313 | **/*.DesktopClient/GeneratedArtifacts
314 | **/*.DesktopClient/ModelManifest.xml
315 | **/*.Server/GeneratedArtifacts
316 | **/*.Server/ModelManifest.xml
317 | _Pvt_Extensions
318 |
319 | # Paket dependency manager
320 | .paket/paket.exe
321 | paket-files/
322 |
323 | # FAKE - F# Make
324 | .fake/
325 |
326 | # CodeRush personal settings
327 | .cr/personal
328 |
329 | # Python Tools for Visual Studio (PTVS)
330 | __pycache__/
331 | *.pyc
332 |
333 | # Cake - Uncomment if you are using it
334 | # tools/**
335 | # !tools/packages.config
336 |
337 | # Tabs Studio
338 | *.tss
339 |
340 | # Telerik's JustMock configuration file
341 | *.jmconfig
342 |
343 | # BizTalk build output
344 | *.btp.cs
345 | *.btm.cs
346 | *.odx.cs
347 | *.xsd.cs
348 |
349 | # OpenCover UI analysis results
350 | OpenCover/
351 |
352 | # Azure Stream Analytics local run output
353 | ASALocalRun/
354 |
355 | # MSBuild Binary and Structured Log
356 | *.binlog
357 |
358 | # NVidia Nsight GPU debugger configuration file
359 | *.nvuser
360 |
361 | # MFractors (Xamarin productivity tool) working folder
362 | .mfractor/
363 |
364 | # Local History for Visual Studio
365 | .localhistory/
366 |
367 | # Visual Studio History (VSHistory) files
368 | .vshistory/
369 |
370 | # BeatPulse healthcheck temp database
371 | healthchecksdb
372 |
373 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
374 | MigrationBackup/
375 |
376 | # Ionide (cross platform F# VS Code tools) working folder
377 | .ionide/
378 |
379 | # Fody - auto-generated XML schema
380 | FodyWeavers.xsd
381 |
382 | # VS Code files for those working on multiple tools
383 | .vscode/*
384 | !.vscode/settings.json
385 | !.vscode/tasks.json
386 | !.vscode/launch.json
387 | !.vscode/extensions.json
388 | *.code-workspace
389 |
390 | # Local History for Visual Studio Code
391 | .history/
392 |
393 | # Windows Installer files from build outputs
394 | *.cab
395 | *.msi
396 | *.msix
397 | *.msm
398 | *.msp
399 |
400 | # JetBrains Rider
401 | *.sln.iml
402 | .idea/
403 |
404 | # MacOS system file
405 | .DS_Store
406 |
407 | # Skunk HTML output
408 | [Ss]kunk-html-output/
--------------------------------------------------------------------------------
/markdown-blog/2024-12-25.md:
--------------------------------------------------------------------------------
1 | # Blogging with Markdown
2 |
3 | Markdown is an ultra-simple markup language that allows you to format text using any editor. When you place such a file (.md) in the `/markdown-blog/` folder, it automatically becomes a blog post.
4 |
5 | Below you'll find some important information specific to SkunkHTML, as well as a comprehensive tutorial on how to write Markdown.
6 |
7 | ## Creating a blog post
8 |
9 | Create a new text file and make a blog post header inside. In Markdown, headers are marked with the `#` symbol. For example:
10 |
11 | ```
12 | # Testing SkunkHTML
13 |
14 | I don't know how it works yet, but I'll find out!
15 | ```
16 | Name this file using a date in any format, but it's important that it starts with a number. For example `2024-12-27.md` (.md is the standard extension for Markdown files)
17 |
18 | Place this file in the `/markdown-blog/` folder. If you're doing this on GitHub with Pages enabled, you'll see your new post appear on your site shortly:
19 |
20 | 
21 |
22 | It's that simple! Just remember that you use `#` to mark your page title, and to use date in file name. Later in the file, you can use additional headers freely. Only the first one matters for the blog post title.
23 |
24 | Markdown is super convenient if you just want to write something without fiddling with HTML, and that's exactly how SkunkHTML works.
25 |
26 | ---
27 |
28 | # Headers
29 |
30 | ```
31 | # This is heading 1
32 | ## This is heading 2
33 | ### This is heading 3
34 | #### This is heading 4
35 | ##### This is heading 5
36 | ###### This is heading 6
37 | ```
38 |
39 | # This is heading 1
40 | ## This is heading 2
41 | ### This is heading 3
42 | #### This is heading 4
43 | ##### This is heading 5
44 | ###### This is heading 6
45 |
46 | ---
47 |
48 | # Lists
49 |
50 | ```
51 | * Unordered lists will start with asterisks
52 | - Or with dashes
53 | + Or with plus signs
54 |
55 | 1. To create an ordered list, You can start lines with numbers followed by periods
56 | 1. Indent with 4 spaces or a tab to create sub-items
57 | 2. Use further indentation to create nested lists
58 | - It's possible to mix and match list types
59 |
60 | 2. Sub-lists within unordered lists will use different markers automatically:
61 | * Any marker can be used for the first level
62 | + And any marker for new sub-levels:
63 | * You can use asterisks
64 | + Or plus signs
65 | - Or dashes
66 | ```
67 |
68 | * Unordered lists will start with asterisks
69 | - Or with dashes
70 | + Or with plus signs
71 |
72 | 1. To create an ordered list, You can start lines with numbers followed by periods
73 | 1. Indent with 4 spaces or a tab to create sub-items
74 | 2. Use further indentation to create nested lists
75 | - It's possible to mix and match list types
76 |
77 | 2. Sub-lists within unordered lists will use different markers automatically:
78 | * Any marker can be used for the first level
79 | + And any marker for new sub-levels:
80 | * You can use asterisks
81 | + Or plus signs
82 | - Or dashes
83 |
84 | ---
85 |
86 | # Emphasis
87 |
88 | ```
89 | Italics: *single asterisks* or _single underscores_
90 |
91 | Bold: **double asterisks** or __double underscores__
92 |
93 | Combined bold and italics: **_double asterisks and single underscores_**
94 |
95 | All bold and italic: ***triple asterisks*** or ___triple underscores___
96 | ```
97 |
98 | Italics: *single asterisks* or _single underscores_
99 |
100 | Bold: **double asterisks** or __double underscores__
101 |
102 | Combined bold and italics: **_double asterisks and single underscores_**
103 |
104 | All bold and italic: ***triple asterisks*** or ___triple underscores___
105 |
106 | ---
107 |
108 | # Links
109 |
110 | ```
111 | [Example website](https://www.example.net)
112 |
113 | [Same website with a title](https://www.example.net "Example Website")
114 |
115 | [Link to a file in the project](./images/skunk-final.png)
116 |
117 | [Numbers can be used for reference links][1]
118 |
119 | Or simply [text as the reference].
120 |
121 | URLs will automatically become links: https://www.example.net or .
122 |
123 | ... and here are some reference links defined later in the document that won't be visible in the rendered HTML:
124 |
125 | [1]: https://www.example.net
126 | [text as the reference]: https://www.example.net
127 | ```
128 |
129 | [Example website](https://www.example.net)
130 |
131 | [Same website with a title](https://www.example.net "Example Website")
132 |
133 | [Link to a file in the project](./images/skunk-final.png)
134 |
135 | [Numbers can be used for reference links][1]
136 |
137 | Or simply [text as the reference].
138 |
139 | URLs will automatically become links: https://www.example.net or .
140 |
141 | ... and here are some reference links defined later in the document that won't be visible in the rendered HTML:
142 |
143 | [1]: https://www.example.net
144 | [text as the reference]: https://www.example.net
145 |
146 | ---
147 |
148 | # Images
149 |
150 | Please place all Markdown-related image files in the `markdown-blog/images` folder:
151 |
152 | ```
153 | Inline, with title:
154 | 
155 |
156 | Inline, reference, with title:
157 | ![eye image][eye_image_reference]
158 |
159 | [eye_image_reference]: images/eye.png "The Eye"
160 |
161 | Regular:
162 |
163 | 
164 |
165 | Regular, with title:
166 |
167 | 
168 | ```
169 |
170 | Inline, with title:
171 | 
172 |
173 | Inline, reference, with title:
174 | ![eye image][eye_image_reference]
175 |
176 | [eye_image_reference]: images/eye.png "The Eye"
177 |
178 | Regular:
179 |
180 | 
181 |
182 | Regular, with title:
183 |
184 | 
185 |
186 | ---
187 |
188 | # Ignoring formatting
189 |
190 | It is possible to ignore Markdown fomatting by placing a backslash before the Markdown character.
191 |
192 | ```
193 | For example, \*this text won't be italicized\*.
194 | ```
195 | For example, \*this text won't be italicized\*.
196 |
197 | ---
198 |
199 | # Code blocks
200 |
201 | ```
202 | Backticks can be used to highlight code inline, like this:
203 |
204 | "To print "Hello, F#!" in F#, you can use the `printfn` function".
205 |
206 | And triple backticks can be used to highlight code blocks:
207 |
208 | ```fsharp
209 | let greet name =
210 | printfn "Hello, %s!" name
211 |
212 | greet "F#"
213 |
214 | ```
215 | ```
216 |
217 | Backticks can be used to highlight code inline, like this:
218 |
219 | "To print "Hello, F#!" in F#, you can use the `printfn` function".
220 |
221 | And triple backticks can be used to highlight code blocks:
222 |
223 | ```fsharp
224 | let greet name =
225 | printfn "Hello, %s!" name
226 |
227 | greet "F#"
228 | ```
229 | Remember to specify the language name immediately after the three backticks (in this case fsharp) if you want syntax highlighting to work!
230 |
231 | ---
232 |
233 | # Tables
234 |
235 | ```
236 | Tables are super easy to create:
237 |
238 | | Left-Aligned | Center-Aligned | Right-Aligned |
239 | |:-------------|:--------------:|--------------:|
240 | | This | This | This |
241 | | column | column | column |
242 | | is | is | is |
243 | | left-aligned | center-aligned | right-aligned |
244 | ```
245 |
246 | Tables are super easy to create:
247 |
248 | | Left-Aligned | Center-Aligned | Right-Aligned |
249 | |:-------------|:--------------:|--------------:|
250 | | This | This | This |
251 | | column | column | column |
252 | | is | is | is |
253 | | left-aligned | center-aligned | right-aligned |
254 | ---
255 |
256 | # Blockquotes
257 |
258 | ```
259 | > This is a blockquote.
260 | >
261 | > This is another paragraph inside the same blockquote.
262 | >
263 | > > This is a nested blockquote.
264 | > >
265 | > > Another paragraph inside the nested blockquote.
266 | > >
267 | > > > This is a nested blockquote inside the second level.
268 | > > >
269 | > > > Another paragraph inside the third level blockquote.
270 | > >
271 | > > Back to the second level blockquote.
272 | >
273 | > Back to the original blockquote.
274 | ```
275 |
276 | > This is a blockquote.
277 | >
278 | > This is another paragraph inside the same blockquote.
279 | >
280 | > > This is a nested blockquote.
281 | > >
282 | > > Another paragraph inside the nested blockquote.
283 | > >
284 | > > > This is a nested blockquote inside the second level.
285 | > > >
286 | > > > Another paragraph inside the third level blockquote.
287 | > >
288 | > > Back to the second level blockquote.
289 | >
290 | > Back to the original blockquote.
291 |
292 |
293 | ---
294 |
295 | # Inline HTML
296 |
297 | ```
298 | Inline HTML is partially supported. Sometimes it can be useful, for example to strikethrough text:
299 |
300 | This text will be striked through.
301 |
302 | For some reason regular strikethrough is not supported. Proof: ~~This text is not striked through~~.
303 | ```
304 |
305 | Inline HTML is partially supported. Sometimes it can be useful, for example to strikethrough text:
306 |
307 | This text will be striked through.
308 |
309 | For some reason regular strikethrough is not supported. Proof: ~~This text is not striked through~~.
310 |
311 | ---
312 |
313 | # Horizontal rules
314 |
315 | ```
316 | Horizontal rule can be created using at least 3 dashes, asterisks, or underscores:
317 |
318 | ---
319 | ```
320 |
321 | Horizontal rule can be created using at least 3 dashes, asterisks, or underscores:
322 |
323 | ---
324 | That's all for now - you're ready to become a Markdown ninja with 🦨!
325 |
326 |
--------------------------------------------------------------------------------
/scripts/microlight.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview microlight - syntax highlightning library
3 | * @version 0.0.7
4 | *
5 | * @license MIT, see http://github.com/asvd/microlight
6 | * @copyright 2016 asvd
7 | *
8 | * Code structure aims at minimizing the compressed library size
9 | */
10 |
11 |
12 | (function (root, factory) {
13 | if (typeof define === 'function' && define.amd) {
14 | define(['exports'], factory);
15 | } else if (typeof exports !== 'undefined') {
16 | factory(exports);
17 | } else {
18 | factory((root.microlight = {}));
19 | }
20 | }(this, function (exports) {
21 | // for better compression
22 | var _window = window,
23 | _document = document,
24 | appendChild = 'appendChild',
25 | test = 'test',
26 | // style and color templates
27 | textShadow = ';text-shadow:',
28 | opacity = 'opacity:.',
29 | _0px_0px = ' 0px 0px ',
30 | _3px_0px_5 = '3px 0px 5',
31 | brace = ')',
32 |
33 | i,
34 | microlighted,
35 | el; // current microlighted element to run through
36 |
37 |
38 |
39 | var reset = function(nodes) {
40 | // nodes to highlight
41 | microlighted = nodes || _document.getElementsByClassName('microlight');
42 |
43 | for (i = 0; el = microlighted[i++];) {
44 | var text = el.textContent,
45 | pos = 0, // current position
46 | next1 = text[0], // next character
47 | chr = 1, // current character
48 | prev1, // previous character
49 | prev2, // the one before the previous
50 | token = // current token content
51 | el.innerHTML = '', // (and cleaning the node)
52 |
53 | // current token type:
54 | // 0: anything else (whitespaces / newlines)
55 | // 1: operator or brace
56 | // 2: closing braces (after which '/' is division not regex)
57 | // 3: (key)word
58 | // 4: regex
59 | // 5: string starting with "
60 | // 6: string starting with '
61 | // 7: xml comment
62 | // 8: multiline comment /* */
63 | // 9: single-line comment starting with two slashes //
64 | // 10: single-line comment starting with hash #
65 | tokenType = 0,
66 |
67 | // kept to determine between regex and division
68 | lastTokenType,
69 | // flag determining if token is multi-character
70 | multichar,
71 | node,
72 |
73 | // calculating the colors for the style templates
74 | colorArr = /(\d*\, \d*\, \d*)(, ([.\d]*))?/g.exec(
75 | _window.getComputedStyle(el).color
76 | ),
77 | pxColor = 'px rgba('+colorArr[1]+',',
78 | alpha = colorArr[3]||1;
79 |
80 | // running through characters and highlighting
81 | while (prev2 = prev1,
82 | // escaping if needed (with except for comments)
83 | // pervious character will not be therefore
84 | // recognized as a token finalize condition
85 | prev1 = tokenType < 7 && prev1 == '\\' ? 1 : chr
86 | ) {
87 | chr = next1;
88 | next1=text[++pos];
89 | multichar = token.length > 1;
90 |
91 | // checking if current token should be finalized
92 | if (!chr || // end of content
93 | // types 9-10 (single-line comments) end with a
94 | // newline
95 | (tokenType > 8 && chr == '\n') ||
96 | [ // finalize conditions for other token types
97 | // 0: whitespaces
98 | /\S/[test](chr), // merged together
99 | // 1: operators
100 | 1, // consist of a single character
101 | // 2: braces
102 | 1, // consist of a single character
103 | // 3: (key)word
104 | !/[$\w]/[test](chr),
105 | // 4: regex
106 | (prev1 == '/' || prev1 == '\n') && multichar,
107 | // 5: string with "
108 | prev1 == '"' && multichar,
109 | // 6: string with '
110 | prev1 == "'" && multichar,
111 | // 7: xml comment
112 | text[pos-4]+prev2+prev1 == '-->',
113 | // 8: multiline comment
114 | prev2+prev1 == '*/'
115 | ][tokenType]
116 | ) {
117 | // appending the token to the result
118 | if (token) {
119 | // remapping token type into style
120 | // (some types are highlighted similarly)
121 | el[appendChild](
122 | node = _document.createElement('span')
123 | ).setAttribute('style', [
124 | // 0: not formatted
125 | '',
126 | // 1: keywords
127 | textShadow + _0px_0px+9+pxColor + alpha * .7 + '),' +
128 | _0px_0px+2+pxColor + alpha * .4 + brace,
129 | // 2: punctuation
130 | opacity + 6 +
131 | textShadow + _0px_0px+7+pxColor + alpha / 4 + '),' +
132 | _0px_0px+3+pxColor + alpha / 4 + brace,
133 | // 3: strings and regexps
134 | opacity + 7 +
135 | textShadow + _3px_0px_5+pxColor + alpha / 5 + '),-' +
136 | _3px_0px_5+pxColor + alpha / 5 + brace,
137 | // 4: comments
138 | 'font-style:italic;'+
139 | opacity + 5 +
140 | textShadow + _3px_0px_5+pxColor + alpha / 4 + '),-' +
141 | _3px_0px_5+pxColor + alpha / 4 + brace
142 | ][
143 | // not formatted
144 | !tokenType ? 0 :
145 | // punctuation
146 | tokenType < 3 ? 2 :
147 | // comments
148 | tokenType > 6 ? 4 :
149 | // regex and strings
150 | tokenType > 3 ? 3 :
151 | // otherwise tokenType == 3, (key)word
152 | // (1 if regexp matches, 0 otherwise)
153 | + /^(a(bstract|lias|nd|rguments|rray|s(m|sert)?|uto)|b(ase|egin|ool(ean)?|reak|yte)|c(ase|atch|har|hecked|lass|lone|ompl|onst|ontinue)|de(bugger|cimal|clare|f(ault|er)?|init|l(egate|ete)?)|do|double|e(cho|ls?if|lse(if)?|nd|nsure|num|vent|x(cept|ec|p(licit|ort)|te(nds|nsion|rn)))|f(allthrough|alse|inal(ly)?|ixed|loat|or(each)?|riend|rom|unc(tion)?)|global|goto|guard|i(f|mp(lements|licit|ort)|n(it|clude(_once)?|line|out|stanceof|t(erface|ernal)?)?|s)|l(ambda|et|ock|ong)|m(icrolight|odule|utable)|NaN|n(amespace|ative|ext|ew|il|ot|ull)|o(bject|perator|r|ut|verride)|p(ackage|arams|rivate|rotected|rotocol|ublic)|r(aise|e(adonly|do|f|gister|peat|quire(_once)?|scue|strict|try|turn))|s(byte|ealed|elf|hort|igned|izeof|tatic|tring|truct|ubscript|uper|ynchronized|witch)|t(emplate|hen|his|hrows?|ransient|rue|ry|ype(alias|def|id|name|of))|u(n(checked|def(ined)?|ion|less|signed|til)|se|sing)|v(ar|irtual|oid|olatile)|w(char_t|hen|here|hile|ith)|xor|yield)$/[test](token)
154 | ]);
155 |
156 | node[appendChild](_document.createTextNode(token));
157 | }
158 |
159 | // saving the previous token type
160 | // (skipping whitespaces and comments)
161 | lastTokenType =
162 | (tokenType && tokenType < 7) ?
163 | tokenType : lastTokenType;
164 |
165 | // initializing a new token
166 | token = '';
167 |
168 | // determining the new token type (going up the
169 | // list until matching a token type start
170 | // condition)
171 | tokenType = 11;
172 | while (![
173 | 1, // 0: whitespace
174 | // 1: operator or braces
175 | /[\/{}[(\-+*=<>:;|\\.,?!&@~]/[test](chr),
176 | /[\])]/[test](chr), // 2: closing brace
177 | /[$\w]/[test](chr), // 3: (key)word
178 | chr == '/' && // 4: regex
179 | // previous token was an
180 | // opening brace or an
181 | // operator (otherwise
182 | // division, not a regex)
183 | (lastTokenType < 2) &&
184 | // workaround for xml
185 | // closing tags
186 | prev1 != '<',
187 | chr == '"', // 5: string with "
188 | chr == "'", // 6: string with '
189 | // 7: xml comment
190 | chr+next1+text[pos+1]+text[pos+2] == '