lektor-website/docs/content/urls/index.html

326 lines
13 KiB
HTML
Raw Permalink Normal View History

2022-02-20 15:15:38 +01:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
2022-12-17 10:12:40 +01:00
<link rel="stylesheet" href="../../../static/styles.css?h=dff0aaad">
2022-02-20 15:15:38 +01:00
<link rel="stylesheet" href="../../../static/pygments.css">
<link rel="shortcut icon" href="../../../static/favicon.png?h=fa09bedd">
<title>URLs and Slugs | Documentation | Lektor Static Content Management System</title>
</head>
<body class="default">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../">Lektor</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="../../../downloads/">Download</a></li>
<li class="active"><a href="../../">Documentation</a></li>
<li><a href="../../../showcase/">Showcase</a></li>
<li><a href="../../../plugins/">Plugins</a></li>
<li><a href="../../../community/">Community</a></li>
<li><a href="../../../blog/">Blog</a></li>
</ul>
</div>
</div>
</nav>
<div class="body-wrapper">
<div class="container">
<div class="row">
<div class="col-sm-3">
<ul class="tree-nav nocontent">
<li><a href="../../">Welcome</a></li>
<li><a href="../../what/">What is Lektor</a>
<li><a href="../../installation/">Installation</a>
<li><a href="../../quickstart/">Quickstart</a>
<li><a href="../../project/">Project</a>
<li><a href="../">Content</a>
<ul>
<li><a href="../alts/">Alternatives</a>
<li><a href="../attachments/">Attachments</a>
<li><a href="../databags/">Data Bags</a>
<li><a href="../flow/">Flow</a>
<li><a href="../paths/">Paths</a>
<li><a href="../system-fields/">System Fields</a>
<li class="active"><a href="./">URLs and Slugs</a>
<ul></ul>
</ul>
<li><a href="../../templates/">Templates</a>
<li><a href="../../themes/">Themes</a>
<li><a href="../../guides/">Guides</a>
<li><a href="../../deployment/">Deployment</a>
<li><a href="../../plugins/">Plugins</a>
<li><a href="../../models/">Data Modelling</a>
<li><a href="../../cli/">Command Line</a>
<li><a href="../../api/">API</a>
<li><a href="../../search/">Search</a>
</ul>
<div class="visible-md-block visible-lg-block">
<h4>This Page</h4>
<ul class="toc">
<li><a href="#a-url-is-composed-of-slugs">A URL Is Composed of Slugs</a></li>
<li><a href="#slug-customization">Slug Customization</a><ul>
<li><a href="#folder-name">Folder Name</a></li>
<li><a href="#the-slug-system-field">The <code>_slug</code> System Field</a></li>
<li><a href="#implied-slug-configuration">Implied Slug Configuration</a></li>
</ul></li>
<li><a href="#slugs-containing-slashes">Slugs Containing Slashes</a></li>
<li><a href="#extensions-and-file-types">Extensions and File Types</a></li>
<li><a href="#content-below-dotted-slugs">Content Below Dotted Slugs</a></li>
<li><a href="#external-and-absolute-urls">External and Absolute URLs</a></li>
</ul>
</div>
</div>
<div class="col-sm-9 doc-styling">
<h1>URLs and Slugs</h1>
<ul class=page-meta>
</ul>
<p>Lektor's URLs in general mirror what happens on the file system as much as
possible. There are however various cases in which this behavior can be
changed.</p>
<h2 id="a-url-is-composed-of-slugs">A URL Is Composed of Slugs</h2><p>Each page in Lektor is associated with a string called a <em>slug</em>. The full
URL of a page is its own slug concatenated with the slug of each its parents.</p>
<p>The default slug is the ID of the page. So the page
<code>content/foo/bar/contents.lr</code> has the default slug <code>bar</code>, its parent has the
default slug <code>foo</code>, and its default URL would be <code>/foo/bar/</code>.</p>
<h2 id="slug-customization">Slug Customization</h2><p>Slugs can be customized. They can even contain slashes (see below). There are
three systems that control what the slug looks like:</p>
<h3 id="folder-name">Folder Name</h3><p>The name of the folder that contains the <code>contents.lr</code> file is the ID of the
page and thus the default slug (unless changed by the model — more about that
later). This means that you could for instance just rename the folder to
get a different slug. This is the recommended way for the majority of pages
to adjust the slug.</p>
<h3 id="the-slug-system-field">The <code>_slug</code> System Field</h3><p>The second option is to use the <code>_slug</code> system field. This field is available
for all models automatically and overrides the slug explicitly. This is
particularly useful to force a slug that could not be represented on the file
system (for instance because it should contain a slash) or because you want
to change the slug for a different <a href="../alts/" class="ref">Alternative</a>. As
an example a page translated to German might want to translate the slug as well.</p>
<h3 id="implied-slug-configuration">Implied Slug Configuration</h3><p>The last part is a system that controls the implied slugs. In particular it
means that the model of the parent page can override the default slug for all
of the children below it. This for instance can be used to automatically add
the date of a blog post into the slug. For more information about this
feature see <a href="../../models/children/" class="ref">Children &amp; Pagination</a>.</p>
<h2 id="slugs-containing-slashes">Slugs Containing Slashes</h2><p>Slugs can indeed contain slashes. It's perfectly valid for a page to have
<code>2015/5/demo</code> as slug, and it will still be incorporated into URLs as described
above. What's not possible is for a page to pretend that it belongs to a
different parent. The parent paths are always added to it. So once a page
has a parent page <code>/foo</code> its URL path will always begin with the URL path of
the page <code>foo</code>.</p>
<h2 id="extensions-and-file-types">Extensions and File Types</h2><p>The default behavior for a page is to build into a hidden <code>index.html</code> file.
This means that if you have a page called <code>foo/bar/contents.lr</code> it will
build into a file named <code>foo/bar/index.html</code>. Web servers typically look for
an <code>index.html</code> file in a folder which is why you can just access <code>/foo/bar/</code>
and the page will render.</p>
<p>If however the last path component contains a period (<code>.</code>) then the last path
component is assumed to be a filename directly. This means that if you set
the slug of a page to <code>404.html</code> for instance, the page will indeed render
into <code>404.html</code> and not <code>404/index.html</code>.</p>
<p>However you need to be careful with this as web servers pick the “mimetype”
of a file based on the extension. So if you name a file <code>foo.html</code> it will
behave very differently compared to a file named <code>foo.txt</code>. So do not name
your files in ways that would be incompatible with what the web server
renders. This however also allows you to generate files that are not
HTML. For instance you could render into a <code>.xml</code> file if that is what
you want.</p>
<p>This feature is called “Dotted Slugs” and there are some specifics with
regards to how these are handled.</p>
<h2 id="content-below-dotted-slugs">Content Below Dotted Slugs</h2><p>One specific behavior of a path component that contains a dotted slug is that
content below that path need to move to a different location. Imagine for
instance you named the page <code>404.html</code> but that page has an attachment. As
<code>404.html</code> is now a file it's impossible for a folder with the same name to
exist. This means that the attachments have to be stored elsewhere. The
convention for this in Lektor is to prefix the path with an underscore. So
if <code>404.html</code> has an attachment named <code>foo.jpeg</code> it will move into
<code>_404.html/foo.jpeg</code>.</p>
<h2 id="external-and-absolute-urls">External and Absolute URLs</h2><p>Lektor by default will prefer relative URLs. This makes it possible to easily
host a website below a certain folder without having to do anything special to
make this work. However there are some features which will require the use of
an absolute or fully canonical (external) URL. For instance sitemaps or Atom
feeds do not work with relative URLs. In this case the absolute URL path has
to be configured.</p>
<p>You can pick the default for URL generation in the project configuration.
2022-03-04 20:32:54 +01:00
For more information read about the <a href="../../project/file/#project" class="ref">Project Configuration</a>.</p>
2022-02-20 15:15:38 +01:00
<p>The default of <code>relative</code>, a relative URL style, means that you can deploy a
website to a sub folder without any configuration, however most likely custom
404 pages will fail to find the needed assets. Fully canonical URLs are not
recommended as default style.</p>
<div class="comment-box">
<h2>Comments</h2>
<div id="disqus_thread"></div>
<script>
var disqus_config = function() { this.page.identifier = "/docs/content/urls"; this.page.url = "https://www.getlektor.com/docs/content/urls/"; };
(function() {
var d = document, s = d.createElement('script');
s.src = '//lektordocumentation.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>
Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript"
rel="nofollow">comments powered by Disqus.</a>
</noscript>
</div>
</div>
</div>
</div>
</div>
<div class="bottomsummary">
<div class="container">
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-sm-4 icon-bar">
<a href="https://github.com/lektor/lektor/" title="Lektor on GitHub"
><i class="fa fa-github"></i></a>
<a href="https://github.com/lektor/lektor/issues/" title="Report Issues for Lektor"
><i class="fa fa-bug"></i></a>
<a href="https://twitter.com/getlektor" title="Find Lektor on Twitter"
><i class="fa fa-twitter"></i></a>
<a href="https://gitter.im/lektor/lektor" title="Chat on Gitter"
><i class="fa fa-comment"></i></a>
<a href="https://github.com/lektor/lektor-website/tree/master/content/docs/content/urls/contents.lr" title="View source for this page"><i class="fa fa-code"></i></a>
</div>
<div class="col-sm-8">
<a href="../../../license/">License & Copyright</a>
<a href="../../../contact/">Contact</a>
Made with <i class="fa fa-fw fa-heart" title="Heart"><span hidden>Heart</span></i> in Carinthia
</div>
</div>
</div>
</footer>
2024-06-22 13:39:56 +02:00
<script type=text/javascript src="../../../static/app.js?h=250c2aed" charset="utf-8"></script>
2022-02-20 15:15:38 +01:00
<script>
((window.gitter = {}).chat = {}).options = {
room: 'lektor/lektor',
activationElement: null
};
document.write('<button class="js-gitter-toggle-chat-button">Toggle Chat</button>');
var dnt = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
if (dnt != "1" && dnt != "yes") {
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-70822533-1', 'auto');
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');
} else {
console.debug("Respecting Do-Not-Track, not running analytics.");
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<script async defer id="github-bjs" src="https://buttons.github.io/buttons.js"></script>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
</body>
</html>