func (p *Page) permalink() (*url.URL, error) { baseURL := string(p.Site.BaseURL) dir := strings.TrimSpace(helpers.MakePath(filepath.ToSlash(strings.ToLower(p.Source.Dir())))) pSlug := strings.TrimSpace(helpers.URLize(p.Slug)) pURL := strings.TrimSpace(helpers.URLize(p.URL)) var permalink string var err error if len(pURL) > 0 { return helpers.MakePermalink(baseURL, pURL), nil } if override, ok := p.Site.Permalinks[p.Section()]; ok { permalink, err = override.Expand(p) if err != nil { return nil, err } // fmt.Printf("have a section override for %q in section %s → %s\n", p.Title, p.Section, permalink) } else { if len(pSlug) > 0 { permalink = helpers.URLPrep(viper.GetBool("UglyURLs"), path.Join(dir, p.Slug+"."+p.Extension())) } else { _, t := filepath.Split(p.Source.LogicalName()) permalink = helpers.URLPrep(viper.GetBool("UglyURLs"), path.Join(dir, helpers.ReplaceExtension(strings.TrimSpace(t), p.Extension()))) } } return helpers.MakePermalink(baseURL, permalink), nil }
func (s *SiteInfo) createNodeMenuEntryURL(in string) string { if !strings.HasPrefix(in, "/") { return in } // make it match the nodes menuEntryURL := in menuEntryURL = helpers.SanitizeURLKeepTrailingSlash(helpers.URLize(menuEntryURL)) if !s.canonifyURLs { menuEntryURL = helpers.AddContextRoot(string(s.BaseURL), menuEntryURL) } return menuEntryURL }
// if the page has a slug, return the slug, else return the title func pageToPermalinkSlugElseTitle(p *Page, a string) (string, error) { if p.Slug != "" { // Don't start or end with a - if strings.HasPrefix(p.Slug, "-") { p.Slug = p.Slug[1:len(p.Slug)] } if strings.HasSuffix(p.Slug, "-") { p.Slug = p.Slug[0 : len(p.Slug)-1] } return helpers.URLize(p.Slug), nil } return pageToPermalinkTitle(p, a) }
func (s *Site) RenderHomePage() error { n := s.newHomeNode() layouts := s.appendThemeTemplates([]string{"index.html", "_default/list.html"}) if err := s.renderAndWritePage("homepage", helpers.FilePathSeparator, n, layouts...); err != nil { return err } if n.paginator != nil { paginatePath := viper.GetString("paginatePath") // write alias for page 1 s.WriteDestAlias(helpers.PaginateAliasPath("", 1), s.permalink("/")) pagers := n.paginator.Pagers() for i, pager := range pagers { if i == 0 { // already created continue } homePagerNode := s.newHomeNode() homePagerNode.paginator = pager if pager.TotalPages() > 0 { first, _ := pager.page(0) homePagerNode.Date = first.Date homePagerNode.Lastmod = first.Lastmod } pageNumber := i + 1 htmlBase := fmt.Sprintf("/%s/%d", paginatePath, pageNumber) if err := s.renderAndWritePage(fmt.Sprintf("homepage"), filepath.FromSlash(htmlBase), homePagerNode, layouts...); err != nil { return err } } } if !viper.GetBool("DisableRSS") { // XML Feed n.URL = s.permalinkStr(viper.GetString("RSSUri")) n.Title = "" high := 50 if len(s.Pages) < high { high = len(s.Pages) } n.Data["Pages"] = s.Pages[:high] if len(s.Pages) > 0 { n.Date = s.Pages[0].Date n.Lastmod = s.Pages[0].Lastmod } rssLayouts := []string{"rss.xml", "_default/rss.xml", "_internal/_default/rss.xml"} if err := s.renderAndWriteXML("homepage rss", viper.GetString("RSSUri"), n, s.appendThemeTemplates(rssLayouts)...); err != nil { return err } } // TODO(bep) reusing the Home Node smells trouble n.URL = helpers.URLize("404.html") n.IsHome = false n.Title = "404 Page not found" n.Permalink = s.permalink("404.html") n.scratch = newScratch() nfLayouts := []string{"404.html"} if nfErr := s.renderAndWritePage("404 page", "404.html", n, s.appendThemeTemplates(nfLayouts)...); nfErr != nil { return nfErr } return nil }
// pageToPermalinkFilename returns the URL-safe form of the filename func pageToPermalinkFilename(p *Page, _ string) (string, error) { //var extension = p.Source.Ext //var name = p.Source.Path()[0 : len(p.Source.Path())-len(extension)] return helpers.URLize(p.Source.BaseFileName()), nil }
// pageToPermalinkTitle returns the URL-safe form of the title func pageToPermalinkTitle(p *Page, _ string) (string, error) { // Page contains Node which has Title // (also contains URLPath which has Slug, sometimes) return helpers.URLize(p.Title), nil }
func (p *Page) update(f interface{}) error { if f == nil { return fmt.Errorf("no metadata found") } m := f.(map[string]interface{}) var err error for k, v := range m { loki := strings.ToLower(k) switch loki { case "title": p.Title = cast.ToString(v) case "linktitle": p.linkTitle = cast.ToString(v) case "description": p.Description = cast.ToString(v) case "slug": p.Slug = helpers.URLize(cast.ToString(v)) case "url": if url := cast.ToString(v); strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { return fmt.Errorf("Only relative URLs are supported, %v provided", url) } p.URL = helpers.URLize(cast.ToString(v)) case "type": p.contentType = cast.ToString(v) case "extension", "ext": p.extension = cast.ToString(v) case "keywords": p.Keywords = cast.ToStringSlice(v) case "date": p.Date, err = cast.ToTimeE(v) if err != nil { jww.ERROR.Printf("Failed to parse date '%v' in page %s", v, p.File.Path()) } case "publishdate", "pubdate": p.PublishDate, err = cast.ToTimeE(v) if err != nil { jww.ERROR.Printf("Failed to parse publishdate '%v' in page %s", v, p.File.Path()) } case "draft": p.Draft = cast.ToBool(v) case "layout": p.layout = cast.ToString(v) case "markup": p.Markup = cast.ToString(v) case "weight": p.Weight = cast.ToInt(v) case "aliases": p.Aliases = cast.ToStringSlice(v) for _, alias := range p.Aliases { if strings.HasPrefix(alias, "http://") || strings.HasPrefix(alias, "https://") { return fmt.Errorf("Only relative aliases are supported, %v provided", alias) } } case "status": p.Status = cast.ToString(v) case "sitemap": p.Sitemap = parseSitemap(cast.ToStringMap(v)) default: // If not one of the explicit values, store in Params switch vv := v.(type) { case bool: p.Params[loki] = vv case string: p.Params[loki] = vv case int64, int32, int16, int8, int: p.Params[loki] = vv case float64, float32: p.Params[loki] = vv case time.Time: p.Params[loki] = vv default: // handle array of strings as well switch vvv := vv.(type) { case []interface{}: var a = make([]string, len(vvv)) for i, u := range vvv { a[i] = cast.ToString(u) } p.Params[loki] = a default: p.Params[loki] = vv } } } } return nil }
func (s *Site) RenderHomePage() error { n := s.newHomeNode() layouts := s.appendThemeTemplates([]string{"index.html", "_default/list.html", "_default/single.html"}) if err := s.renderAndWritePage("homepage", helpers.FilePathSeparator, n, layouts...); err != nil { return err } if n.paginator != nil { paginatePath := viper.GetString("paginatePath") // write alias for page 1 s.WriteDestAlias(filepath.FromSlash(fmt.Sprintf("/%s/%d", paginatePath, 1)), s.permalink("/")) pagers := n.paginator.Pagers() for i, pager := range pagers { if i == 0 { // already created continue } homePagerNode := s.newHomeNode() homePagerNode.paginator = pager if pager.TotalPages() > 0 { homePagerNode.Date = pager.Pages()[0].Date } pageNumber := i + 1 htmlBase := fmt.Sprintf("/%s/%d", paginatePath, pageNumber) if err := s.renderAndWritePage(fmt.Sprintf("homepage_%d", pageNumber), filepath.FromSlash(htmlBase), homePagerNode, layouts...); err != nil { return err } } } if !viper.GetBool("DisableRSS") { // XML Feed n.Url = s.permalinkStr("index.xml") n.Title = "" high := 50 if len(s.Pages) < high { high = len(s.Pages) } n.Data["Pages"] = s.Pages[:high] if len(s.Pages) > 0 { n.Date = s.Pages[0].Date } rssLayouts := []string{"rss.xml", "_default/rss.xml", "_internal/_default/rss.xml"} if err := s.renderAndWriteXML("homepage rss", "index.xml", n, s.appendThemeTemplates(rssLayouts)...); err != nil { return err } } n.Url = helpers.URLize("404.html") n.Title = "404 Page not found" n.Permalink = s.permalink("404.html") nfLayouts := []string{"404.html"} if nfErr := s.renderAndWritePage("404 page", "404.html", n, s.appendThemeTemplates(nfLayouts)...); nfErr != nil { return nfErr } return nil }