Repository: gohugoio/hugo (language: go)

Issue:
Deprecate and then rename/remove Page.URL
I cannot think of one valid use case for it, and I see it used in the wild all the time when `RelPermalik` or `Permalink` is the correct choice.

`URL` returns the front matter value for regular pages, if set, else it return the `RelPermalink`.



Discussion / hints:
I am not in favor of removing Page.URL. 

For example 
`if eq .URL "/some-url/"` provides an easy way to add an active class to page links that live outside Hugo's menu configuration (for various reasons) Also this is handy in cases where it's difficult to do a `.Permalink` or `.RelPermalink `check, like in Nested Sections list pages.

But if you really think these are not valid use cases. Go ahead and remove it. I'll look into what can be done to replace its functionality... like I always do...
`.URL` and `.Permalink` are indeed much the same, although the first returns a string value and the second a `template.HTML` value. So even though they return the same data, they behave differently:

~~~plain
{{ if in .URL "hugo" }}
...
{{ end }}

{{ if in (.Permalink | string) "hugo" }}
...
{{ end }}
~~~

I agree there's some redundancy. And on one hand I think Hugo template code might become easier when there's no two variables that return the same data. But on the other hand the required conversion to string of `.Permalink` might be more odd to newcomers than two variables are.

That latter might also make explaining how people can update from `.URL` to `.Permalink` somewhat confusing. Assuming we use a terminal message for this like Hugo did with previous depreciations. Would a terminal message like this be something people with little knowledge of Go/Hugo understand?

~~~
WARN: .URL has been deprecated. Replace .URL with 
.Permalink, but when comparing .Permalink against a 
string, first translate .Permalink to a string value
with the 'string' function.
~~~

Even though I wrote this without using programming lingo (like 'casting' or 'type incompatibility'), I still doubt if this is clear enough. (Or should we assume people read the release notes, where this can be explained more fully?)

So to summarise: I don't know what wisdom is for this issue. 😆 
> Or should we assume people read the release notes, where this can be explained more fully?

If the recent release of Hugo 0.32 is any indication I would say that people don't bother with the release notes. The forum is full of posts regarding `index.md`

A Warn like @Jos512 proposes is the way to go. 

And possibly an example of the `.Permalink `translation to a string value, in the Release notes.

You cannot assume that every user of Hugo has used every one of its functions or that he/she knows what to do in advance. Not all of us are from a Dev background.
> {{ if in (.Permalink | string) "hugo" }}

I just want to say that the above approach would not work with `.FirstSection` list pages because obviously the `string` is also present in the Nested Sections of that section.

For example let's say that I have a section called `/women/` and a nested section called `/women/backpacks` and I want to have each custom menu entry of these links have a selected class when the user is in their corresponding URL. With the above both menu entries would have the selected class under both URLs.

But thanks to Hugo 0.45.1 and `.FirstSection` here is how I finally managed to do this.

```
{{ $currentURL := .Permalink }}
{{ with .FirstSection }}
<a {{ if eq .Permalink $currentURL }}class="selected"{{ end }} href="...">...</a>
{{ end }}
```
And then for other list pages within that Section I do the following simple check:
```
{{ if eq .Permalink $currentURL }}class="selected" {{ end }}
```

So at this point, I am fine with `.URL` being deprecated from Hugo, since I can have the functionality I need with other simple means.
Actually if `.Page.URL` is deprecated and removed it will break several older themes that are currently in the Hugo Themes showcase.

And that is not a bad thing. 

Since it will force theme authors to update their themes or if they don't we can always clean up the showcase from unmaintained themes.

So +1 for this issue.

@bep 

Please consider removing `.Page.URL` in the next Hugo release. I think that it's about time.

