node to page: Remove Node

And misc. TODO-fixes

Updates #2297
This commit is contained in:
Bjørn Erik Pedersen
2016-11-13 14:27:10 +01:00
parent 9347084d61
commit c8d3124dde
22 changed files with 538 additions and 567 deletions

View File

@@ -86,27 +86,35 @@ type Page struct {
// This collection will be nil for regular pages.
Pages Pages
Params map[string]interface{}
Content template.HTML
Summary template.HTML
Aliases []string
Status string
Images []Image
Videos []Video
TableOfContents template.HTML
Truncated bool
Draft bool
PublishDate time.Time
ExpiryDate time.Time
Markup string
translations Pages
extension string
contentType string
renderable bool
Params map[string]interface{}
Content template.HTML
Summary template.HTML
Aliases []string
Status string
Images []Image
Videos []Video
TableOfContents template.HTML
Truncated bool
Draft bool
PublishDate time.Time
ExpiryDate time.Time
Markup string
translations Pages
extension string
contentType string
renderable bool
Layout string
layoutsCalculated []string
linkTitle string
frontmatter []byte
linkTitle string
frontmatter []byte
// rawContent isn't "raw" as in the same as in the content file.
// Hugo cares about memory consumption, so we make changes to it to do
@@ -132,9 +140,6 @@ type Page struct {
Source
Position `json:"-"`
// TODO(bep) np pointer, or remove
Node
GitInfo *gitmap.GitInfo
// This was added as part of getting the Nodes (taxonomies etc.) to work as
@@ -151,6 +156,32 @@ type Page struct {
// TODO(bep) np Site added to page, keep?
site *Site
// Pulled over from Node. TODO(bep) np reorg and group (embed)
Site *SiteInfo `json:"-"`
Title string
Description string
Keywords []string
Data map[string]interface{}
Date time.Time
Lastmod time.Time
Sitemap Sitemap
RSSLink template.HTML
URLPath
paginator *Pager
paginatorInit sync.Once
scratch *Scratch
language *helpers.Language
languageInit sync.Once
lang string
}
// IsNode returns whether this is an item of one of the list types in Hugo,
@@ -207,6 +238,10 @@ type Position struct {
type Pages []*Page
func (p Pages) String() string {
return fmt.Sprintf("Pages(%d)", len(p))
}
func (ps Pages) FindPagePosByFilePath(inPath string) int {
for i, x := range ps {
if x.Source.Path() == inPath {
@@ -300,14 +335,6 @@ func (p *Page) UniqueID() string {
return p.Source.UniqueID()
}
func (p *Page) Ref(ref string) (string, error) {
return p.Node.Site.Ref(ref, p)
}
func (p *Page) RelRef(ref string) (string, error) {
return p.Node.Site.RelRef(ref, p)
}
// for logging
func (p *Page) lineNumRawContentStart() int {
return bytes.Count(p.frontmatter, []byte("\n")) + 1
@@ -450,10 +477,10 @@ func (p *Page) renderContent(content []byte) []byte {
var fileFn helpers.FileResolverFunc
if p.getRenderingConfig().SourceRelativeLinksEval {
fn = func(ref string) (string, error) {
return p.Node.Site.SourceRelativeLink(ref, p)
return p.Site.SourceRelativeLink(ref, p)
}
fileFn = func(ref string) (string, error) {
return p.Node.Site.SourceRelativeLinkFile(ref, p)
return p.Site.SourceRelativeLinkFile(ref, p)
}
}
return helpers.RenderBytes(&helpers.RenderingContext{
@@ -483,10 +510,10 @@ func (p *Page) getRenderingConfig() *helpers.Blackfriday {
func newPage(filename string) *Page {
page := Page{
Kind: kindFromFilename(filename),
contentType: "",
Source: Source{File: *source.NewFile(filename)},
Node: Node{Keywords: []string{}, Sitemap: Sitemap{Priority: -1}},
Kind: kindFromFilename(filename),
contentType: "",
Source: Source{File: *source.NewFile(filename)},
Keywords: []string{}, Sitemap: Sitemap{Priority: -1},
Params: make(map[string]interface{}),
translations: make(Pages, 0),
sections: sectionsFromFilename(filename),
@@ -778,7 +805,7 @@ func (p *Page) IsExpired() bool {
func (p *Page) Permalink() (string, error) {
// TODO(bep) np permalink
if p.IsNode() {
return p.Node.Permalink(), nil
return p.Site.permalink(p.URL()), nil
}
link, err := p.permalink()
if err != nil {
@@ -788,6 +815,10 @@ func (p *Page) Permalink() (string, error) {
}
func (p *Page) URL() string {
// TODO(bep np URL
if p.IsNode() {
return p.addLangPathPrefix(p.URLPath.URL)
}
if p.URLPath.URL != "" {
// This is the url set in front matter
return p.URLPath.URL
@@ -1013,29 +1044,48 @@ func (p *Page) getParam(key string, stringToLower bool) interface{} {
return nil
}
func (p *Page) HasMenuCurrent(menu string, me *MenuEntry) bool {
// TODO(bep) np menu
if p.IsNode() {
return p.Node.HasMenuCurrent(menu, me)
}
menus := p.Menus()
func (p *Page) HasMenuCurrent(menuID string, me *MenuEntry) bool {
sectionPagesMenu := helpers.Config().GetString("SectionPagesMenu")
// page is labeled as "shadow-member" of the menu with the same identifier as the section
if sectionPagesMenu != "" && p.Section() != "" && sectionPagesMenu == menu && p.Section() == me.Identifier {
if sectionPagesMenu != "" && p.Section() != "" && sectionPagesMenu == menuID && p.Section() == me.Identifier {
return true
}
if m, ok := menus[menu]; ok {
if me.HasChildren() {
for _, child := range me.Children {
if child.IsEqual(m) {
return true
}
if p.HasMenuCurrent(menu, child) {
return true
}
if !me.HasChildren() {
return false
}
menus := p.Menus()
if m, ok := menus[menuID]; ok {
for _, child := range me.Children {
if child.IsEqual(m) {
return true
}
if p.HasMenuCurrent(menuID, child) {
return true
}
}
}
if p.IsPage() {
return false
}
// The following logic is kept from back when Hugo had both Page and Node types.
// TODO(bep) consolidate / clean
nme := MenuEntry{Name: p.Title, URL: p.URL()}
for _, child := range me.Children {
if nme.IsSameResource(child) {
return true
}
if p.HasMenuCurrent(menuID, child) {
return true
}
}
@@ -1043,17 +1093,59 @@ func (p *Page) HasMenuCurrent(menu string, me *MenuEntry) bool {
}
func (p *Page) IsMenuCurrent(menu string, inme *MenuEntry) bool {
// TODO(bep) np menu
if p.IsNode() {
return p.Node.IsMenuCurrent(menu, inme)
}
func (p *Page) IsMenuCurrent(menuID string, inme *MenuEntry) bool {
menus := p.Menus()
if me, ok := menus[menu]; ok {
return me.IsEqual(inme)
if me, ok := menus[menuID]; ok {
if me.IsEqual(inme) {
return true
}
}
if p.IsPage() {
return false
}
// The following logic is kept from back when Hugo had both Page and Node types.
// TODO(bep) consolidate / clean
me := MenuEntry{Name: p.Title, URL: p.Site.createNodeMenuEntryURL(p.URL())}
if !me.IsSameResource(inme) {
return false
}
// this resource may be included in several menus
// search for it to make sure that it is in the menu with the given menuId
if menu, ok := (*p.Site.Menus)[menuID]; ok {
for _, menuEntry := range *menu {
if menuEntry.IsSameResource(inme) {
return true
}
descendantFound := p.isSameAsDescendantMenu(inme, menuEntry)
if descendantFound {
return descendantFound
}
}
}
return false
}
func (p *Page) isSameAsDescendantMenu(inme *MenuEntry, parent *MenuEntry) bool {
if parent.HasChildren() {
for _, child := range parent.Children {
if child.IsSameResource(inme) {
return true
}
descendantFound := p.isSameAsDescendantMenu(inme, child)
if descendantFound {
return descendantFound
}
}
}
return false
}
@@ -1253,7 +1345,6 @@ func (p *Page) FullFilePath() string {
func (p *Page) TargetPath() (outfile string) {
// TODO(bep) np
switch p.Kind {
case KindHome:
return p.addLangFilepathPrefix(helpers.FilePathSeparator)
@@ -1416,7 +1507,7 @@ func (p *Page) updatePageDates() {
// the paginators etc., we do it manually here.
// TODO(bep) np do better
func (p *Page) copy() *Page {
c := &Page{Kind: p.Kind, Node: Node{Site: p.Site}}
c := &Page{Kind: p.Kind, Site: p.Site}
c.Title = p.Title
c.Data = p.Data
c.Date = p.Date
@@ -1426,3 +1517,217 @@ func (p *Page) copy() *Page {
c.URLPath = p.URLPath
return c
}
// TODO(bep) np these are pulled over from Node. Needs regrouping / embed
func (p *Page) Now() time.Time {
return time.Now()
}
func (p *Page) Hugo() *HugoInfo {
return hugoInfo
}
func (p *Page) RSSlink() template.HTML {
// TODO(bep) we cannot have two of these
helpers.Deprecated(".Page", "RSSlink", "RSSLink")
return p.RSSLink
}
func (p *Page) Ref(ref string) (string, error) {
return p.Site.Ref(ref, nil)
}
func (p *Page) RelRef(ref string) (string, error) {
return p.Site.RelRef(ref, nil)
}
func (p *Page) String() string {
return fmt.Sprintf("Page(%q)", p.Title)
}
type URLPath struct {
URL string
Permalink string
Slug string
Section string
}
// Scratch returns the writable context associated with this Page.
func (p *Page) Scratch() *Scratch {
if p.scratch == nil {
p.scratch = newScratch()
}
return p.scratch
}
func (p *Page) Language() *helpers.Language {
p.initLanguage()
return p.language
}
func (p *Page) Lang() string {
// When set, Language can be different from lang in the case where there is a
// content file (doc.sv.md) with language indicator, but there is no language
// config for that language. Then the language will fall back on the site default.
if p.Language() != nil {
return p.Language().Lang
}
return p.lang
}
func (p *Page) isTranslation(candidate *Page) bool {
if p == candidate || p.Kind != candidate.Kind {
return false
}
if p.lang != candidate.lang || p.language != p.language {
return false
}
if p.Kind == KindPage || p.Kind == kindUnknown {
panic("Node type not currently supported for this op")
}
// At this point, we know that this is a traditional Node (home page, section, taxonomy)
// It represents the same node, but different language, if the sections is the same.
if len(p.sections) != len(candidate.sections) {
return false
}
for i := 0; i < len(p.sections); i++ {
if p.sections[i] != candidate.sections[i] {
return false
}
}
return true
}
func (p *Page) shouldAddLanguagePrefix() bool {
if !p.Site.IsMultiLingual() {
return false
}
if p.Lang() == "" {
return false
}
if !p.Site.defaultContentLanguageInSubdir && p.Lang() == p.Site.multilingual.DefaultLang.Lang {
return false
}
return true
}
func (p *Page) initLanguage() {
p.languageInit.Do(func() {
if p.language != nil {
return
}
pageLang := p.lang
ml := p.Site.multilingual
if ml == nil {
panic("Multilanguage not set")
}
if pageLang == "" {
p.language = ml.DefaultLang
return
}
language := ml.Language(pageLang)
if language == nil {
// It can be a file named stefano.chiodino.md.
jww.WARN.Printf("Page language (if it is that) not found in multilang setup: %s.", pageLang)
language = ml.DefaultLang
}
p.language = language
})
}
func (p *Page) LanguagePrefix() string {
return p.Site.LanguagePrefix
}
func (p *Page) addLangPathPrefix(outfile string) string {
return p.addLangPathPrefixIfFlagSet(outfile, p.shouldAddLanguagePrefix())
}
func (p *Page) addLangPathPrefixIfFlagSet(outfile string, should bool) string {
if helpers.IsAbsURL(outfile) {
return outfile
}
if !should {
return outfile
}
hadSlashSuffix := strings.HasSuffix(outfile, "/")
outfile = "/" + path.Join(p.Lang(), outfile)
if hadSlashSuffix {
outfile += "/"
}
return outfile
}
func (p *Page) addLangFilepathPrefix(outfile string) string {
if outfile == "" {
outfile = helpers.FilePathSeparator
}
if !p.shouldAddLanguagePrefix() {
return outfile
}
return helpers.FilePathSeparator + filepath.Join(p.Lang(), outfile)
}
func sectionsFromFilename(filename string) []string {
dir, _ := filepath.Split(filename)
dir = strings.TrimSuffix(dir, helpers.FilePathSeparator)
sections := strings.Split(dir, helpers.FilePathSeparator)
return sections
}
func kindFromFilename(filename string) string {
if !strings.Contains(filename, "_index") {
return KindPage
}
if strings.HasPrefix(filename, "_index") {
return KindHome
}
// We don't know enough yet to determine the type.
return kindUnknown
}
func (p *Page) setNodeTypeVars(s *Site) {
if p.Kind == kindUnknown {
// This is either a taxonomy list, taxonomy term or a section
nodeType := s.nodeTypeFromSections(p.sections)
if nodeType == kindUnknown {
panic(fmt.Sprintf("Unable to determine node type from %q", p.sections))
}
p.Kind = nodeType
}
// TODO(bep) np node URL
// Set Node URL
switch p.Kind {
case KindHome:
p.URLPath.URL = ""
case KindSection:
p.URLPath.URL = p.sections[0]
case KindTaxonomy:
p.URLPath.URL = path.Join(p.sections...)
case KindTaxonomyTerm:
p.URLPath.URL = path.Join(p.sections...)
}
p.site = s
}