Repository: gohugoio/hugo (language: go)

Issue:
Permalink variable for using slug, or filename otherwise
I'm new to Hugo so I may be looking in the wrong place, but it seems that when I don't specify custom permalinks for `posts`, it will look for a `slug` in the front-matter, and use the filename if none is found. (Which is great!)

However, I can't seem to specify such a fallback order inside permalinks, because `:slug` will fallback to `:title` instead of `:filename`.

---

There is a [report of this from a while back](https://github.com/gohugoio/hugo/issues/385), which has been closed as "stale". Apologies if this a faux-pas, but I would like to re-open the conversation as a _feature request_. 

I'm migrating my old blog from a personal solution to Hugo, and I have all my posts as `domain.com/post-slug`, and it would be great to use the filename as slug without adding it in the front-matter.


Discussion / hints:
Did you come up with a solution to this? I have a similar issue.
@Ziflin I guess you could always add a slug to each post in the front-matter. I have not investigated other options...
I'm not exactly sure if this is what you're trying to do, but I have all my posts in `content/posts/` and they can be named `my-post-1.md` or named by using sub-directories `my-post-1/index.md`. My goal was to just get them to show up in the final website as `domain.com/my-post-1/` which I think is what you were trying? 

I was able to do this by making the following change in the sites `config` file (mine's yaml):
```
permalinks:
    posts: '/:slug/'
```
With that config change I don't need to make any other changes to the front matter per post. The post filename (or directory if using index.md in a sub-directory) is used and the final post url becomes `http://domain.com/my-post-1/`
This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
If this is a **bug** and you can still reproduce this error on the <code>master</code> branch, please reply with all of the information you have about it in order to keep the issue open.
If this is a **feature request**, and you feel that it is still relevant and valuable, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Fix patch:
diff --git a/docs/content/en/content-management/urls.md b/docs/content/en/content-management/urls.md
index f498d02ea51..774bd9a5852 100644
--- a/docs/content/en/content-management/urls.md
+++ b/docs/content/en/content-management/urls.md
@@ -91,6 +91,9 @@ The following is a list of values that can be used in a `permalink` definition i
 `:slug`
 : the content's slug (or title if no slug is provided in the front matter)
 
+`:slugorfilename`
+: the content's slug (or filename if no slug is provided in the front matter)
+
 `:filename`
 : the content's filename (without extension)
 
diff --git a/resources/page/permalinks.go b/resources/page/permalinks.go
index cd9c1dc1532..c31d22a3c67 100644
--- a/resources/page/permalinks.go
+++ b/resources/page/permalinks.go
@@ -72,18 +72,19 @@ func NewPermalinkExpander(ps *helpers.PathSpec) (PermalinkExpander, error) {
 	p := PermalinkExpander{ps: ps}
 
 	p.knownPermalinkAttributes = map[string]pageToPermaAttribute{
-		"year":        p.pageToPermalinkDate,
-		"month":       p.pageToPermalinkDate,
-		"monthname":   p.pageToPermalinkDate,
-		"day":         p.pageToPermalinkDate,
-		"weekday":     p.pageToPermalinkDate,
-		"weekdayname": p.pageToPermalinkDate,
-		"yearday":     p.pageToPermalinkDate,
-		"section":     p.pageToPermalinkSection,
-		"sections":    p.pageToPermalinkSections,
-		"title":       p.pageToPermalinkTitle,
-		"slug":        p.pageToPermalinkSlugElseTitle,
-		"filename":    p.pageToPermalinkFilename,
+		"year":           p.pageToPermalinkDate,
+		"month":          p.pageToPermalinkDate,
+		"monthname":      p.pageToPermalinkDate,
+		"day":            p.pageToPermalinkDate,
+		"weekday":        p.pageToPermalinkDate,
+		"weekdayname":    p.pageToPermalinkDate,
+		"yearday":        p.pageToPermalinkDate,
+		"section":        p.pageToPermalinkSection,
+		"sections":       p.pageToPermalinkSections,
+		"title":          p.pageToPermalinkTitle,
+		"slug":           p.pageToPermalinkSlugElseTitle,
+		"slugorfilename": p.pageToPermalinkSlugElseFilename,
+		"filename":       p.pageToPermalinkFilename,
 	}
 
 	patterns := ps.Cfg.GetStringMapString("permalinks")
@@ -266,6 +267,14 @@ func (l PermalinkExpander) pageToPermalinkSlugElseTitle(p Page, a string) (strin
 	return l.pageToPermalinkTitle(p, a)
 }
 
+// if the page has a slug, return the slug, else return the filename
+func (l PermalinkExpander) pageToPermalinkSlugElseFilename(p Page, a string) (string, error) {
+	if p.Slug() != "" {
+		return l.ps.URLize(p.Slug()), nil
+	}
+	return l.pageToPermalinkFilename(p, a)
+}
+
 func (l PermalinkExpander) pageToPermalinkSection(p Page, _ string) (string, error) {
 	return p.Section(), nil
 }


Test patch:
diff --git a/resources/page/permalinks_test.go b/resources/page/permalinks_test.go
index ca106c2361b..7baf1650370 100644
--- a/resources/page/permalinks_test.go
+++ b/resources/page/permalinks_test.go
@@ -36,6 +36,7 @@ var testdataPermalinks = []struct {
 	{"/:section/", true, "/blue/"},                                  // Section
 	{"/:title/", true, "/spf13-vim-3.0-release-and-new-website/"},   // Title
 	{"/:slug/", true, "/the-slug/"},                                 // Slug
+	{"/:slugorfilename/", true, "/the-slug/"},                       // Slug or filename
 	{"/:filename/", true, "/test-page/"},                            // Filename
 	{"/:06-:1-:2-:Monday", true, "/12-4-6-Friday"},                  // Dates with Go formatting
 	{"/:2006_01_02_15_04_05.000", true, "/2012_04_06_03_01_59.000"}, // Complicated custom date format
@@ -102,9 +103,13 @@ func TestPermalinkExpansionMultiSection(t *testing.T) {
 	page.section = "blue"
 	page.slug = "The Slug"
 
+	page_slug_fallback := newTestPageWithFile("/page-filename/index.md")
+	page_slug_fallback.title = "Page Title"
+
 	permalinksConfig := map[string]string{
-		"posts": "/:slug",
-		"blog":  "/:section/:year",
+		"posts":   "/:slug",
+		"blog":    "/:section/:year",
+		"recipes": "/:slugorfilename",
 	}
 
 	ps := newTestPathSpec()
@@ -120,6 +125,14 @@ func TestPermalinkExpansionMultiSection(t *testing.T) {
 	expanded, err = expander.Expand("blog", page)
 	c.Assert(err, qt.IsNil)
 	c.Assert(expanded, qt.Equals, "/blue/2012")
+
+	expanded, err = expander.Expand("posts", page_slug_fallback)
+	c.Assert(err, qt.IsNil)
+	c.Assert(expanded, qt.Equals, "/page-title")
+
+	expanded, err = expander.Expand("recipes", page_slug_fallback)
+	c.Assert(err, qt.IsNil)
+	c.Assert(expanded, qt.Equals, "/page-filename")
 }
 
 func TestPermalinkExpansionConcurrent(t *testing.T) {