Skip to content

Commit

Permalink
Merge pull request #20 from paganotoni/task-using-gostar
Browse files Browse the repository at this point in the history
task: moving the HTML to be generated using gostar
  • Loading branch information
paganotoni authored May 23, 2024
2 parents 0438e67 + a20d3e3 commit 14a389b
Show file tree
Hide file tree
Showing 24 changed files with 712 additions and 665 deletions.
9 changes: 8 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
module github.com/paganotoni/doco

go 1.22
go 1.22.1

require (
github.com/delaneyj/gostar v0.7.3
github.com/fsnotify/fsnotify v1.7.0
github.com/yuin/goldmark v1.5.4
github.com/yuin/goldmark-meta v1.1.0
Expand All @@ -12,6 +13,12 @@ require (
)

require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/igrmk/treemap/v2 v2.0.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/sys v0.16.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
27 changes: 24 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/delaneyj/gostar v0.7.3 h1:+7vEN7T9Y6HESGMHwlXzsTC/apgVwQy1bR4NQ7IKYfo=
github.com/delaneyj/gostar v0.7.3/go.mod h1:mlxRWAVbntRR2VWlpXAzt7y9HY+bQtEm/lsyFnGLx/w=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/igrmk/treemap/v2 v2.0.1 h1:Jhy4z3yhATvYZMWCmxsnHO5NnNZBdueSzvxh6353l+0=
github.com/igrmk/treemap/v2 v2.0.1/go.mod h1:PkTPvx+8OHS8/41jnnyVY+oVsfkaOUZGcr+sfonosd4=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
go.abhg.dev/goldmark/anchor v0.1.1 h1:NUH3hAzhfeymRqZKOkSoFReZlEAmfXBZlbXEzpD2Qgc=
go.abhg.dev/goldmark/anchor v0.1.1/go.mod h1:zYKiaHXTdugwVJRZqInVdmNGQRM3ZRJ6AGBC7xP7its=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
File renamed without changes.
165 changes: 165 additions & 0 deletions internal/assets/doco.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
document.addEventListener("DOMContentLoaded", () => {
// Add highligthing to the code blocks
hljs.highlightAll();

// Adding the mobile menu toggle
let toggles = document.querySelectorAll(".toggle-mobile-nav");
toggles.forEach((toggle) => {
toggle.addEventListener("click", () => {
document.getElementById("mobile-menu").classList.toggle("hidden");
document.querySelector("body").classList.toggle("overflow-hidden");
});
});

// Replacing the $YEAR element with the current year
let copy = document.getElementById("copy");
copy.innerHTML = copy.innerHTML.replace("$YEAR", new Date().getFullYear());

// TODO: Keyboard up and down
// TODO: Keyboard enter to navigate to article
document.querySelectorAll(".search-button").forEach((element) => {
element.addEventListener("click", showSearch);
});

document
.getElementById("search-overlay")
.addEventListener("click", hideSearch);
document.getElementById("close-search").addEventListener("click", hideSearch);
document
.getElementById("search-input")
.addEventListener("keyup", (e) => search(e.target.value));

// Loading the index when the page it loaded so the search just uses it.
fetch("/index.json")
.then((response) => response.json())
.then((data) => {
window.searchIndex = new Fuse(data, {
threshold: 0.8,
tokenize: false,
includeMatches: true,
maxPatternLength: 32,
minMatchCharLength: 1,
location: 80_000,
keys: ["content", "title", "section_name"],
});
})
.catch((error) => console.error("Error:", error));

let imageContainer = document.querySelector("#zoomed-image-overlay");
imageContainer.addEventListener("click", () => {
imageContainer.classList.add("hidden");
});

let zoomables = document.querySelectorAll("#htmlcontainer img");
zoomables.forEach((zoomable) => {
zoomable.classList.add("cursor-zoom-in");
zoomable.addEventListener("click", () => {
imageContainer.classList.remove("hidden");
imageContainer.querySelector("img").src = zoomable.src;
});
});

document.addEventListener("keydown", (e) => {
if (e.keyCode === 27) {
hideSearch();
// hide image container
imageContainer.classList.add("hidden");
}

if (e.keyCode >= 65 && e.keyCode <= 90) {
let char = (e.metaKey ? "⌘-" : "") + String.fromCharCode(e.keyCode);
if (char == "⌘-K") {
showSearch();
}
}
});
});

function showSearch() {
document.getElementById("search-palette").classList.remove("hidden");
document.getElementById("search-input").focus();
}

function hideSearch() {
document.getElementById("search-palette").classList.add("hidden");
}

let tm = null;
function search(searchQuery) {
if (searchQuery.length == 0) {
document.getElementById("search-no-results").classList.add("hidden");
document.getElementById("search-results").classList.add("hidden");
document.getElementById("search-quick-actions").classList.remove("hidden");

return;
}

if (tm != null) {
clearTimeout(tm);
}

tm = setTimeout(() => {
var result = searchIndex.search(searchQuery);

// hide the quick actions
document.getElementById("search-quick-actions").classList.add("hidden");

if (result.length == 0) {
document.getElementById("search-no-results").classList.remove("hidden");
document.getElementById("search-results").classList.add("hidden");
return;
}

document.getElementById("search-no-results").classList.add("hidden");
document.getElementById("search-results").classList.remove("hidden");

populateResults(result);
}, 400);
}

function populateResults(result) {
let template = document.getElementById("search-result-template").innerHTML;
document.getElementById("search-results").innerHTML = "";

result.forEach((value, index) => {
if (value.item.title == null) {
return;
}

var output = render(template, {
key: index,
title: value.item.title,
link: value.item.link,
});

document.getElementById("search-results").innerHTML += output;
});
}

function render(templateString, data) {
var conditionalMatches, conditionalPattern, copy;
conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
//since loop below depends on re.lastIndex, we use a copy to capture any manipulations whilst inside the loop
copy = templateString;
while (
(conditionalMatches = conditionalPattern.exec(templateString)) !== null
) {
if (data[conditionalMatches[1]]) {
//valid key, remove conditionals, leave contents.
copy = copy.replace(conditionalMatches[0], conditionalMatches[2]);
} else {
//not valid, remove entire section
copy = copy.replace(conditionalMatches[0], "");
}
}

templateString = copy;
//now any conditionals removed we can do simple substitution
var key, find, re;
for (key in data) {
find = "\\$\\{\\s*" + key + "\\s*\\}";
re = new RegExp(find, "g");
templateString = templateString.replace(re, data[key]);
}
return templateString;
}
26 changes: 14 additions & 12 deletions internal/config.go → internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package internal
package config

import (
"io"
"os"
"path/filepath"

"github.com/paganotoni/doco/internal/markdown"
)

const (
Expand All @@ -13,32 +15,32 @@ const (
)

// config of the general elements of the site.
type config struct {
type Site struct {
Name string
Favicon string
Description string
Keywords string
Github string // Github link to display, empty means no link

Logo link
Announcement link
ExternalLinks []link
QuickLinks []link
Logo Link
Announcement Link
ExternalLinks []Link
QuickLinks []Link

Copy string
}

type link struct {
type Link struct {
Text string
Link string
Icon string
ImageSrc string
}

// readConfig parses the _meta.md file and returns the config
// Read parses the _meta.md file and returns the config
// for the site.
// TODO: change this to receive the file access (fs package?) instead of the folder.
func readConfig(folder string) (c config, err error) {
func Read(folder string) (c Site, err error) {
file, err := os.Open(filepath.Join(folder, metafile))
if err != nil {
return c, err
Expand All @@ -51,7 +53,7 @@ func readConfig(folder string) (c config, err error) {
return c, err
}

meta, err := metadataFrom(content)
meta, err := markdown.ReadMetadata(content)
if err != nil {
return c, err
}
Expand Down Expand Up @@ -88,7 +90,7 @@ func readConfig(folder string) (c config, err error) {
if ok {
for _, v := range qlinks {
l := v.(map[any]any)
c.QuickLinks = append(c.QuickLinks, link{
c.QuickLinks = append(c.QuickLinks, Link{
Text: def(l["text"], ""),
Link: def(l["link"], ""),
Icon: def(l["icon"], ""),
Expand All @@ -100,7 +102,7 @@ func readConfig(folder string) (c config, err error) {
if ok {
for _, v := range elinks {
l := v.(map[any]any)
c.ExternalLinks = append(c.ExternalLinks, link{
c.ExternalLinks = append(c.ExternalLinks, Link{
Text: def(l["text"], ""),
Link: def(l["link"], ""),
})
Expand Down
6 changes: 3 additions & 3 deletions internal/config_test.go → internal/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package internal
package config

import (
_ "embed"
Expand Down Expand Up @@ -41,7 +41,7 @@ func TestReadConfig(t *testing.T) {
t.Fatal(err)
}

_, err = readConfig(tmpdir)
_, err = Read(tmpdir)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -70,7 +70,7 @@ func TestReadConfig(t *testing.T) {
t.Fatal(err)
}

_, err = readConfig(tmpdir)
_, err = Read(tmpdir)
if err != nil {
t.Fatal(err)
}
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion internal/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

// copyDir copies a directory recursively from src to dst
// src and dst must be absolute paths
// src and dst must be absolute paths. This is useful to copy the
// assets recursively.
func copyDir(src string, dst string) error {
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
Expand Down
Loading

0 comments on commit 14a389b

Please sign in to comment.