There are out-of-date themes and perhaps tutorials floating around and some users keep on encountering the `.Page.URL` deprecation notice and having questions about it, as shown [here](https://discourse.gohugo.io/t/url-deprecated/36559/8).

It's better to break some old projects rather than wasting time explaining a deprecation message that was added in 2017, five years later, in 2022. 

@onedrawingperday hmm... I was sure I removed that in the previous release. O well, thanks for the heads up.

EDIT: OK, I see I bump the WARNING level to ERROR ... Yes, I will remove.

Fix patch:
diff --git a/hugolib/page__common.go b/hugolib/page__common.go
index ccef79a3fe4..bf11ae7d671 100644
--- a/hugolib/page__common.go
+++ b/hugolib/page__common.go
@@ -78,7 +78,6 @@ type pageCommon struct {
 	page.RefProvider
 	page.ShortcodeInfoProvider
 	page.SitesProvider
-	page.DeprecatedWarningPageMethods
 	page.TranslationsProvider
 	page.TreeProvider
 	resource.LanguageProvider
diff --git a/hugolib/page__new.go b/hugolib/page__new.go
index 17bdb30ff6f..5efebe4f599 100644
--- a/hugolib/page__new.go
+++ b/hugolib/page__new.go
@@ -20,7 +20,6 @@ import (
 	"github.com/gohugoio/hugo/common/hugo"
 
 	"github.com/gohugoio/hugo/common/maps"
-	"github.com/gohugoio/hugo/source"
 
 	"github.com/gohugoio/hugo/output"
 
@@ -65,15 +64,6 @@ func newPageBase(metaProvider *pageMeta) (*pageState, error) {
 
 	siteAdapter := pageSiteAdapter{s: s, p: ps}
 
-	deprecatedWarningPage := struct {
-		source.FileWithoutOverlap
-		page.DeprecatedWarningPageMethods1
-	}{
-		FileWithoutOverlap:            metaProvider.File(),
-		DeprecatedWarningPageMethods1: &pageDeprecatedWarning{p: ps},
-	}
-
-	ps.DeprecatedWarningPageMethods = page.NewDeprecatedWarningPage(deprecatedWarningPage)
 	ps.pageMenus = &pageMenus{p: ps}
 	ps.PageMenusProvider = ps.pageMenus
 	ps.GetPageProvider = siteAdapter
diff --git a/resources/page/page.go b/resources/page/page.go
index f23069a68de..d1790806ead 100644
--- a/resources/page/page.go
+++ b/resources/page/page.go
@@ -24,7 +24,6 @@ import (
 	"github.com/gohugoio/hugo/config"
 	"github.com/gohugoio/hugo/tpl"
 
-	"github.com/gohugoio/hugo/common/hugo"
 	"github.com/gohugoio/hugo/common/maps"
 	"github.com/gohugoio/hugo/compare"
 	"github.com/gohugoio/hugo/hugofs/files"
@@ -379,18 +378,7 @@ type TreeProvider interface {
 // DeprecatedWarningPageMethods lists deprecated Page methods that will trigger
 // a WARNING if invoked.
 // This was added in Hugo 0.55.
-type DeprecatedWarningPageMethods interface {
-	source.FileWithoutOverlap
-	DeprecatedWarningPageMethods1
-}
-
-type DeprecatedWarningPageMethods1 interface {
-	IsDraft() bool
-	Hugo() hugo.Info
-	LanguagePrefix() string
-	GetParam(key string) interface{}
-	RSSLink() template.URL
-	URL() string
+type DeprecatedWarningPageMethods interface { // This was emptied in Hugo 0.93.0.
 }
 
 // Move here to trigger ERROR instead of WARNING.
diff --git a/resources/page/page_generate/generate_page_wrappers.go b/resources/page/page_generate/generate_page_wrappers.go
index ae05ad5c2ee..9d790cc014e 100644
--- a/resources/page/page_generate/generate_page_wrappers.go
+++ b/resources/page/page_generate/generate_page_wrappers.go
@@ -47,7 +47,6 @@ const header = `// Copyright 2019 The Hugo Authors. All rights reserved.
 `
 
 var (
-	fileInterfaceDeprecated = reflect.TypeOf((*source.FileWithoutOverlap)(nil)).Elem()
 	pageInterfaceDeprecated = reflect.TypeOf((*page.DeprecatedWarningPageMethods)(nil)).Elem()
 	pageInterface           = reflect.TypeOf((*page.Page)(nil)).Elem()
 
@@ -155,15 +154,9 @@ func generateDeprecatedWrappers(c *codegen.Inspector) error {
 	}
 
 	deprecated := func(name string, tp reflect.Type) string {
-		var alternative string
-		if tp == fileInterfaceDeprecated {
-			alternative = "Use .File." + name
-		} else {
-			var found bool
-			alternative, found = reasons[name]
-			if !found {
-				panic(fmt.Sprintf("no deprecated reason found for %q", name))
-			}
+		alternative, found := reasons[name]
+		if !found {
+			panic(fmt.Sprintf("no deprecated reason found for %q", name))
 		}
 
 		return fmt.Sprintf("helpers.Deprecated(%q, %q, true)", "Page."+name, alternative)
@@ -171,7 +164,7 @@ func generateDeprecatedWrappers(c *codegen.Inspector) error {
 
 	var buff bytes.Buffer
 
-	methods := c.MethodsFromTypes([]reflect.Type{fileInterfaceDeprecated, pageInterfaceDeprecated}, nil)
+	methods := c.MethodsFromTypes([]reflect.Type{pageInterfaceDeprecated}, nil)
 
 	for _, m := range methods {
 		fmt.Fprint(&buff, m.Declaration("*pageDeprecated"))
@@ -181,7 +174,8 @@ func generateDeprecatedWrappers(c *codegen.Inspector) error {
 
 	}
 
-	pkgImports := append(methods.Imports(), "github.com/gohugoio/hugo/helpers")
+	pkgImports := methods.Imports()
+	// pkgImports := append(methods.Imports(), "github.com/gohugoio/hugo/helpers")
 
 	fmt.Fprintf(f, `%s
 
diff --git a/resources/page/page_marshaljson.autogen.go b/resources/page/page_marshaljson.autogen.go
index 6cfa411e21a..7b44d4a7201 100644
--- a/resources/page/page_marshaljson.autogen.go
+++ b/resources/page/page_marshaljson.autogen.go
@@ -17,9 +17,6 @@ package page
 
 import (
 	"encoding/json"
-	"html/template"
-	"time"
-
 	"github.com/bep/gitmap"
 	"github.com/gohugoio/hugo/common/maps"
 	"github.com/gohugoio/hugo/config"
@@ -29,6 +26,8 @@ import (
 	"github.com/gohugoio/hugo/media"
 	"github.com/gohugoio/hugo/navigation"
 	"github.com/gohugoio/hugo/source"
+	"html/template"
+	"time"
 )
 
 func MarshalPageToJSON(p Page) ([]byte, error) {
@@ -69,7 +68,8 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
 	linkTitle := p.LinkTitle()
 	isNode := p.IsNode()
 	isPage := p.IsPage()
-	path := p.Pathc()
+	path := p.Path()
+	pathc := p.Pathc()
 	slug := p.Slug()
 	lang := p.Lang()
 	isSection := p.IsSection()
@@ -127,6 +127,7 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
 		IsNode                   bool
 		IsPage                   bool
 		Path                     string
+		Pathc                    string
 		Slug                     string
 		Lang                     string
 		IsSection                bool
@@ -183,6 +184,7 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
 		IsNode:                   isNode,
 		IsPage:                   isPage,
 		Path:                     path,
+		Pathc:                    pathc,
 		Slug:                     slug,
 		Lang:                     lang,
 		IsSection:                isSection,
diff --git a/resources/page/page_wrappers.autogen.go b/resources/page/page_wrappers.autogen.go
index 2bdd5112180..55dff47d5ab 100644
--- a/resources/page/page_wrappers.autogen.go
+++ b/resources/page/page_wrappers.autogen.go
@@ -15,13 +15,6 @@
 
 package page
 
-import (
-	"github.com/gohugoio/hugo/common/hugo"
-	"github.com/gohugoio/hugo/helpers"
-	"github.com/gohugoio/hugo/hugofs"
-	"html/template"
-)
-
 // NewDeprecatedWarningPage adds deprecation warnings to the given implementation.
 func NewDeprecatedWarningPage(p DeprecatedWarningPageMethods) DeprecatedWarningPageMethods {
 	return &pageDeprecated{p: p}
@@ -30,68 +23,3 @@ func NewDeprecatedWarningPage(p DeprecatedWarningPageMethods) DeprecatedWarningP
 type pageDeprecated struct {
 	p DeprecatedWarningPageMethods
 }
-
-func (p *pageDeprecated) Filename() string {
-	helpers.Deprecated("Page.Filename", "Use .File.Filename", true)
-	return p.p.Filename()
-}
-func (p *pageDeprecated) Dir() string {
-	helpers.Deprecated("Page.Dir", "Use .File.Dir", true)
-	return p.p.Dir()
-}
-func (p *pageDeprecated) IsDraft() bool {
-	helpers.Deprecated("Page.IsDraft", "Use .Draft.", true)
-	return p.p.IsDraft()
-}
-func (p *pageDeprecated) Extension() string {
-	helpers.Deprecated("Page.Extension", "Use .File.Extension", true)
-	return p.p.Extension()
-}
-func (p *pageDeprecated) Hugo() hugo.Info {
-	helpers.Deprecated("Page.Hugo", "Use the global hugo function.", true)
-	return p.p.Hugo()
-}
-func (p *pageDeprecated) Ext() string {
-	helpers.Deprecated("Page.Ext", "Use .File.Ext", true)
-	return p.p.Ext()
-}
-func (p *pageDeprecated) LanguagePrefix() string {
-	helpers.Deprecated("Page.LanguagePrefix", "Use .Site.LanguagePrefix.", true)
-	return p.p.LanguagePrefix()
-}
-func (p *pageDeprecated) GetParam(arg0 string) interface{} {
-	helpers.Deprecated("Page.GetParam", "Use .Param or .Params.myParam.", true)
-	return p.p.GetParam(arg0)
-}
-func (p *pageDeprecated) LogicalName() string {
-	helpers.Deprecated("Page.LogicalName", "Use .File.LogicalName", true)
-	return p.p.LogicalName()
-}
-func (p *pageDeprecated) BaseFileName() string {
-	helpers.Deprecated("Page.BaseFileName", "Use .File.BaseFileName", true)
-	return p.p.BaseFileName()
-}
-func (p *pageDeprecated) RSSLink() template.URL {
-	helpers.Deprecated("Page.RSSLink", "Use the Output Format's link, e.g. something like:\n    {{ with .OutputFormats.Get \"RSS\" }}{{ .RelPermalink }}{{ end }}", true)
-	return p.p.RSSLink()
-}
-func (p *pageDeprecated) TranslationBaseName() string {
-	helpers.Deprecated("Page.TranslationBaseName", "Use .File.TranslationBaseName", true)
-	return p.p.TranslationBaseName()
-}
-func (p *pageDeprecated) URL() string {
-	helpers.Deprecated("Page.URL", "Use .Permalink or .RelPermalink. If what you want is the front matter URL value, use .Params.url", true)
-	return p.p.URL()
-}
-func (p *pageDeprecated) ContentBaseName() string {
-	helpers.Deprecated("Page.ContentBaseName", "Use .File.ContentBaseName", true)
-	return p.p.ContentBaseName()
-}
-func (p *pageDeprecated) UniqueID() string {
-	helpers.Deprecated("Page.UniqueID", "Use .File.UniqueID", true)
-	return p.p.UniqueID()
-}
-func (p *pageDeprecated) FileInfo() hugofs.FileMetaInfo {
-	helpers.Deprecated("Page.FileInfo", "Use .File.FileInfo", true)
-	return p.p.FileInfo()
-}


Test patch: