diff --git a/Makefile b/Makefile index 3fe8d26..8f11716 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,10 @@ serve: @echo "anna: serving site" @go build @./anna -s "site/" +wizard: + @echo "anna: running wizard" + @go build + @./anna -w tests: @echo "anna: running all tests" @go test ./... diff --git a/anna.json b/anna.json new file mode 100644 index 0000000..cb96b95 --- /dev/null +++ b/anna.json @@ -0,0 +1,5 @@ +{ + "siteDataPaths": { + "site": "site/" + } +} diff --git a/anna.yml b/anna.yml deleted file mode 100644 index 691a1f5..0000000 --- a/anna.yml +++ /dev/null @@ -1,2 +0,0 @@ -siteDataPaths: - - site: site/ diff --git a/cmd/anna/anna.go b/cmd/anna/anna.go index d45b82f..1346d34 100644 --- a/cmd/anna/anna.go +++ b/cmd/anna/anna.go @@ -1,6 +1,7 @@ package anna import ( + "encoding/json" "html/template" "log" "os" @@ -9,7 +10,6 @@ import ( "github.com/anna-ssg/anna/v2/pkg/engine" "github.com/anna-ssg/anna/v2/pkg/helpers" "github.com/anna-ssg/anna/v2/pkg/parser" - "gopkg.in/yaml.v3" ) type Cmd struct { @@ -25,7 +25,7 @@ type Cmd struct { } type AnnaConfig struct { - SiteDataPaths []map[string]string `yaml:"siteDataPaths"` + SiteDataPaths map[string]string `json:"siteDataPaths"` } func (cmd *Cmd) VanillaRenderManager() { @@ -33,21 +33,21 @@ func (cmd *Cmd) VanillaRenderManager() { // Check if the configuration file exists // If it does not, render only the site/ directory - _, err := os.Stat("anna.yml") + _, err := os.Stat("anna.json") if os.IsNotExist(err) { cmd.VanillaRender("site/") return } // Read and parse the configuration file - annaConfigFile, err := os.ReadFile("anna.yml") + annaConfigFile, err := os.ReadFile("anna.json") if err != nil { cmd.ErrorLogger.Fatal(err) } var annaConfig AnnaConfig - err = yaml.Unmarshal(annaConfigFile, &annaConfig) + err = json.Unmarshal(annaConfigFile, &annaConfig) if err != nil { cmd.ErrorLogger.Fatal(err) } @@ -56,13 +56,11 @@ func (cmd *Cmd) VanillaRenderManager() { if cmd.RenderSpecificSite == "" { siteRendered := false - for _, sites := range annaConfig.SiteDataPaths { - for _, path := range sites { - if !siteRendered { - siteRendered = true - } - cmd.VanillaRender(path) + for _, path := range annaConfig.SiteDataPaths { + if !siteRendered { + siteRendered = true } + cmd.VanillaRender(path) } // If no site has been rendered due to empty "anna.yml", render the default "site/" path @@ -72,12 +70,10 @@ func (cmd *Cmd) VanillaRenderManager() { } else { siteRendered := false - for _, sites := range annaConfig.SiteDataPaths { - for _, sitePath := range sites { - if strings.Compare(cmd.RenderSpecificSite, sitePath) == 0 { - cmd.VanillaRender(sitePath) - siteRendered = true - } + for _, sitePath := range annaConfig.SiteDataPaths { + if strings.Compare(cmd.RenderSpecificSite, sitePath) == 0 { + cmd.VanillaRender(sitePath) + siteRendered = true } } @@ -96,21 +92,21 @@ func (cmd *Cmd) ValidateHTMLManager() { // Check if the configuration file exists // If it does not, validate only the site/ directory - _, err := os.Stat("anna.yml") + _, err := os.Stat("anna.json") if os.IsNotExist(err) { cmd.VanillaRender("site/") return } // Read and parse the configuration file - annaConfigFile, err := os.ReadFile("anna.yml") + annaConfigFile, err := os.ReadFile("anna.json") if err != nil { cmd.ErrorLogger.Fatal(err) } var annaConfig AnnaConfig - err = yaml.Unmarshal(annaConfigFile, &annaConfig) + err = json.Unmarshal(annaConfigFile, &annaConfig) if err != nil { cmd.ErrorLogger.Fatal(err) } @@ -118,12 +114,10 @@ func (cmd *Cmd) ValidateHTMLManager() { // Validating sites validatedSites := false - for _, sites := range annaConfig.SiteDataPaths { - for _, sitePath := range sites { - cmd.ValidateHTMLContent(sitePath) - if !validatedSites { - validatedSites = true - } + for _, sitePath := range annaConfig.SiteDataPaths { + cmd.ValidateHTMLContent(sitePath) + if !validatedSites { + validatedSites = true } } @@ -139,21 +133,21 @@ func (cmd *Cmd) LiveReloadManager() { // Check if the configuration file exists // If it does not, serve only the site/ directory - _, err := os.Stat("anna.yml") + _, err := os.Stat("anna.json") if os.IsNotExist(err) { cmd.StartLiveReload("site/") return } // Read and parse the configuration file - annaConfigFile, err := os.ReadFile("anna.yml") + annaConfigFile, err := os.ReadFile("anna.json") if err != nil { cmd.ErrorLogger.Fatal(err) } var annaConfig AnnaConfig - err = yaml.Unmarshal(annaConfigFile, &annaConfig) + err = json.Unmarshal(annaConfigFile, &annaConfig) if err != nil { cmd.ErrorLogger.Fatal(err) } @@ -162,12 +156,10 @@ func (cmd *Cmd) LiveReloadManager() { if cmd.ServeSpecificSite == "" { cmd.StartLiveReload("site/") } else { - for _, sites := range annaConfig.SiteDataPaths { - for _, sitePath := range sites { - if strings.Compare(cmd.ServeSpecificSite, sitePath) == 0 { - cmd.StartLiveReload(sitePath) - return - } + for _, sitePath := range annaConfig.SiteDataPaths { + if strings.Compare(cmd.ServeSpecificSite, sitePath) == 0 { + cmd.StartLiveReload(sitePath) + return } } @@ -205,7 +197,7 @@ func (cmd *Cmd) VanillaRender(siteDirPath string) { helper.CreateRenderedDir(siteDirPath) - p.ParseConfig(siteDirPath + "layout/config.yml") + p.ParseConfig(siteDirPath + "layout/config.json") p.ParseRobots(siteDirPath+"layout/robots.txt", siteDirPath+"rendered/robots.txt") fileSystem := os.DirFS(siteDirPath + "content/") diff --git a/cmd/anna/livereload.go b/cmd/anna/livereload.go index 9d9eaf6..48d8c10 100644 --- a/cmd/anna/livereload.go +++ b/cmd/anna/livereload.go @@ -35,7 +35,7 @@ func newLiveReload(siteDataPath string) *liveReload { errorLogger: log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), fileTimes: make(map[string]time.Time), rootDirs: []string{siteDataPath}, - extensions: []string{".go", ".md", ".yml"}, + extensions: []string{".go", ".md", ".json"}, siteDataPath: siteDataPath, } return &lr diff --git a/cmd/anna/wizard.go b/cmd/anna/wizard.go index 97b50c6..dd9b462 100644 --- a/cmd/anna/wizard.go +++ b/cmd/anna/wizard.go @@ -4,43 +4,47 @@ import ( "context" "encoding/json" "errors" - "fmt" "log" "net/http" "os" "path/filepath" - "gopkg.in/yaml.v3" + "github.com/anna-ssg/anna/v2/pkg/parser" ) -type Config struct { - BaseURL string `yaml:"baseURL"` - SiteTitle string `yaml:"siteTitle"` - SiteScripts []string `yaml:"siteScripts"` - Author string `yaml:"author"` - ThemeURL string `yaml:"themeURL"` - Navbar []string `yaml:"navbar"` -} - type WizardServer struct { - server *http.Server + server *http.Server + serveMux *http.ServeMux + + // Common logger for all parser functions + InfoLogger *log.Logger + // Common logger for all parser functions + ErrorLogger *log.Logger } +var FormSubmittedCh = make(chan struct{}) + func NewWizardServer(addr string) *WizardServer { - return &WizardServer{ - server: &http.Server{ - Addr: addr, - }, + serveMuxLocal := http.NewServeMux() + + wizardServer := WizardServer{ + serveMux: serveMuxLocal, + server: &http.Server{Addr: addr, Handler: serveMuxLocal}, + InfoLogger: log.New(os.Stderr, "INFO\t", log.Ldate|log.Ltime), + ErrorLogger: log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), } + + return &wizardServer } func (ws *WizardServer) Start() { - http.HandleFunc("/submit", ws.handleSubmit) + ws.serveMux.HandleFunc("/submit", ws.handleSubmit) fs := http.FileServer(http.Dir("./site/static/wizard")) - http.Handle("/", fs) - fmt.Printf("Wizard is running at: http://localhost%s\n", ws.server.Addr) + ws.serveMux.Handle("/", fs) + ws.InfoLogger.Printf("Wizard is running at: http://localhost%s\n", ws.server.Addr) + if err := ws.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Fatalf("Could not start server: %v", err) + ws.ErrorLogger.Fatalf("Could not start server: %v", err) } } @@ -51,44 +55,47 @@ func (ws *WizardServer) Stop() error { func (ws *WizardServer) handleSubmit(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + ws.ErrorLogger.Println("Method not allowed") return } - var config Config + + var config parser.LayoutConfig err := json.NewDecoder(r.Body).Decode(&config) + + err = ws.writeConfigToFile(config) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - err = writeConfigToFile(config) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + ws.ErrorLogger.Println(err) return } FormSubmittedCh <- struct{}{} } -func writeConfigToFile(config Config) error { - configFilePath := "./site/layout/config.yml" +func (ws *WizardServer) writeConfigToFile(config parser.LayoutConfig) error { + configFilePath := "./site/layout/config.json" if err := os.MkdirAll(filepath.Dir(configFilePath), 0755); err != nil { return err } - file, err := os.Create(configFilePath) + marshaledJsonConfig, err := json.Marshal(config) + if err != nil { + ws.ErrorLogger.Fatal(err) + } + + configFile, err := os.Create(configFilePath) if err != nil { return err } defer func() { - err = file.Close() + err = configFile.Close() if err != nil { - log.Fatal(err) + ws.ErrorLogger.Fatal(err) } }() + os.WriteFile(configFilePath, marshaledJsonConfig, 0666) - // Encode the config into YAML format and write it to the file. - if err := yaml.NewEncoder(file).Encode(&config); err != nil { + if err != nil { return err } + return nil } - -var FormSubmittedCh = make(chan struct{}) diff --git a/main.go b/main.go index 02153e6..ca595c1 100644 --- a/main.go +++ b/main.go @@ -31,7 +31,7 @@ func main() { RenderSpecificSite: renderSpecificSite, ServeSpecificSite: serve, ErrorLogger: log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile), - InfoLogger: log.New(os.Stderr, "LOG\t", log.Ldate|log.Ltime|log.Lshortfile), + InfoLogger: log.New(os.Stderr, "LOG\t", log.Ldate|log.Ltime), } if serve != "" { @@ -61,9 +61,9 @@ func main() { if err := server.Stop(); err != nil { annaCmd.InfoLogger.Println(err) } - annaCmd.VanillaRenderManager() annaCmd.LiveReloadManager() } + annaCmd.VanillaRenderManager() }, } diff --git a/pkg/engine/anna_engine.go b/pkg/engine/anna_engine.go index c5ceb8d..7de7b00 100644 --- a/pkg/engine/anna_engine.go +++ b/pkg/engine/anna_engine.go @@ -81,6 +81,9 @@ func (e *Engine) RenderTags(fileOutPath string, templ *template.Template) { e.DeepDataMerge.Tags = make(map[template.URL]parser.TemplateData) for tag := range e.DeepDataMerge.TagsMap { + slices.SortFunc(e.DeepDataMerge.TagsMap[tag], func(a, b parser.TemplateData) int { + return cmp.Compare(b.Date, a.Date) + }) tagString := string(tag) tagString, _ = strings.CutPrefix(tagString, "tags/") tagString, _ = strings.CutSuffix(tagString, ".html") @@ -139,7 +142,7 @@ func (e *Engine) RenderCollections(fileOutPath string, templ *template.Template) CollectionNames: collectionNames, } - // Rendering the page displaying all tags + // Rendering the page displaying all collections err := templ.ExecuteTemplate(&collectionsBuffer, "all-collections", collectionTemplateData) if err != nil { e.ErrorLogger.Fatal(err) @@ -157,6 +160,10 @@ func (e *Engine) RenderCollections(fileOutPath string, templ *template.Template) e.DeepDataMerge.Collections = make(map[template.URL]parser.TemplateData) for collection := range e.DeepDataMerge.CollectionsMap { + slices.SortFunc(e.DeepDataMerge.CollectionsMap[collection], func(a, b parser.TemplateData) int { + return cmp.Compare(b.Date, a.Date) + }) + collectionString := string(collection) collectionString, _ = strings.CutPrefix(collectionString, "collections/") collectionString, _ = strings.CutSuffix(collectionString, ".html") @@ -297,7 +304,6 @@ func (e *Engine) GenerateFeed() { buffer.WriteString(" " + time.Now().Format(time.RFC1123Z) + "\n") buffer.WriteString(" \n") - // slice var posts []parser.TemplateData for _, templateData := range e.DeepDataMerge.Templates { if !templateData.Frontmatter.Draft { @@ -306,8 +312,8 @@ func (e *Engine) GenerateFeed() { } // sort by publication date - sort.Slice(posts, func(i, j int) bool { - return posts[i].Date > posts[j].Date // assuming Date is Unix timestamp + slices.SortFunc(posts, func(a, b parser.TemplateData) int { + return cmp.Compare(b.Date, a.Date) // assuming Date is Unix timestamp }) // Iterate over sorted posts diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 49bd3c8..41749bc 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -2,6 +2,7 @@ package parser import ( "bytes" + "encoding/json" "html/template" "io/fs" "log" @@ -24,15 +25,15 @@ import ( ) type LayoutConfig struct { - Navbar []map[string]string `yaml:"navbar"` - BaseURL string `yaml:"baseURL"` - SiteTitle string `yaml:"siteTitle"` - SiteScripts []string `yaml:"siteScripts"` - Author string `yaml:"author"` - Copyright string `yaml:"copyright"` - ThemeURL string `yaml:"themeURL"` - Socials []map[string]string `yaml:"socials"` - CollectionLayouts []map[string]string `yaml:"collectionLayouts"` + Navbar []map[string]string `json:"navbar"` + BaseURL string `json:"baseURL"` + SiteTitle string `json:"siteTitle"` + SiteScripts []string `json:"siteScripts"` + Author string `json:"author"` + Copyright string `json:"copyright"` + ThemeURL string `json:"themeURL"` + Socials map[string]string `json:"socials"` + CollectionLayouts map[string]string `json:"collectionLayouts"` } type Frontmatter struct { @@ -275,8 +276,9 @@ func (p *Parser) ParseConfig(inFilePath string) { p.ErrorLogger.Fatal(err) } - err = yaml.Unmarshal(configFile, &p.LayoutConfig) + err = json.Unmarshal(configFile, &p.LayoutConfig) if err != nil { + p.ErrorLogger.Println("Error at: ", inFilePath) p.ErrorLogger.Fatal(err) } @@ -380,9 +382,7 @@ func (p *Parser) collectionsParser(page TemplateData) { } func (p *Parser) parseCollectionLayoutEntries() { - for _, pair := range p.LayoutConfig.CollectionLayouts { - for collectionURL, layoutName := range pair { - p.CollectionsSubPageLayouts[template.URL(collectionURL)] = layoutName - } + for collectionURL, layoutName := range p.LayoutConfig.CollectionLayouts { + p.CollectionsSubPageLayouts[template.URL(collectionURL)] = layoutName } } diff --git a/pkg/parser/parser_test.go b/pkg/parser/parser_test.go index 9383cc0..d3e8ef2 100644 --- a/pkg/parser/parser_test.go +++ b/pkg/parser/parser_test.go @@ -124,7 +124,7 @@ func TestParseMarkdownContent(t *testing.T) { } func TestParseConfig(t *testing.T) { - t.Run("unmarshal `config.yml` to LayoutConfig", func(t *testing.T) { + t.Run("unmarshal `config.json` to LayoutConfig", func(t *testing.T) { gotParser := parser.Parser{ Templates: make(map[template.URL]parser.TemplateData), TagsMap: make(map[template.URL][]parser.TemplateData), @@ -144,7 +144,7 @@ func TestParseConfig(t *testing.T) { Author: "Anna", } - gotParser.ParseConfig(TestDirPath + "layout/config.yml") + gotParser.ParseConfig(TestDirPath + "layout/config.json") if !reflect.DeepEqual(gotParser.LayoutConfig, wantLayout) { t.Errorf("got \n%v want \n%v", gotParser.LayoutConfig, wantLayout) diff --git a/site/layout/config.json b/site/layout/config.json new file mode 100644 index 0000000..bd283a7 --- /dev/null +++ b/site/layout/config.json @@ -0,0 +1,40 @@ +{ + "navbar": [ + { + "Index": "index.html" + }, + { + "Quick Start": "quick-start.html" + }, + { + "Docs": "docs.html" + }, + { + "Dev Guide": "developer-guide.html" + }, + { + "Tags": "tags.html" + }, + { + "Collections": "collections.html" + }, + { + "Posts": "collections/posts.html" + }, + { + "Anna Blog": "posts/building-anna/index.html" + } + ], + "baseURL": "https://anna-docs.netlify.app", + "siteTitle": "anna-docs", + "siteScripts": null, + "author": "anna", + "themeURL": "/static/style.css", + "copyright": "This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.", + "socials": { + "Github": "https://github.com/anna-ssg/anna" + }, + "collectionLayouts": { + "collections/posts.html": "all-posts" + } +} diff --git a/site/layout/config.yml b/site/layout/config.yml deleted file mode 100644 index 8ab6eb0..0000000 --- a/site/layout/config.yml +++ /dev/null @@ -1,19 +0,0 @@ -navbar: - - Index: index.html - - Quick Start: quick-start.html - - Docs: docs.html - - Dev Guide: developer-guide.html - - Tags: tags.html - - Collections: collections.html - - Posts: collections/posts.html - - Anna Blog: posts/building-anna/index.html -baseURL: https://anna-docs.netlify.app -siteTitle: "anna-docs" -siteScripts: -author: anna -themeURL: "/static/style.css" -copyright: "This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International." -socials: - - Github: https://github.com/anna-ssg/anna -collectionLayouts: - - collections/posts.html: all-posts diff --git a/site/layout/tags.html b/site/layout/tags.html index f094c0c..922d577 100644 --- a/site/layout/tags.html +++ b/site/layout/tags.html @@ -16,9 +16,9 @@ -
+ {{template "footer" .}} diff --git a/site/static/wizard/index.html b/site/static/wizard/index.html index b7f67a4..9c022cf 100644 --- a/site/static/wizard/index.html +++ b/site/static/wizard/index.html @@ -48,11 +48,9 @@

Enter a domain name

Pick what you'd like on the navbar

@@ -90,4 +88,4 @@

Cooking your Anna site

- \ No newline at end of file + diff --git a/site/static/wizard/script.js b/site/static/wizard/script.js index d40c89a..d11d919 100644 --- a/site/static/wizard/script.js +++ b/site/static/wizard/script.js @@ -1,268 +1,282 @@ -const slides = document.querySelectorAll('.content'); +const slides = document.querySelectorAll(".content"); let currentSlide = 0; // Declare global variables let author, siteTitle, baseURL, themeURL; function showSlide(index) { - slides.forEach((slide, i) => { - slide.style.display = i === index ? 'block' : 'none'; - }); - updateProgress(); + slides.forEach((slide, i) => { + slide.style.display = i === index ? "block" : "none"; + }); + updateProgress(); } function updateProgress() { - const progressContainer = document.querySelector(".progress-container"); - const oldWidth = window.getComputedStyle(progressContainer).getPropertyValue('--new-width'); - const newWidth = ((currentSlide + 1) / slides.length) * 100 + "%"; - progressContainer.style.setProperty('--old-width', oldWidth); - progressContainer.style.setProperty('--new-width', newWidth); - progressContainer.style.animation = 'progressAnimation 1s ease-in-out both'; + const progressContainer = document.querySelector(".progress-container"); + const oldWidth = window + .getComputedStyle(progressContainer) + .getPropertyValue("--new-width"); + const newWidth = ((currentSlide + 1) / slides.length) * 100 + "%"; + progressContainer.style.setProperty("--old-width", oldWidth); + progressContainer.style.setProperty("--new-width", newWidth); + progressContainer.style.animation = "progressAnimation 1s ease-in-out both"; } function nextSlide() { - currentSlide = Math.min(currentSlide + 1, slides.length - 1); - showSlide(currentSlide); + currentSlide = Math.min(currentSlide + 1, slides.length - 1); + showSlide(currentSlide); } function prevSlide() { - currentSlide = Math.max(currentSlide - 1, 0); - showSlide(currentSlide); + currentSlide = Math.max(currentSlide - 1, 0); + showSlide(currentSlide); } function checkFormValidity() { - author = document.getElementById("author").value; - siteTitle = document.getElementById("siteTitle").value; - baseURL = document.getElementById("baseURL").value; - themeURL = document.getElementById("themeURL").value; + author = document.getElementById("author").value; + siteTitle = document.getElementById("siteTitle").value; + baseURL = document.getElementById("baseURL").value; + themeURL = document.getElementById("themeURL").value; - var nameRegex = /^[a-zA-Z0-9\s]+$/; - var urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([a-z.]{2,6})(\/[^\/\s]+)*$/; + var nameRegex = /^[a-zA-Z0-9\s]+$/; + var urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([a-z.]{2,6})(\/[^\/\s]+)*$/; - var authorButton = document.getElementById("authorButton"); - var siteTitleButton = document.getElementById("siteTitleButton"); - var baseURLButton = document.getElementById("baseURLButton"); + var authorButton = document.getElementById("authorButton"); + var siteTitleButton = document.getElementById("siteTitleButton"); + var baseURLButton = document.getElementById("baseURLButton"); - authorButton.disabled = !(author && author.match(nameRegex)); - siteTitleButton.disabled = !(siteTitle && siteTitle.match(nameRegex)); - baseURLButton.disabled = !(baseURL && baseURL.match(urlRegex)); + authorButton.disabled = !(author && author.match(nameRegex)); + siteTitleButton.disabled = !(siteTitle && siteTitle.match(nameRegex)); + baseURLButton.disabled = !(baseURL && baseURL.match(urlRegex)); - // Add or remove 'valid' class based on validity - document.getElementById("author").classList.toggle("valid", author && author.match(nameRegex)); - document.getElementById("siteTitle").classList.toggle("valid", siteTitle && siteTitle.match(nameRegex)); - document.getElementById("baseURL").classList.toggle("valid", baseURL && baseURL.match(urlRegex)); + // Add or remove 'valid' class based on validity + document + .getElementById("author") + .classList.toggle("valid", author && author.match(nameRegex)); + document + .getElementById("siteTitle") + .classList.toggle("valid", siteTitle && siteTitle.match(nameRegex)); + document + .getElementById("baseURL") + .classList.toggle("valid", baseURL && baseURL.match(urlRegex)); } - function submitForm() { - var checkboxes = document.querySelectorAll('.nav-checkboxes input[type="checkbox"]'); - var navbarOptions = Array.from(checkboxes) - .filter(checkbox => checkbox.checked) - .map(checkbox => checkbox.value); + var checkboxes = document.querySelectorAll( + '.nav-checkboxes input[type="checkbox"]', + ); - var formData = JSON.stringify({ - "author": author, - "siteTitle": siteTitle, - "baseURL": baseURL, - "themeURL": themeURL, - "navbar": navbarOptions + var navbarOptions = Array.from(checkboxes) + .filter((checkbox) => checkbox.checked) + .map((checkbox) => { + navbarElementsMap = {}; + navbarElementsMap[checkbox.className] = checkbox.value; + return navbarElementsMap; }); - showSlide(slides.length - 1); - fetch('/submit', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: formData - }); + var formData = JSON.stringify({ + author: author, + siteTitle: siteTitle, + baseURL: baseURL, + themeURL: themeURL, + navbar: navbarOptions, + }); - tsParticles.load({ - id: "tsparticles", - options: { - "fullScreen": { - "zIndex": 1 + console.log(formData); + + showSlide(slides.length - 1); + fetch("/submit", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: formData, + }); + + tsParticles.load({ + id: "tsparticles", + options: { + fullScreen: { + zIndex: 1, + }, + emitters: [ + { + position: { + x: 0, + y: 30, + }, + rate: { + quantity: 5, + delay: 0.15, + }, + particles: { + move: { + direction: "top-right", + outModes: { + top: "none", + left: "none", + default: "destroy", + }, }, - "emitters": [ - { - "position": { - "x": 0, - "y": 30 - }, - "rate": { - "quantity": 5, - "delay": 0.15 - }, - "particles": { - "move": { - "direction": "top-right", - "outModes": { - "top": "none", - "left": "none", - "default": "destroy" - } - } - } - }, - { - "position": { - "x": 100, - "y": 30 - }, - "rate": { - "quantity": 5, - "delay": 0.15 - }, - "particles": { - "move": { - "direction": "top-left", - "outModes": { - "top": "none", - "right": "none", - "default": "destroy" - } - } - } - } - ], - "particles": { - "color": { - "value": [ - "#ffffff", - "#FF0000" - ] - }, - "move": { - "decay": 0.05, - "direction": "top", - "enable": true, - "gravity": { - "enable": true - }, - "outModes": { - "top": "none", - "default": "destroy" - }, - "speed": { - "min": 10, - "max": 50 - } - }, - "number": { - "value": 0 - }, - "opacity": { - "value": 1 - }, - "rotate": { - "value": { - "min": 0, - "max": 360 - }, - "direction": "random", - "animation": { - "enable": true, - "speed": 30 - } - }, - "tilt": { - "direction": "random", - "enable": true, - "value": { - "min": 0, - "max": 360 - }, - "animation": { - "enable": true, - "speed": 30 - } - }, - "size": { - "value": { - "min": 0, - "max": 2 - }, - "animation": { - "enable": true, - "startValue": "min", - "count": 1, - "speed": 16, - "sync": true - } - }, - "roll": { - "darken": { - "enable": true, - "value": 25 - }, - "enable": true, - "speed": { - "min": 5, - "max": 15 - } - }, - "wobble": { - "distance": 30, - "enable": true, - "speed": { - "min": -7, - "max": 7 - } + }, + }, + { + position: { + x: 100, + y: 30, + }, + rate: { + quantity: 5, + delay: 0.15, + }, + particles: { + move: { + direction: "top-left", + outModes: { + top: "none", + right: "none", + default: "destroy", + }, + }, + }, + }, + ], + particles: { + color: { + value: ["#ffffff", "#FF0000"], + }, + move: { + decay: 0.05, + direction: "top", + enable: true, + gravity: { + enable: true, + }, + outModes: { + top: "none", + default: "destroy", + }, + speed: { + min: 10, + max: 50, + }, + }, + number: { + value: 0, + }, + opacity: { + value: 1, + }, + rotate: { + value: { + min: 0, + max: 360, + }, + direction: "random", + animation: { + enable: true, + speed: 30, + }, + }, + tilt: { + direction: "random", + enable: true, + value: { + min: 0, + max: 360, + }, + animation: { + enable: true, + speed: 30, + }, + }, + size: { + value: { + min: 0, + max: 2, + }, + animation: { + enable: true, + startValue: "min", + count: 1, + speed: 16, + sync: true, + }, + }, + roll: { + darken: { + enable: true, + value: 25, + }, + enable: true, + speed: { + min: 5, + max: 15, + }, + }, + wobble: { + distance: 30, + enable: true, + speed: { + min: -7, + max: 7, + }, + }, + shape: { + type: "emoji", + options: { + emoji: { + particles: { + size: { + value: 8, }, - "shape": { - "type": "emoji", - "options": { - "emoji": { - "particles": { - "size": { - "value": 8 - } - }, - "value": [ - "🍚" - ] - } - } - } - } - } - }); - + }, + value: ["🍚"], + }, + }, + }, + }, + }, + }); - tsParticles.load("confetti", confettiSettings); - currentSlide = currentSlide + 1; - updateProgress() - setTimeout(() => { - window.location.href = 'http://localhost:8000'; - }, 5000); + tsParticles.load("confetti", confettiSettings); + currentSlide = currentSlide + 1; + updateProgress(); + setTimeout(() => { + window.location.href = "http://localhost:8000"; + }, 2000); } showSlide(0); // Add event listeners to call checkFormValidity when input fields change document.getElementById("author").addEventListener("input", checkFormValidity); -document.getElementById("siteTitle").addEventListener("input", checkFormValidity); +document + .getElementById("siteTitle") + .addEventListener("input", checkFormValidity); document.getElementById("baseURL").addEventListener("input", checkFormValidity); -document.getElementById("themeURL").addEventListener("input", checkFormValidity); +document + .getElementById("themeURL") + .addEventListener("input", checkFormValidity); // Confetti animation const confettiSettings = { - particles: { - number: { - value: 10 - }, - size: { - value: 2 - }, - shape: { - type: "circle" - }, - move: { - speed: 6 - }, - color: { - value: "#00FFFF" - }, - opacity: { - value: 0.8 - } - } + particles: { + number: { + value: 10, + }, + size: { + value: 2, + }, + shape: { + type: "circle", + }, + move: { + speed: 6, + }, + color: { + value: "#00FFFF", + }, + opacity: { + value: 0.8, + }, + }, }; diff --git a/test/parser/layout/config.json b/test/parser/layout/config.json new file mode 100644 index 0000000..08b5e28 --- /dev/null +++ b/test/parser/layout/config.json @@ -0,0 +1,20 @@ +{ + "navbar": [ + { + "Index": "index.html" + }, + { + "Docs": "docs.html" + }, + { + "Tags": "tags.html" + }, + { + "Posts": "posts.html" + } + ], + "baseURL": "example.org", + "siteTitle": "ssg", + "siteScripts": null, + "author": "Anna" +} diff --git a/test/parser/layout/config.yml b/test/parser/layout/config.yml deleted file mode 100644 index f964205..0000000 --- a/test/parser/layout/config.yml +++ /dev/null @@ -1,9 +0,0 @@ -navbar: - - Index: index.html - - Docs: docs.html - - Tags: tags.html - - Posts: posts.html -baseURL: example.org -siteTitle: ssg -siteScripts: -author: Anna