Initial check-in after refactoring to use Hugo site generator with ReLearn template. HTTP Status Codes page not done--nor adwords added.

This commit is contained in:
Todd Fredrich
2022-11-07 09:48:25 -07:00
parent b9dc2eaf8d
commit 7675fcd740
353 changed files with 28093 additions and 1493 deletions

6
archetypes/default.md Normal file
View File

@ -0,0 +1,6 @@
---
title: "{{ replace .Name "-" " " | title }}"
date: {{ .Date }}
draft: true
---

30
config.toml Normal file
View File

@ -0,0 +1,30 @@
baseURL = 'http://restapitutorial.org/'
languageCode = 'en-us'
title = 'REST API Tutorial'
uglyURLs = true
#
# Change the default theme to hugo-theme-relearn
theme = "relearn"
# For search functionality
[outputs]
home = [ "HTML", "RSS", "JSON"]
[[menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Tags"
url = "tags/"
weight = 40
[params]
editURL = "https://github.com/McShelby/hugo-theme-relearn/edit/main/exampleSite/content/"
description = "Learn REST API Design"
author = "Todd Fredrich"
collapsibleMenu = true
titleSeparator = " - "
themeVariant = [ "relearn-light", "relearn-dark" ]

8
content/_index.md Normal file
View File

@ -0,0 +1,8 @@
# Learn REST API Design
Keyword-rich introductory content goes here.
## Get Started
1. Click the arrow in the upper-right corner to progress to the next section or
2. Use the left-hand menu to begin with [Chapter 1. The Basics](/basics)

View File

@ -0,0 +1,11 @@
+++
chapter = true
pre = "<b>2. </b>"
title = "Advanced API Design"
weight = 10
+++
### Chapter 2
# The Seven Pillars of API Design
We Begin Our Journey in Designing Exquisite RESTful APIs.

16
content/basics/_index.md Normal file
View File

@ -0,0 +1,16 @@
+++
chapter = true
pre = "<b>1. </b>"
title = "The Basics"
weight = 5
+++
### Chapter 1
# Learn REST API Basics
Quickly learn the basics of what REST is and the core concepts behind it.
{{% notice style="tip" title="Here's a Quick Tip!" icon="exclamation-circle" %}}
Be on the lookout for Quick Tips in boxes like this throughout the course. They'll provide a jump-start to your super-powers
(or at least give you a leg up on getting your job done)!
{{% /notice %}}

View File

@ -0,0 +1,84 @@
---
title: "HTTP Methods"
date: 2022-06-07T16:31:51-06:00
weight: 30
---
The HTTP verbs (or methods, as they are formally called) comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs are POST, GET, PUT, PATCH, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other verbs, too, but are utilized less frequently. Of those less-frequent methods, OPTIONS and HEAD are used more often than others.
Below is a table summarizing recommended return values of the primary HTTP methods in combination with the resource URIs:
| Method | CRUD | Entire Collection (e.g. /customers) | Specific Item (e.g. /customers/{id}) |
| --------- | ---- | ----------------------------------- | ------------------------------------ |
| POST | Create | 201 (Created), 'Location' header with link to /customers/{id} containing new ID. | 404 (Not Found), 409 (Conflict) if resource already exists. |
| GET | Read | 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. | 200 (OK), single customer. 404 (Not Found), if ID not found or invalid. |
| PUT | Update/Replace | 405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
| PATCH | Update/Modify 405 (Method Not Allowed), unless you want to modify the collection itself. Which is possible if operating on the collection as a whole. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
| DELETE | Delete | 405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable. | 200 (OK). 404 (Not Found), if ID not found or invalid. |
Below is a more-detailed discussion of the main HTTP methods.
### POST
The POST verb is most-often utilized to *create* new a resource. In particular, it's used to create subordinate resources. That is, subordinate to some other (e.g. parent) resource. In other words, when creating a new resource, POST to the parent and the service takes care of associating the new resource with the parent, assigning an ID (new resource URI), etc.
On successful creation, return HTTP status 201, returning a Location header with a link to the newly-created resource with the 201 HTTP status.
POST is neither safe nor idempotent. It is therefore recommended for non-idempotent resource requests. Making two identical POST requests will most-likely result in two resources containing the same information.
__Examples:__
* POST http://www.example.com/customers
* POST http://www.example.com/customers/12345/orders
### GET
The HTTP GET method is used to **read** (or retrieve) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).
According to the design of the HTTP specification, GET (along with HEAD) requests are used only to read data and not change it. Therefore, when used this way, they are considered safe. That is, they can be called without risk of data modification or corruption—calling it once has the same effect as calling it 10 times, or none at all. Additionally, GET (and HEAD) is idempotent, which means that making multiple identical requests ends up having the same result as a single request.
Do not expose unsafe operations via GET—it should never modify any resources on the server.
__Examples:__
* GET http://www.example.com/customers/12345
* GET http://www.example.com/customers/12345/orders
* GET http://www.example.com/buckets/sample
### PUT
PUT is most-often utilized for *update* capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource.
However, PUT can also be used to create a resource in the case where the resource ID is chosen by the client instead of by the server. In other words, if the PUT is to a URI that contains the value of a non-existent resource ID. Again, the request body contains a resource representation. Many feel this is convoluted and confusing. Consequently, this method of creation should be used sparingly, if at all.
Alternatively, use POST to create new resources and provide the client-defined ID in the body representation—presumably to a URI that doesn't include the ID of the resource (see POST below).
On successful update, return 200 (or 204 if not returning any content in the body) from a PUT. If using PUT for create, return HTTP status 201 on successful creation. A body in the response is optional—providing one consumes more bandwidth. It is not necessary to return a link via a Location header in the creation case since the client already set the resource ID.
PUT is not a safe operation, in that it modifies (or creates) state on the server, but it is idempotent. In other words, if you create or update a resource using PUT and then make that same call again, the resource is still there and still has the same state as it did with the first call.
If, for instance, calling PUT on a resource increments a counter within the resource, the call is no longer idempotent. Sometimes that happens and it may be enough to document that the call is not idempotent. However, it's recommended to keep PUT requests idempotent. It is strongly recommended to use POST for non-idempotent requests.
__Examples:__
* PUT http://www.example.com/customers/12345
* PUT http://www.example.com/customers/12345/orders/98765
* PUT http://www.example.com/buckets/secret_stuff
### PATCH
PATCH is used for *modify* capabilities. The PATCH request only needs to contain the changes to the resource, not the complete resource.
This resembles PUT, but the body contains a set of instructions describing how a resource currently residing on the server should be modified to produce a new version. This means that the PATCH body should not just be a modified part of the resource, but in some kind of patch language like JSON Patch or XML Patch.
PATCH is neither safe nor idempotent. However, a PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame. Collisions from multiple PATCH requests may be more dangerous than PUT collisions because some patch formats need to operate from a known base-point or else they will corrupt the resource. Clients using this kind of patch application should use a conditional request such that the request will fail if the resource has been updated since the client last accessed the resource. For example, the client can use a strong ETag in an If-Match header on the PATCH request.
__Examples:__
* PATCH http://www.example.com/customers/12345
* PATCH http://www.example.com/customers/12345/orders/98765
* PATCH http://www.example.com/buckets/secret_stuff
### DELETE
DELETE is pretty easy to understand. It is used to *delete* a resource identified by a URI.
On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the representation of the deleted item (often demands too much bandwidth), or a wrapped response (see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no response body. In other words, a 204 status with no body, or the JSEND-style response and HTTP status 200 are the recommended responses.
HTTP-spec-wise, DELETE operations are idempotent. If you DELETE a resource, it's removed. Repeatedly calling DELETE on that resource ends up the same: the resource is gone. If calling DELETE say, decrements a counter (within the resource), the DELETE call is no longer idempotent. As mentioned previously, usage statistics and measurements may be updated while still considering the service idempotent as long as no resource data is changed. Using POST for non-idempotent resource requests is recommended.
There is a caveat about DELETE idempotence, however. Calling DELETE on a resource a second time will often return a 404 (NOT FOUND) since it was already removed and therefore is no longer findable. This, by some opinions, makes DELETE operations no longer idempotent, however, the end-state of the resource is the same. Returning a 404 is acceptable and communicates accurately the status of the call.
__Examples:__
* DELETE http://www.example.com/customers/12345
* DELETE http://www.example.com/customers/12345/orders
* DELETE http://www.example.com/bucket/sample

View File

@ -0,0 +1,14 @@
---
title: "Idempotence"
date: 2022-06-08T15:35:13-06:00
weight: 50
---
{{< youtube 6dVNdFwqeKs >}}
Idempotence is a funky word that often hooks people. Idempotence is sometimes a confusing concept, at least from the academic definition.
From a RESTful service standpoint, for an operation (or service call) to be idempotent, clients can make that same call repeatedly while producing the same result. In other words, making multiple identical requests has the same effect as making a single request. Note that while idempotent operations produce the same result on the server (no side effects), the response itself may not be the same (e.g. a resource's state may change between requests).
The PUT and DELETE methods are defined to be idempotent. However, there is a caveat on DELETE. The problem with DELETE, which if successful would normally return a 200 (OK) or 204 (No Content), will often return a 404 (Not Found) on subsequent calls, unless the service is configured to "mark" resources for deletion without actually deleting them. However, when the service actually deletes the resource, the next call will not find the resource to delete it and return a 404. However, the state on the server is the same after each DELETE call, but the response is different.
GET, HEAD, OPTIONS and TRACE methods are defined as safe, meaning they are only intended for retrieving data. This makes them idempotent as well since multiple, identical requests will behave the same.

View File

@ -0,0 +1,77 @@
---
title: "Resource Naming"
date: 2022-06-07T16:44:49-06:00
weight: 40
---
In addition to utilizing the HTTP verbs appropriately, resource naming is arguably the most debated and most important concept to grasp when creating an understandable, easily leveraged Web service API. When resources are named well, an API is intuitive and easy to use. Done poorly, that same API can feel klutzy and be difficult to use and understand. Below are a few tips to get you going when creating the resource URIs for your new API.
Essentially, a RESTful API ends up being simply a collection of URIs, HTTP calls to those URIs and some JSON and/or XML representations of resources, many of which will contain relational links. The RESTful principal of addressability is covered by the URIs. Each resource has its own address or URI—every interesting piece of information the server can provide is exposed as a resource. The constraint of uniform interface is partially addressed by the combination of URIs and HTTP verbs, and using them in line with the standards and conventions.
In deciding what resources are within your system, name them as nouns as opposed to verbs or actions. In other words, a RESTful URI should refer to a resource that is a thing instead of referring to an action. Nouns have properties as verbs do not, just another distinguishing factor.
Some example resources are:
* Users of the system.
* Courses in which a student is enrolled.
* A user's timeline of posts.
* The users that follow another user.
* An article about horseback riding.
Each resource in a service suite will have at least one URI identifying it. And it's best when that URI makes sense and adequately describes the resource. URIs should follow a predictable, hierarchical structure to enhance understandability and, therefore, usability: predictable in the sense that they're consistent, hierarchical in the sense that data has structure—relationships. This is not a REST rule or constraint, but it enhances the API.
RESTful APIs are written for consumers. The name and structure of URIs should convey meaning to those consumers. It's often difficult to know what the data boundaries should be, but with understanding of your data, you most-likely are equipped to take a stab and what makes sense to return as a representation to your clients. Design for your clients, not for your data.
Let's say we're describing an order system with customers, orders, line items, products, etc. Consider the URIs involved in describing the resources in this service suite:
## Resource URI Examples
### Customers
To insert (create) a new customer in the system, we might use:
* POST http://www.example.com/customers
To read a customer with Customer ID# 33245:
* GET http://www.example.com/customers/33245
The same URI would be used for PUT and DELETE, to update and delete, respectively.
### Products
Here are proposed URIs for products:
* For creating a new product:
* POST http://www.example.com/products
* For reading, replacing, updating, deleting product ID 66432, respectively:
* GET http://www.example.com/products/66432
* PUT http://www.example.com/products/66432
* PATCH http://www.example.com/products/66432
* DELETE http://www.example.com/products/66432
### Orders
Now, here is where it gets fun... What about creating a new order for a customer? One option might be:
* POST http://www.example.com/orders
And that could work to create an order, but it's arguably outside the context of a customer.
Because we want to create an order for a customer (note the relationship), this URI perhaps is not as intuitive as it could be. It could be argued that the following URI would offer better clarity:
* POST http://www.example.com/customers/33245/orders
Now we know we're creating an order for customer ID# 33245.
Now what would the following return?
* GET http://www.example.com/customers/33245/orders
Probably a list of orders that customer #33245 has created or owns. Note: we may choose to not support DELETE or PUT for that url since it's operating on the entire collection of a cutomer's orders.
Now, to continue the hierarchical concept, what about the following URI?
* POST http://www.example.com/customers/33245/orders/8769/lineitems
That might add a line item to order #8769 (which is for customer #33245). Right! GET for that URI might return all the line items for that order. However, if line items don't make sense only in customer context or also make sense outside the context of a customer, we would offer a:
* POST www.example.com/orders/8769/lineitems URI.
Along those lines, because there may be multiple URIs for a given resource, we might also offer a
* GET http://www.example.com/orders/8769
URI that supports retrieving an order by number without having to know the customer number.
To go one layer deeper in the hierarchy:
* GET http://www.example.com/customers/33245/orders/8769/lineitems/1
Might return only the first line item in that same order.
By now you can see how the hierarchy concept works. There aren't any hard and fast rules, only make sure the imposed structure makes sense to consumers of your services. As with everything in the craft of Software Development, naming is critical to success.
### Other Example APIs
Look at some widely used APIs to get the hang of this and leverage the intuition of your teammates to refine your API resource URIs. Some example APIs are:
* Twitter: https://developer.twitter.com/en/docs/api-reference-index
* Facebook: https://developers.facebook.com/docs/reference/api/
* LinkedIn: https://developer.linkedin.com/apis

View File

@ -0,0 +1,53 @@
---
title: "The Six Constraints"
date: 2022-06-07T08:22:06-06:00
weight: 15
---
{{< youtube llpr5924N7E >}}
The REST architectural style describes six constraints. These constraints, applied to the architecture, were originally communicated by Roy Fielding in his doctoral dissertation (see https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm) and defines the basis of RESTful-style.
The six constraints are as follows:
## 1. Uniform Interface
The uniform interface constraint defines the interface between clients and servers. It simplifies and decouples the architecture, which enables each part to evolve independently. The four guiding principles of the uniform interface are:
### 1.a. Resource-Based
Individual resources are identified in requests using URIs as resource identifiers. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server does not send its database, but rather, some HTML, XML or JSON that represents some database records expressed, for instance, in Finnish and encoded in UTF-8, depending on the details of the request and the server implementation.
### 1.b. Manipulation of Resources Through Representations
When a client holds a representation of a resource, including any metadata attached, it has enough information to modify or delete the resource on the server, provided it has permission to do so.
### 1.c. Self-descriptive Messages
Each message includes enough information to describe how to process the message. For example, which parser to invoke may be specified by an Internet media type (previously known as a MIME type). Responses also explicitly indicate their cache-ability.
### 1.d. Hypermedia as the Engine of Application State (HATEOAS)
Clients deliver state via body contents, query-string parameters, request headers and the requested URI (the resource name). Services deliver state to clients via body content, response codes, and response headers. This is technically referred-to as hypermedia (or hyperlinks within hypertext).
Aside from the description above, HATEOS also means that, where necessary, links are contained in the returned body (or headers) to supply the URI for retrieval of the object itself or related objects. We'll talk about this in more detail later.
The uniform interface that any REST services must provide is fundamental to its design.
## 2. Stateless
As REST is an acronym for REpresentational State Transfer, statelessness is key. Essentially, what this means is that the necessary state to handle the request is contained within the request itself, whether as part of the URI, query-string parameters, body, or headers. The URI uniquely identifies the resource and the body contains the state (or state change) of that resource. Then after the server does it's processing, the appropriate state, or the piece(s) of state that matter, are communicated back to the client via headers, status and response body.
Most of us who have been in the industry for a while are accustomed to programming within a container which provides us with the concept of “session” which maintains state across multiple HTTP requests. In REST, the client must include all information for the server to fulfill the request, resending state as necessary if that state must span multiple requests. Statelessness enables greater scalability since the server does not have to maintain, update or communicate that session state. Additionally, load balancers don't have to worry about session affinity for stateless systems.
So what's the difference between state and a resource? State, or application state, is that which the server cares about to fulfill a request—data necessary for the current session or request. A resource, or resource state, is the data that defines the resource representation—the data stored in the database, for instance. Consider application state to be data that could vary by client, and per request. Resource state, on the other hand, is constant across every client who requests it.
Ever had back-button issues with a web application where it went AWOL at a certain point because it expected you to do things in a certain order? That's because it violated the statelessness principle. There are cases that don't honor the statelessness principle, such as three-legged OAuth, API call rate limiting, etc. However, make every effort to ensure that application state doesn't span multiple requests of your service(s).
## 3. Cacheable
As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some clientserver interactions, further improving scalability and performance.
## 4. Client-Server
The uniform interface separates clients from servers. This separation of concerns means that, for example, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface is not altered.
## 5. Layered System
A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. Layers may also enforce security policies.
## 6. Code on Demand (optional)
Servers are able to temporarily extend or customize the functionality of a client by transferring logic to it that it can execute. Examples of this may include compiled components such as Java applets and client-side scripts such as JavaScript.
Complying with these constraints, and thus conforming to the REST architectural style, will enable any kind of distributed hypermedia system to have desirable emergent properties, such as performance, scalability, simplicity, modifiability, visibility, portability and reliability.
NOTE: The only optional constraint of REST architecture is code on demand. If a service violates any other constraint, it cannot strictly be referred to as RESTful.

View File

@ -0,0 +1,81 @@
---
title: "REST Quick Tips"
date: 2022-06-06T16:58:56-06:00
weight: 20
---
Whether it's technically RESTful or not (according to the six constraints mentioned previously), here are a few recommended REST-like concepts. These six quick tips will result in better, more usable services.
## Use HTTP Methods to Make Requests Mean Something
API consumers are capable of sending GET, POST, PUT, PATCH and DELETE methods (or verbs), which greatly enhance the clarity of a given request.
Generally, the five primary HTTP methods are used as follows:
| Method | Description |
| ---- | ----------- |
| GET | Read a specific resource (by an identifier) or a collection of resources.|
| PUT | Replace a specific resource (by an identifier) or a collection of resources. Can also be used to create a specific resource if the resource identifier is known before-hand.|
| PATCH | Update a specific resource (by an identifier) or a collection of resources. This can be thought of in some ways as a 'partial update' vs the replace that PUT performs.|
| DELETE | Remove/delete a specific resource by an identifier. |
| POST | Create a new resource. Also a catch-all verb for operations that don't fit into the other categories. |
__Note__: GET requests MUST not change any underlying resource data. Measurements and tracking which update data may still occur, but the resource identified by the URI MUST not change.
## Provide Sensible Resource Names
Producing a great API is 80% art and 20% science. Creating a URL hierarchy representing sensible resources is the art part. Having sensible resource names (which are just URL paths, such as /customers/12345/orders) improves the clarity of what a given request does. As humans are involved in understanding an API, this clarity counts.
Appropriate resource names provide context for a service request, increasing understandability of the API. Resources are viewed hierarchically via their URI names, offering consumers a friendly, easily-understood hierarchy of resources to leverage in their applications.
Here are some quick-hit rules for URL path (resource name) design:
* Use identifiers in your URLs instead of in the query-string. Using URL query-string parameters is fantastic for filtering, but not for resource names.
* Good: /users/12345
* Poor: /api?type=user&id=23
* Leverage the hierarchical nature of the URL to imply structure.
* Design for your clients, not for your data.
* Resource names should be nouns. Avoid verbs as resource names, to improve clarity. Use the HTTP methods to specify the verb portion of the request.
* Use plurals in URL segments to keep your API URIs consistent across all HTTP methods, using the collection metaphor.
* Recommended: /customers/33245/orders/8769/lineitems/1
* Not: /customer/33245/order/8769/lineitem/1
* Avoid using collection verbiage in URLs. For example 'customer_list' as a resource. Use pluralization to indicate the collection metaphor (e.g. customers vs. customer_list).
* Use lower-case in URL segments, separating words with underscores ('_') or hyphens ('-'). Some servers ignore case so it's best to be clear.
* Keep URLs as short as possible, with as few segments as makes sense.
## Use HTTP Response Codes to Indicate Status
Response status codes are part of the HTTP specification. There are quite a number of them to address the most common situations. In the spirit of having our RESTful services embrace the HTTP specification, our Web APIs should return relevant HTTP status codes. For example, when a resource is successfully created (e.g. from a POST request), the API should return HTTP status code 201. A list of valid HTTP status codes is available here which lists detailed descriptions of each.
Suggested usages for the "Top 10" HTTP Response Status Codes are as follows:
| Status Code | Description |
| ----------- | ----------- |
| 200 OK | General success status code. This is the most common code. Used to indicate success. |
| 201 CREATED | Successful creation occurred (via either POST or PUT). Set the Location header to contain a link to the newly-created resource (on POST). Response body content may or may not be present. |
| 204 NO CONTENT | Indicates success but nothing is in the response body, often used for DELETE and PUT operations. |
| 400 BAD REQUEST | General error for when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples. |
| 401 UNAUTHORIZED | Error code response for missing or invalid authentication token. |
| 403 FORBIDDEN | Error code for when the user is not authorized to perform the operation or the resource is unavailable for some reason (e.g. time constraints, etc.). |
| 404 NOT FOUND | Used when the requested resource is not found, whether it doesn't exist or if there was a 401 or 403 that, for security reasons, the service wants to mask. |
| 405 METHOD NOT ALLOWED | Used to indicate that the requested URL exists, but the requested HTTP method is not applicable. For example, POST /users/12345 where the API doesn't support creation of resources this way (with a provided ID). The Allow HTTP header must be set when returning a 405 to indicate the HTTP methods that are supported. In the previous case, the header would look like "Allow: GET, PUT, DELETE" |
| 409 CONFLICT | Whenever a resource conflict would be caused by fulfilling the request. Duplicate entries, such as trying to create two customers with the same information, and deleting root objects when cascade-delete is not supported are a couple of examples. |
| 500 INTERNAL SERVER ERROR | __Never return this intentionally.__ The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end. |
## Support JSON
Favor JSON support unless you're in a highly-standardized and regulated industry that requires XML, schema validation and namespaces. If you must provide both JSON and XML let consumers switch between formats using the HTTP Accept header: application/json or application/xml.
Be aware that as soon as we start talking about XML support, we start talking about schemas for validation, namespaces, etc. Unless required by your industry, avoid supporting all that complexity initially, if ever. JSON is designed to be simple, terse and functional.
## Create Fine-Grained Resources
When starting out, it's best to create APIs that mimic the underlying application domain or database architecture of your system. Eventually, you'll want aggregate services that utilize multiple underlying resources to reduce chattiness. However, it's much easier to create larger resources later from individual resources than it is to create fine-grained or individual resources from larger aggregates. Make it easy on yourself and start with small, easily defined resources, providing CRUD functionality on those. You can create those use-case-oriented, chattiness-reducing resources later.
## Consider Connectedness
One of the principles of REST is connectedness—via hypermedia links (search HATEOAS). While services are still useful without them, APIs become more self-descriptive and discoverable when links are returned in the response. At the very least, a 'self' link reference informs clients how the data was or can be retrieved. Additionally, utilize the HTTP Location header to contain a link on resource creation via POST (or PUT). For collections returned in a response that support pagination, 'first', 'last', 'next' and 'prev' links at a minimum are very helpful.
Regarding linking formats, there are many. The HTTP Web Linking Specification (RFC5988) explains a link as follows:
> a link is a typed connection between two resources that are identified by Internationalised Resource Identifiers (IRIs) [RFC3987], and is comprised of:
> * A context IRI,
> * a link relation type
> * a target IRI, and
> * optionally, target attributes.
>
> A link can be viewed as a statement of the form "{context IRI} has a {relation type} resource at {target IRI}, which has {target attributes}."
At the very least, place links in the HTTP Link header as recommended in the specification, or embrace a JSON representation of this HTTP link style (such as Atom-style links, see: RFC4287) in your JSON representations. Later, you can layer in more complex linking styles such as HAL+JSON, Siren, Collection+JSON, and/or JSON-LD, etc. as your REST APIs become more mature.

View File

@ -0,0 +1,140 @@
---
title: "What is REST?"
date: 2022-06-06T16:35:40-06:00
weight: 10
---
The term RESTful APIs or RESTful services is a hot topic. So what is REST? And how do we create a so-called RESTful API? Good question! Let's talk about this often misunderstood phrase...
{{% notice style="tip" title="Here's a Quick Tip!" icon="exclamation-circle" %}}
When someone says, "REST service," "REST API" or "RESTful API" they more-than-likely mean an HTTP or Web-based server that accepts requests over HTTP and responds in human-readable JSON.
Yep, that really is it. But there are a lot of nuances--read on to discover more details!
{{% /notice %}}
Technically, REST is an acronym for "REpresentational State Transfer" which is simply an architectural style originally written about by Roy Fielding in his doctoral dissertation (see https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm). You can read more details about the six contraints here, but first I want to give you a brief overview of what people mean when they say "REST."
To be clear, the constraints in Roy Fielding's dissertation MUST be met in order for a service to be technically RESTful. And the REST constraints do not specify a communication protocol. However, at this point the term is used very loosely and in today's Internet world, RESTful almost always means an HTTP-based API. That means it operates in a request-response fashion over HTTP, usually using JSON as the data format in the request and response bodies. Though there are a lot of nuances, it's really just that simple!
In other words, the caller (or client):
* Makes an HTTP request to a URL...
* Using one of the standard HTTP methods (GET, PUT, POST, PATCH, DELETE, etc.)...
* With some content (usually JSON) in the body...
* And waits for a response, which:
* Indicates status via an HTTP response code
* And usually has more JSON in the body.
For example, say we wanted to search iTunes for RadioHead songs. We would call the iTunes Search API (See: https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/iTuneSearchAPI/index.html).
We can use 'curl' on the command-line as follows. In this case all the query-string paremeters on the URL are simply telling the search API what term to search for (radiohead), how many results we want returned (3), and the type of media (music):
```bash
curl -i 'https://itunes.apple.com/search?term=radiohead&media=music&limit=3'
```
Which returns the following JSON response:
```json
{
"resultCount":3,
"results":[
{
"wrapperType":"track",
"kind":"song",
"artistId":657515,
"collectionId":1109714933,
"trackId":1109715066,
"artistName":"Radiohead",
"collectionName":"In Rainbows",
"trackName":"15 Step",
"collectionCensoredName":"In Rainbows",
"trackCensoredName":"15 Step",
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
"collectionViewUrl":"https://music.apple.com/us/album/15-step/1109714933?i=1109715066&uo=4",
"trackViewUrl":"https://music.apple.com/us/album/15-step/1109714933?i=1109715066&uo=4",
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/af/72/85/af728523-8048-4a8b-9e13-e8f4f64e9d69/mzaf_8205306206851675436.plus.aac.p.m4a",
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
"collectionPrice":9.99,
"trackPrice":1.29,
"releaseDate":"2007-10-10T07:00:00Z",
"collectionExplicitness":"notExplicit",
"trackExplicitness":"notExplicit",
"discCount":1,
"discNumber":1,
"trackCount":10,
"trackNumber":1,
"trackTimeMillis":237293,
"country":"USA",
"currency":"USD",
"primaryGenreName":"Alternative",
"isStreamable":true
},
{
"wrapperType":"track",
"kind":"song",
"artistId":657515,
"collectionId":1109714933,
"trackId":1109715161,
"artistName":"Radiohead",
"collectionName":"In Rainbows",
"trackName":"Bodysnatchers",
"collectionCensoredName":"In Rainbows",
"trackCensoredName":"Bodysnatchers",
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
"collectionViewUrl":"https://music.apple.com/us/album/bodysnatchers/1109714933?i=1109715161&uo=4",
"trackViewUrl":"https://music.apple.com/us/album/bodysnatchers/1109714933?i=1109715161&uo=4",
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/ba/e4/ac/bae4ac59-3bfa-e4b9-4f4c-03f667324fc0/mzaf_14837742185575446625.plus.aac.p.m4a",
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
"collectionPrice":9.99,
"trackPrice":1.29,
"releaseDate":"2007-10-10T07:00:00Z",
"collectionExplicitness":"notExplicit",
"trackExplicitness":"notExplicit",
"discCount":1,
"discNumber":1,
"trackCount":10,
"trackNumber":2,
"trackTimeMillis":242293,
"country":"USA",
"currency":"USD",
"primaryGenreName":"Alternative",
"isStreamable":true
},
{
"wrapperType":"track",
"kind":"song",
"artistId":657515,
"collectionId":1109714933,
"trackId":1109715168,
"artistName":"Radiohead",
"collectionName":"In Rainbows",
"trackName":"Weird Fishes / Arpeggi",
"collectionCensoredName":"In Rainbows",
"trackCensoredName":"Weird Fishes / Arpeggi",
"artistViewUrl":"https://music.apple.com/us/artist/radiohead/657515?uo=4",
"collectionViewUrl":"https://music.apple.com/us/album/weird-fishes-arpeggi/1109714933?i=1109715168&uo=4",
"trackViewUrl":"https://music.apple.com/us/album/weird-fishes-arpeggi/1109714933?i=1109715168&uo=4",
"previewUrl":"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/6c/e9/79/6ce9792e-c06a-b49b-6efe-60b96a690af8/mzaf_5478326228427438939.plus.aac.p.m4a",
"artworkUrl30":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/30x30bb.jpg",
"artworkUrl60":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/60x60bb.jpg",
"artworkUrl100":"https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/9a/4f/8a/9a4f8a4b-0254-d5ab-74b5-ebe39bbbe85d/634904032463.png/100x100bb.jpg",
"collectionPrice":9.99,
"trackPrice":1.29,
"releaseDate":"2007-10-10T07:00:00Z",
"collectionExplicitness":"notExplicit",
"trackExplicitness":"notExplicit",
"discCount":1,
"discNumber":1,
"trackCount":10,
"trackNumber":4,
"trackTimeMillis":318187,
"country":"USA",
"currency":"USD",
"primaryGenreName":"Alternative",
"isStreamable":true
}
]
}
```

View File

@ -0,0 +1,53 @@
+++
title = "HTTP Status Codes"
weight = 40
+++
## {{% expand title="1xx Informational" %}}
This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and is terminated by an empty line. There are no required headers for this class of status code. Since HTTP/1.0 did not define any 1xx status codes, servers MUST NOT send a 1xx response to an HTTP/1.0 client except under experimental conditions.
A client MUST be prepared to accept one or more 1xx status responses prior to a regular response, even if the client does not expect a 100 (Continue) status message. Unexpected 1xx status responses MAY be ignored by a user agent.
Proxies MUST forward 1xx responses, unless the connection between the proxy and its client has been closed, or unless the proxy itself requested the generation of the 1xx response. (For example, if a proxy adds a "Expect: 100-continue" field when it forwards a request, then it need not forward the corresponding 100 (Continue) response(s).)
### Wikipedia
Request received, continuing process.
This class of status code indicates a provisional response, consisting only of the Status-Line and optional headers, and is terminated by an empty line. Since HTTP/1.0 did not define any 1xx status codes, servers must not send a 1xx response to an HTTP/1.0 client except under experimental conditions.
{{% /expand %}}
## {{% expand title="2xx Success" %}}
This class of status code indicates that the client's request was successfully received, understood, and accepted.
### Wikipedia
This class of status codes indicates the action requested by the client was received, understood, accepted and processed successfully.
{{% /expand %}}
## {{% expand title="3xx Redirection" %}}
This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request. The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD. A client SHOULD detect infinite redirection loops, since such loops generate network traffic for each redirection.
> __Note:__ previous versions of this specification recommended a maximum of five redirections. Content developers should be aware that there might be clients that implement such a fixed limitation.
### Wikipedia
The client must take additional action to complete the request.
This class of status code indicates that further action needs to be taken by the user agent in order to fulfil the request. The action required may be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD. A user agent should not automatically redirect a request more than five times, since such redirections usually indicate an infinite loop.
{{% /expand %}}
## {{% expand title="4xx Client Error" %}}
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents SHOULD display any included entity to the user.
If the client is sending data, a server implementation using TCP SHOULD be careful to ensure that the client acknowledges receipt of the packet(s) containing the response, before the server closes the input connection. If the client continues sending data to the server after the close, the server's TCP stack will send a reset packet to the client, which may erase the client's unacknowledged input buffers before they can be read and interpreted by the HTTP application.
### Wikipedia
The 4xx class of status code is intended for cases in which the client seems to have erred. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. These status codes are applicable to any request method. User agents should display any included entity to the user.
{{% /expand %}}
## {{% expand title="5xx Server Error" %}}
Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. User agents SHOULD display any included entity to the user. These response codes are applicable to any request method.
### Wikipedia
The server failed to fulfill an apparently valid request.
Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has encountered an error or is otherwise incapable of performing the request. Except when responding to a HEAD request, the server should include an entity containing an explanation of the error situation, and indicate whether it is a temporary or permanent condition. Likewise, user agents should display any included entity to the user. These response codes are applicable to any request method.
{{% /expand %}}

View File

@ -0,0 +1,28 @@
+++
title = "Resources"
weight = 50
+++
# REST API Resources
## Translations
* [Russian](http://www.restapitutorial.ru/)
## REST API Cheat Sheets
* [API Design Cheat Sheet](https://github.com/RestCheatSheet/api-cheat-sheet#api-design-cheat-sheet) - This GitHub repository outlines important tips to consider when designing APIs that developers love.
* [Platform-Building Cheat Sheet](https://github.com/RestCheatSheet/platform-cheat-sheet#platform-building-cheat-sheet) - Everyone wants to build a platform. This GitHub repository is a public receptical of ground rules when building a platform.
## REST API Best Practices
Get the RESTful Design Best Practices guide (choose your format). This guide reduces the world of RESTful services design into easy-to-follow principles. It also provides several cookbook type recipes in critical areas to increase service usability, reduce confusion during implemenation, as well as improve consistency.
* [PDF](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.pdf) (~306KB)
* [ePub](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.epub) (~46KB). Works on iPad, iPhone, B&N Nook and most other readers.
* [Mobi](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.mobi) (~86KB). Works on Kindle, Kindle Reader Apps
* [Source Document in Libre/Open Office format](https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.odt) (~48KB)
## Building REST APIs in Java
[RestExpress](https://github.com/RestExpress/RestExpress) (GitHub). A lightweight microservices framework for Java, RestExpress composes best-of-breed tools to form a lightweight, minimalist Java framework for quickly creating RESTful APIs.
## Web Resources
* [REST API Tutorial YouTube Channel](https://www.youtube.com/user/restapitutorial) - The companion channel where all of the videos for this site live.
* [Sascha Preibisch YouTube Channel](https://www.youtube.com/channel/UCBSlXL7WCE-MR8uuwurqVKA) - A great resource on Security; Particularly Oauth2 and OpenID Connect (OIDC).
* [Todd Fredrich's Blog](http://www.toddfredrich.com/)

View File

@ -1,30 +0,0 @@
<html>
<head>
<title>Moved to new URL: https://www.restapitutorial.com/lessons/httpmethods.html</title>
<meta http-equiv=refresh content="0; url=https://www.restapitutorial.com/lessons/httpmethods.html" />
<meta name="robots" content="noindex,follow" />
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<h1>This page has been moved to https://www.restapitutorial.com/lessons/httpmethods.html</h1>
<p>If your browser doesn't redirect you to the new location please
<a href="https://www.restapitutorial.com/lessons/httpmethods.html"><strong>click here</strong></a>,
sorry for the hassles!</p>
</body>
</html>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Binary file not shown.

View File

@ -1,149 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google Analytics Content Experiment code -->
<script>function utmx_section(){}function utmx(){}(function(){var
k='59305729-0',d=document,l=d.location,c=d.cookie;
if(l.search.indexOf('utm_expid='+k)>0)return;
function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.
indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.
length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write(
'<sc'+'ript src="'+'http'+(l.protocol=='https:'?'s://ssl':
'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+
'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().
valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+
'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();
</script><script>utmx('url','A/B');</script>
<!-- End of Google Analytics Content Experiment code -->
<meta charset="utf-8">
<title>REST API Tutorial</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="The REST API Tutorial. Learn REST API best practices.">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.banner-container {
}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span10 offset2 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial Responsive -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span2">
<ul class="nav nav-list">
<li class="active"><a href="https://www.restapitutorial.com">Home</a></li>
<ul class="nav nav-list">
<li><a href="lessons/whatisrest.html">What Is REST?</a></li>
<li><a href="lessons/restquicktips.html">REST Quick Tips</a></li>
<li><a href="lessons/httpmethods.html">HTTP Methods</a></li>
<li><a href="lessons/restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="lessons/idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="resources.html">Resources</a></li>
</ul>
</div>
<!-- Main hero unit for a primary marketing message or call to action -->
<div class="span10">
<div class="hero-unit">
<h1>Learn <abbr title="Representational State Transfer">REST</abbr>: A RESTful Tutorial</h1>
<p><strong>Hey, Fellow REST API Designer!</strong></p>
<p>Building RESTful web services, like other programming skills is <strong>part art, part science</strong>. As the Internet industry progresses, creating a REST API becomes more concrete with emerging best practices. As RESTful web services don't follow a prescribed standard except for HTTP, it's important to build your RESTful API in accordance with industry best practices to ease development and increase client adoption.</p>
<p>Presently, there aren't a lot of REST API guides to help the lonely developer. <a href="https://www.restapitutorial.com">RestApiTutorial.com</a> is dedicated to tracking REST API best practices and making resources available to enable quick reference and self education for the development crafts-person. We'll discuss both the art and science of creating REST Web services.</p>
<p>&mdash;Todd Fredrich, <em>The REST API Tutor</em></p>
<p>Jump in with <a href="lessons/whatisrest.html">What Is REST?</a>, an overview of concepts and constraints of the RESTful architecture.</p>
<p><a class="btn btn-primary btn-large" href="lessons/whatisrest.html">Next &raquo;</a></p>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div>
</div> <!-- /row -->
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="https://www.restapitutorial.com">Home</a></li>
<li class="dropdown" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="lessons/whatisrest.html">What Is REST?</a></li>
<li><a href="lessons/restquicktips.html">REST Quick Tips</a></li>
<li><a href="lessons/httpmethods.html">HTTP Methods</a></li>
<li><a href="lessons/restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="lessons/idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,240 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>HTTP Methods for RESTful Services</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="HTTP methods tutorial on how to use them for RESTful API or Web Service.">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span8">
<h1>Using HTTP Methods for RESTful Services</h1>
</div>
<div class="span4">
<ul class="pager">
<li>
<a href="restquicktips.html"><i class="icon-step-backward"></i> Quick-Tips</a>
</li>
<li>
<a href="restfulresourcenaming.html">Resource Naming <i class="icon-step-forward"></i></a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span12">
<p>The HTTP verbs comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, PATCH, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other verbs, too, but are utilized less frequently. Of those less-frequent methods, OPTIONS and HEAD are used more often than others.</p>
<p>Below is a table summarizing recommended return values of the primary HTTP methods in combination with the resource URIs:</p>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>HTTP Verb</th>
<th>CRUD</th>
<th>Entire Collection (e.g. /customers)</th>
<th>Specific Item (e.g. /customers/{id})</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>Create</td>
<td>201 (Created), 'Location' header with link to /customers/{id} containing new ID.</td>
<td>404 (Not Found), 409 (Conflict) if resource already exists..</td>
</tr>
<tr>
<td>GET</td>
<td>Read/Retrieve</td>
<td>200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists.</td>
<td>200 (OK), single customer. 404 (Not Found), if ID not found or invalid.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update/Replace</td>
<td>405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection.</td>
<td>200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Update/Modify</td>
<td>405 (Method Not Allowed), unless you want to modify the collection itself.</td>
<td>200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete</td>
<td>405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable.</td>
<td>200 (OK). 404 (Not Found), if ID not found or invalid.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="span12">
<p>Below is a more-detailed discussion of the main HTTP methods. Click on a tab for more information about the desired HTTP method.</p>
<ul class="nav nav-tabs">
<li class="active"><a href="#post" data-toggle="tab">POST</a></li>
<li><a href="#get" data-toggle="tab">GET</a></li>
<li><a href="#put" data-toggle="tab">PUT</a></li>
<li><a href="#patch" data-toggle="tab">PATCH</a></li>
<li><a href="#delete" data-toggle="tab">DELETE</a></li>
</ul>
<div id="methodTabContent" class="tab-content">
<div class="tab-pane fade in active" id="post">
<p>The POST verb is most-often utilized to **create** new resources. In particular, it's used to create subordinate resources. That is, subordinate to some other (e.g. parent) resource. In other words, when creating a new resource, POST to the parent and the service takes care of associating the new resource with the parent, assigning an ID (new resource URI), etc.</p>
<p>On successful creation, return HTTP status 201, returning a Location header with a link to the newly-created resource with the 201 HTTP status.</p>
<p>POST is neither safe nor idempotent. It is therefore recommended for non-idempotent resource requests. Making two identical POST requests will most-likely result in two resources containing the same information.</p>
<p><strong>Examples:</strong></p>
<ul>
<li><em>POST http://www.example.com/customers</em></li>
<li><em>POST http://www.example.com/customers/12345/orders</em></li>
</ul>
</div>
<div class="tab-pane fade" id="get">
<p>The HTTP GET method is used to **read** (or retrieve) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).</p>
<p>According to the design of the HTTP specification, GET (along with HEAD) requests are used only to read data and not change it. Therefore, when used this way, they are considered safe. That is, they can be called without risk of data modification or corruption—calling it once has the same effect as calling it 10 times, or none at all. Additionally, GET (and HEAD) is idempotent, which means that making multiple identical requests ends up having the same result as a single request.</p>
<p>Do not expose unsafe operations via GET—it should never modify any resources on the server.</p>
<p><strong>Examples:</strong></p>
<ul>
<li><em>GET http://www.example.com/customers/12345</em></li>
<li><em>GET http://www.example.com/customers/12345/orders</em></li>
<li><em>GET http://www.example.com/buckets/sample</em></li>
</ul>
</div>
<div class="tab-pane fade" id="put">
<p>PUT is most-often utilized for **update** capabilities, PUT-ing to a known resource URI with the request body containing the newly-updated representation of the original resource.</p>
<p>However, PUT can also be used to create a resource in the case where the resource ID is chosen by the client instead of by the server. In other words, if the PUT is to a URI that contains the value of a non-existent resource ID. Again, the request body contains a resource representation. Many feel this is convoluted and confusing. Consequently, this method of creation should be used sparingly, if at all.</p>
<p>Alternatively, use POST to create new resources and provide the client-defined ID in the body representation—presumably to a URI that doesn't include the ID of the resource (see POST below).</p>
<p>On successful update, return 200 (or 204 if not returning any content in the body) from a PUT. If using PUT for create, return HTTP status 201 on successful creation. A body in the response is optional—providing one consumes more bandwidth. It is not necessary to return a link via a Location header in the creation case since the client already set the resource ID.</p>
<p>PUT is not a safe operation, in that it modifies (or creates) state on the server, but it is idempotent. In other words, if you create or update a resource using PUT and then make that same call again, the resource is still there and still has the same state as it did with the first call.</p>
<p>If, for instance, calling PUT on a resource increments a counter within the resource, the call is no longer idempotent. Sometimes that happens and it may be enough to document that the call is not idempotent. However, it's recommended to keep PUT requests idempotent. It is strongly recommended to use POST for non-idempotent requests.</p>
<p><strong>Examples:</strong></p>
<ul>
<li><em>PUT http://www.example.com/customers/12345</em></li>
<li><em>PUT http://www.example.com/customers/12345/orders/98765</em></li>
<li><em>PUT http://www.example.com/buckets/secret_stuff</em></li>
</ul>
</div>
<div class="tab-pane fade" id="patch">
<p>PATCH is used for **modify** capabilities. The PATCH request only needs to contain the changes to the resource, not the complete resource.</p>
<p>This resembles PUT, but the body contains a set of instructions describing how a resource currently residing on the server should be modified to produce a new version. This means that the PATCH body should not just be a modified part of the resource, but in some kind of patch language like JSON Patch or XML Patch.</p>
<p>PATCH is neither safe nor idempotent. However, a PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame. Collisions from multiple PATCH requests may be more dangerous than PUT collisions because some patch formats need to operate from a known base-point or else they will corrupt the resource. Clients using this kind of patch application should use a conditional request such that the request will fail if the resource has been updated since the client last accessed the resource. For example, the client can use a strong ETag in an If-Match header on the PATCH request.</p>
<p><strong>Examples:</strong></p>
<ul>
<li><em>PATCH http://www.example.com/customers/12345</em></li>
<li><em>PATCH http://www.example.com/customers/12345/orders/98765</em></li>
<li><em>PATCH http://www.example.com/buckets/secret_stuff</em></li>
</ul>
</div>
<div class="tab-pane fade" id="delete">
<p>DELETE is pretty easy to understand. It is used to **delete** a resource identified by a URI.
<p>On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the representation of the deleted item (often demands too much bandwidth), or a wrapped response (see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no response body. In other words, a 204 status with no body, or the JSEND-style response and HTTP status 200 are the recommended responses.</p>
<p>HTTP-spec-wise, DELETE operations are idempotent. If you DELETE a resource, it's removed. Repeatedly calling DELETE on that resource ends up the same: the resource is gone. If calling DELETE say, decrements a counter (within the resource), the DELETE call is no longer idempotent. As mentioned previously, usage statistics and measurements may be updated while still considering the service idempotent as long as no resource data is changed. Using POST for non-idempotent resource requests is recommended.</p>
<p>There is a caveat about DELETE idempotence, however. Calling DELETE on a resource a second time will often return a 404 (NOT FOUND) since it was already removed and therefore is no longer findable. This, by some opinions, makes DELETE operations no longer idempotent, however, the end-state of the resource is the same. Returning a 404 is acceptable and communicates accurately the status of the call.</p>
<p><strong>Examples:</strong></p>
<ul>
<li><em>DELETE http://www.example.com/customers/12345</em></li>
<li><em>DELETE http://www.example.com/customers/12345/orders</em></li>
<li><em>DELETE http://www.example.com/bucket/sample</em></li>
</ul>
</div>
</div>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.RestApiTutorial.com" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="../index.html">Home</a></li>
<li class="dropdown active" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="whatisrest.html">What Is REST?</a></li>
<li><a href="restquicktips.html">REST Quick Tips</a></li>
<li class="active"><a href="httpmethods.html">HTTP Methods</a></li>
<li><a href="restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="../httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="../resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,140 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>What is Idempotency?</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Idempotency or Idempotence, definition in a non-academic way, specifically in REST APIs">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span7">
<h1>What Is Idempotence?</h1>
</div>
<div class="span5">
<ul class="pager">
<li>
<a href="restfulresourcenaming.html"><i class="icon-step-backward"></i> Resource Naming</a>
</li>
<li>
<a href="../httpstatuscodes.html">HTTP Status Codes <i class="icon-step-forward"></i></a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span12">
<i class="icon-film"></i> <a href="#" data-toggle="collapse" data-target="#video1">Hide/Show Video</a>
</div>
</div>
<div id="video1" class="row collapse in">
<div class="span12">
<iframe width="853" height="480" src="https://www.youtube.com/embed/6dVNdFwqeKs" frameborder="0" allowfullscreen></iframe>
</div>
</div>
<div class="row">
<div class="span12">
<h2>Idempotence</h2>
</div>
<div class="span12">
<p>Idempotence is a funky word that often hooks people. Idempotence is sometimes a confusing concept, at least from the academic definition.</p>
<p>From a RESTful service standpoint, for an operation (or service call) to be idempotent, clients can make that same call repeatedly while producing the same result. In other words, making multiple identical requests has the same effect as making a single request. Note that while idempotent operations produce the same result on the server (no side effects), the response itself may not be the same (e.g. a resource's state may change between requests).</p>
<p>The PUT and DELETE methods are defined to be idempotent. However, there is a caveat on DELETE. The problem with DELETE, which if successful would normally return a 200 (OK) or 204 (No Content), will often return a 404 (Not Found) on subsequent calls, unless the service is configured to "mark" resources for deletion without actually deleting them. However, when the service actually deletes the resource, the next call will not find the resource to delete it and return a 404. However, the state on the server is the same after each DELETE call, but the response is different.</p>
<p>GET, HEAD, OPTIONS and TRACE methods are defined as safe, meaning they are only intended for retrieving data. This makes them idempotent as well since multiple, identical requests will behave the same.</p>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="../index.html">Home</a></li>
<li class="dropdown active" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="whatisrest.html">What Is REST?</a></li>
<li><a href="restquicktips.html">REST Quick Tips</a></li>
<li><a href="httpmethods.html">HTTP Methods</a></li>
<li><a href="restfulresourcenaming.html">Resource Naming</a></li>
<li class="active"><a href="idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="../httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="../resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,213 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>RESTful Resource Naming</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Naming Tutorial: RESTful services are resource-based. How do you create those noun-based resource names? Here's how...">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span8">
<h1>Resource Naming</h1>
</div>
<div class="span4">
<ul class="pager">
<li>
<a href="httpmethods.html"><i class="icon-step-backward"></i> HTTP Methods</a>
</li>
<li>
<a href="idempotency.html">Idempotence <i class="icon-step-forward"></i></a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span12">
<p>In addition to utilizing the HTTP verbs appropriately, resource naming is arguably the most debated and most important concept to grasp when creating an understandable, easily leveraged Web service API. When resources are named well, an API is intuitive and easy to use. Done poorly, that same API can feel klutzy and be difficult to use and understand. Below are a few tips to get you going when creating the resource URIs for your new API.</p>
<p>Essentially, a RESTful API ends up being simply a collection of URIs, HTTP calls to those URIs and some JSON and/or XML representations of resources, many of which will contain relational links. The RESTful principal of addressability is covered by the URIs. Each resource has its own address or URI—every interesting piece of information the server can provide is exposed as a resource. The constraint of uniform interface is partially addressed by the combination of URIs and HTTP verbs, and using them in line with the standards and conventions.</p>
<p>In deciding what resources are within your system, name them as nouns as opposed to verbs or actions. In other words, a RESTful URI should refer to a resource that is a thing instead of referring to an action. Nouns have properties as verbs do not, just another distinguishing factor.</p>
<p>Some example resources are:</p>
<ul>
<li>Users of the system.</li>
<li>Courses in which a student is enrolled.</li>
<li>A user's timeline of posts.</li>
<li>The users that follow another user.</li>
<li>An article about horseback riding.</li>
</ul>
<p>Each resource in a service suite will have at least one URI identifying it. And it's best when that URI makes sense and adequately describes the resource. URIs should follow a predictable, hierarchical structure to enhance understandability and, therefore, usability: predictable in the sense that they're consistent, hierarchical in the sense that data has structure—relationships. This is not a REST rule or constraint, but it enhances the API.</p>
<p>RESTful APIs are written for consumers. The name and structure of URIs should convey meaning to those consumers. It's often difficult to know what the data boundaries should be, but with understanding of your data, you most-likely are equipped to take a stab and what makes sense to return as a representation to your clients. Design for your clients, not for your data.</p>
<p>Let's say we're describing an order system with customers, orders, line items, products, etc. Consider the URIs involved in describing the resources in this service suite:</p>
</div>
</div>
<div class="row">
<div class="span12">
<ul class="nav nav-tabs">
<li class="active"><a href="#examples" data-toggle="tab">Resource URI Examples</a></li>
<li><a href="#antipatterns" data-toggle="tab">Resource Naming Anti-Patterns</a></li>
<li><a href="#pluralization" data-toggle="tab">Pluralization</a></li>
</ul>
<div id="namingTabContent" class="tab-content">
<div class="tab-pane fade in active" id="examples">
<p>To insert (create) a new customer in the system, we might use:<br/>
<em>POST http://www.example.com/customers</em></p>
<p>To read a customer with Customer ID# 33245:<br/>
<em>GET http://www.example.com/customers/33245</em>
The same URI would be used for PUT and DELETE, to update and delete, respectively.</p>
<p>Here are proposed URIs for products:<br/>
<em>POST http://www.example.com/products</em>
for creating a new product.</p>
<p><em>GET|PUT|DELETE http://www.example.com/products/66432</em><br/>
for reading, updating, deleting product 66432, respectively.</p>
<p>Now, here is where it gets fun... What about creating a new order for a customer? One option might be: POST http://www.example.com/orders And that could work to create an order, but it's arguably outside the context of a customer.</p>
<p>Because we want to create an order for a customer (note the relationship), this URI perhaps is not as intuitive as it could be. It could be argued that the following URI would offer better clarity: <em>POST http://www.example.com/customers/33245/orders</em> Now we know we're creating an order for customer ID# 33245.</p>
<p>Now what would the following return?<br/>
<em>GET http://www.example.com/customers/33245/orders</em><br/>
Probably a list of orders that customer #33245 has created or owns. Note: we may choose to not support DELETE or PUT for that url since it's operating on a collection.</p>
<p>Now, to continue the hierarchical concept, what about the following URI?<br/>
<em>POST http://www.example.com/customers/33245/orders/8769/lineitems</em><br/>
That might add a line item to order #8769 (which is for customer #33245). Right! GET for that URI might return all the line items for that order. However, if line items don't make sense only in customer context or also make sense outside the context of a customer, we would offer a POST www.example.com/orders/8769/lineitems URI.</p>
<p>Along those lines, because there may be multiple URIs for a given resource, we might also offer a GET http://www.example.com/orders/8769 URI that supports retrieving an order by number without having to know the customer number.</p>
<p>To go one layer deeper in the hierarchy:<br/>
<em>GET http://www.example.com/customers/33245/orders/8769/lineitems/1</em><br/>
Might return only the first line item in that same order.</p>
<p>By now you can see how the hierarchy concept works. There aren't any hard and fast rules, only make sure the imposed structure makes sense to consumers of your services. As with everything in the craft of Software Development, naming is critical to success.</p>
<p>Look at some widely used APIs to get the hang of this and leverage the intuition of your teammates to refine your API resource URIs. Some example APIs are:</p>
<ul>
<li>Twitter: https://developer.twitter.com/en/docs/api-reference-index</li>
<li>Facebook: https://developers.facebook.com/docs/reference/api/</li>
<li>LinkedIn: https://developer.linkedin.com/apis</li>
</ul>
</div>
<div class="tab-pane fade" id="antipatterns">
<p>While we've discussed some examples of appropriate resource names, sometimes it's informative to see some anti-patterns. Below are some examples of poor RESTful resource URIs seen in the &quot;wild.&quot; These are examples of what not to do!</p>
<p>First up, often services use a single URI to specify the service interface, using query-string parameters to specify the requested operation and/or HTTP verb. For example to update customer with ID 12345, the request for a JSON body might be:</p>
<p><em>GET http://api.example.com/services?op=update_customer&id=12345&format=json</em></p>
<p>By now, you're above doing this. Even though the 'services' URL node is a noun, this URL is not self- descriptive as the URI hierarchy is the same for all requests. Plus, it uses GET as the HTTP verb even though we're performing an update. This is counter-intuitive and is painful (even dangerous) to use as a client.</p>
<p>Here's another example following the same operation of updating a customer:</p>
<p><em>GET http://api.example.com/update_customer/12345</em></p>
<p>And its evil twin:</p>
<p><em>GET http://api.example.com/customers/12345/update</em></p>
<p>You'll see this one a lot as you visit other developer's service suites. Note that the developer is attempting to create RESTful resource names and has made some progress. But you're better than this —able to identify the verb phrase in the URL. Notice that we don't need to use the 'update' verb phrase in the URL because we can rely on the HTTP verb to inform that operation. Just to clarify, the following resource URL is redundant:</p>
<p><em>PUT http://api.example.com/customers/12345/update</em></p>
<p>With both PUT and 'update' in the request, we're offering to confuse our service consumers! Is 'update' the resource? So, we've spent some time beating the horse at this point. I'm certain you understand...</p>
</div>
<div class="tab-pane fade" id="pluralization">
<p>Let's talk about the debate between the pluralizers and the &quot;singularizers&quot;... Haven't heard of that debate? It does exist. Essentially, it boils down to this question...</p>
<p>Should URI nodes in your hierarchy be named using singular or plural nouns? For example, should your URI for retrieving a representation of a customer resource look like this:</p>
<p><em>GET http://www.example.com/customer/33245</em> or:
<em>GET http://www.example.com/customers/33245</em></p>
<p>There are good arguments on both sides, but the commonly-accepted practice is to always use plurals in node names to keep your API URIs consistent across all HTTP methods. The reasoning is based on the concept that customers are a collection within the service suite and the ID (e.g. 33245) refers to one of those customers in the collection.</p>
<p>Using this rule, an example multi-node URI using pluralization would look like (emphasis added):</p>
<p><em>GET http://www.example.com/<strong>customers</strong>/33245/<strong>orders</strong>/8769/<strong>lineitems</strong>/1</em></p>
<p>with 'customers', 'orders', and 'lineitems' URI nodes all being their plural forms.</p>
<p>This implies that you only really need two base URLs for each root resource. One for creation of the resource within a collection and the second for reading, updating and deleting the resource by its identifier. For example the creation case, using customers as the example, is handled by the following URL:</p>
<p><em>POST http://www.example.com/customers</em></p>
<p>And the read, update and delete cases are handled by the following:</p>
<p><em>GET|PUT|DELETE http://www.example.com/customers/{id}</em></p>
<p>As mentioned earlier, there may be multiple URIs for a given resource, but as a minimum full CRUD capabilities are aptly handled with two simple URIs.</p>
<p>You ask if there is a case where pluralization doesn't make sense. Well, yes, in fact there is. When there isn't a collection concept in play. In other words, it's acceptable to use a singularized resource name when there can only be one of the resource—it's a singleton resource. For example, if there was a single, overarching configuration resource, you might use a singularized noun to represent that:</p>
<p><em>GET|PUT|DELETE http://www.example.com/configuration</em></p>
<p>Note the lack of a configuration ID and usage of POST verb. And say that there was only one configuration per customer, then the URL might be:</p>
<p><em>GET|PUT|DELETE http://www.example.com/customers/12345/configuration</em></p>
<p>Again, no ID for the configuration and no POST verb usage. Although, I'm sure that in both of these cases POST usage might be argued to be valid. Well... OK.</p>
</div>
</div>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="../index.html">Home</a></li>
<li class="dropdown active" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="whatisrest.html">What Is REST?</a></li>
<li><a href="restquicktips.html">REST Quick Tips</a></li>
<li><a href="httpmethods.html">HTTP Methods</a></li>
<li class="active"><a href="restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="../httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="../resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,208 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>RESTful Services Quick Tips</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="RESTful API or Web Service Quick Tips. Want to learn the high points of creating a REST API? Here's the Web Services in 60-seconds version.">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span8">
<h1>REST API Quick Tips</h1>
</div>
<div class="span4">
<ul class="pager">
<li>
<a href="whatisrest.html"><i class="icon-step-backward"></i> What is REST?</a>
</li>
<li>
<a href="httpmethods.html">HTTP Methods <i class="icon-step-forward"></i></a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span12">
<p>Whether it's technically RESTful or not (according to the six constraints mentioned previously), here are a few recommended REST-like concepts. These six quick tips will result in better, more usable services.</p>
<h2>Use HTTP Verbs to Make Your Requests Mean Something</h2>
<p>API consumers are capable of sending GET, POST, PUT, and DELETE verbs, which greatly enhance the clarity of a given request.</p>
<p>Generally, the four primary HTTP verbs are used as follows:
<dl>
<dt>GET</dt>
<dd>Read a specific resource (by an identifier) or a collection of resources.</dd>
<dt>PUT</dt>
<dd>Update a specific resource (by an identifier) or a collection of resources. Can also be used to create a specific resource if the resource identifier is known before-hand.</dd>
<dt>DELETE</dt>
<dd>Remove/delete a specific resource by an identifier.</dd>
<dt>POST</dt>
<dd>Create a new resource. Also a catch-all verb for operations that don't fit into the other categories.</dd>
</dl>
</p>
<h3>Note</h3>
<p>
GET requests must not change any underlying resource data. Measurements and tracking which update data may still occur, but the resource data identified by the URI should not change.
</p>
<h2>Provide Sensible Resource Names</h2>
<p>Producing a great API is 80% art and 20% science. Creating a URL hierarchy representing sensible resources is the art part. Having sensible resource names (which are just URL paths, such as /customers/12345/orders) improves the clarity of what a given request does.</p>
<p>Appropriate resource names provide context for a service request, increasing understandability of the API. Resources are viewed hierarchically via their URI names, offering consumers a friendly, easily-understood hierarchy of resources to leverage in their applications.</p>
<p>Here are some quick-hit rules for URL path (resource name) design:
<ul>
<li>Use identifiers in your URLs instead of in the query-string. Using URL query-string parameters is fantastic for filtering, but not for resource names.
<ul><li><strong>Good:</strong> /users/12345</li><li><strong>Poor:</strong> /api?type=user&amp;id=23</li></ul></li>
<li>Leverage the hierarchical nature of the URL to imply structure.</li>
<li>Design for your clients, not for your data.</li>
<li>Resource names should be nouns. Avoid verbs as resource names, to improve clarity. Use the HTTP methods to specify the verb portion of the request.</li>
<li>Use plurals in URL segments to keep your API URIs consistent across all HTTP methods, using the collection metaphor.
<ul><li><strong>Recommended:</strong> /customers/33245/orders/8769/lineitems/1</li><li><strong>Not:</strong> /customer/33245/order/8769/lineitem/1</li></ul></li>
<li>Avoid using collection verbiage in URLs. For example 'customer_list' as a resource. Use pluralization to indicate the collection metaphor (e.g. customers vs. customer_list).</li>
<li>Use lower-case in URL segments, separating words with underscores ('_') or hyphens ('-'). Some servers ignore case so it's best to be clear.</li>
<li>Keep URLs as short as possible, with as few segments as makes sense.</li>
</ul>
</p>
<h2>Use HTTP Response Codes to Indicate Status</h2>
<p>Response status codes are part of the HTTP specification. There are quite a number of them to address the most common situations. In the spirit of having our RESTful services embrace the HTTP specification, our Web APIs should return relevant HTTP status codes. For example, when a resource is successfully created (e.g. from a POST request), the API should return HTTP status code 201. A list of valid <a href="https://www.restapitutorial.com/httpstatuscodes.html">HTTP status codes</a> is available <a href="https://www.restapitutorial.com/httpstatuscodes.html">here</a> which lists detailed descriptions of each.</p>
<p>Suggested usages for the &quot;Top 10&quot; HTTP Response Status Codes are as follows:
<dl>
<dt>200 OK</dt>
<dd>General success status code. This is the most common code. Used to indicate success.</dd>
<dt>201 CREATED</dt>
<dd>Successful creation occurred (via either POST or PUT). Set the Location header to contain a link to the newly-created resource (on POST). Response body content may or may not be present.</dd>
<dt>204 NO CONTENT</dt>
<dd>Indicates success but nothing is in the response body, often used for DELETE and PUT operations.</dd>
<dt>400 BAD REQUEST</dt>
<dd>General error for when fulfilling the request would cause an invalid state. Domain validation errors, missing data, etc. are some examples.</dd>
<dt>401 UNAUTHORIZED</dt>
<dd>Error code response for missing or invalid authentication token.</dd>
<dt>403 FORBIDDEN</dt>
<dd>Error code for when the user is not authorized to perform the operation or the resource is unavailable for some reason (e.g. time constraints, etc.).</dd>
<dt>404 NOT FOUND</dt>
<dd>Used when the requested resource is not found, whether it doesn't exist or if there was a 401 or 403 that, for security reasons, the service wants to mask.</dd>
<dt>405 METHOD NOT ALLOWED</dt>
<dd>Used to indicate that the requested URL exists, but the requested HTTP method is not applicable. For example, POST <em>/users/12345</em> where the API doesn't support creation of resources this way (with a provided ID). The Allow HTTP header must be set when returning a 405 to indicate the HTTP methods that are supported. In the previous case, the header would look like "Allow: GET, PUT, DELETE"</dd>
<dt>409 CONFLICT</dt>
<dd>Whenever a resource conflict would be caused by fulfilling the request. Duplicate entries, such as trying to create two customers with the same information, and deleting root objects when cascade-delete is not supported are a couple of examples.</dd>
<dt>500 INTERNAL SERVER ERROR</dt>
<dd>Never return this intentionally. The general catch-all error when the server-side throws an exception. Use this only for errors that the consumer cannot address from their end.</dd>
</dl>
</p>
<h2>Offer Both JSON and XML</h2>
<p>Favor JSON support unless you're in a highly-standardized and regulated industry that requires XML, schema validation and namespaces, and offer both JSON and XML unless the costs are staggering. Ideally, let consumers switch between formats using the HTTP Accept header, or by just changing an extension from .xml to .json on the URL.</p>
<p>Be aware that as soon as we start talking about XML support, we start talking about schemas for validation, namespaces, etc. Unless required by your industry, avoid supporting all that complexity initially, if ever. JSON is designed to be simple, terse and functional. Make your XML look like that if you can.</p>
<p>In other words, make the XML that is returned more JSON-like &mdash; simple and easy to read, without the schema and namespace details present, just data and links. If it ends up being more complex than this, the cost of XML will be staggering. In my experience no one has used XML responses anyway for the last several years, it's just too expensive to consume.</p>
<p>Note that <a href="https://json-schema.org/">JSON-Schema</a> offers schema-style validation capabilities, if you need that sort of thing.</p>
<h2>Create Fine-Grained Resources</h2>
<p>When starting out, it's best to create APIs that mimic the underlying application domain or database architecture of your system. Eventually, you'll want aggregate services that utilize multiple underlying resources to reduce chattiness. However, it's much easier to create larger resources later from individual resources than it is to create fine-grained or individual resources from larger aggregates. Make it easy on yourself and start with small, easily defined resources, providing CRUD functionality on those. You can create those use-case-oriented, chattiness-reducing resources later.</p>
<h2>Consider Connectedness</h2>
<p>One of the principles of REST is connectedness—via hypermedia links (search HATEOAS). While services are still useful without them, APIs become more self-descriptive and discoverable when links are returned in the response. At the very least, a 'self' link reference informs clients how the data was or can be retrieved. Additionally, utilize the HTTP Location header to contain a link on resource creation via POST (or PUT). For collections returned in a response that support pagination, 'first', 'last', 'next' and 'prev' links at a minimum are very helpful.</p>
<p>Regarding linking formats, there are many. The HTTP Web Linking Specification (<a href="https://tools.ietf.org/search/rfc5988">RFC5988</a>) explains a link as follows:
<blockquote>a link is a typed connection between two
resources that are identified by Internationalised Resource
Identifiers (IRIs) [<a href="https://tools.ietf.org/search/rfc3987">RFC3987</a>], and is comprised of:
<ul>
<li>A context IRI,</li>
<li>a link relation type</li>
<li>a target IRI, and</li>
<li>optionally, target attributes.</li>
</ul>
A link can be viewed as a statement of the form &quot;{context IRI} has a
{relation type} resource at {target IRI}, which has {target
attributes}.&quot;</blockquote></p>
<p>At the very least, place links in the HTTP Link header as recommended in the specification, or embrace a JSON representation of this HTTP link style (such as Atom-style links, see: <a href="https://tools.ietf.org/search/rfc4287#section-4.2.7">RFC4287</a>) in your JSON representations. Later, you can layer in more complex linking styles such as <a href="https://stateless.co/hal_specification.html">HAL+JSON</a>, <a href="https://github.com/kevinswiber/siren">Siren</a>, <a href="https://amundsen.com/media-types/collection/">Collection+JSON</a>, and/or <a href="https://json-ld.org/">JSON-LD</a>, etc. as your REST APIs become more mature.</p>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="../index.html">Home</a></li>
<li class="dropdown active" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="whatisrest.html">What Is REST?</a></li>
<li class="active"><a href="restquicktips.html">REST Quick Tips</a></li>
<li><a href="httpmethods.html">HTTP Methods</a></li>
<li><a href="restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="../httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="../resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,182 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>What is REST?</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A tutorial on the six primary REST constraints as explained by Roy Fielding">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span8">
<h1>What Is REST?</h1>
</div>
<div class="span4">
<ul class="pager">
<li>
<a href="../index.html"><i class="icon-step-backward"></i> Home</a>
</li>
<li>
<a href="restquicktips.html">Quick Tips <i class="icon-step-forward"></i></a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span12">
<i class="icon-film"></i> <a href="#" data-toggle="collapse" data-target="#video1">Hide/Show Video</a>
</div>
</div>
<div id="video1" class="row collapse in">
<div class="span12">
<iframe width="853" height="480" src="https://www.youtube.com/embed/llpr5924N7E" frameborder="0" allowfullscreen></iframe>
</div>
</div>
<div class="row">
<div class="span12">
<p>The REST architectural style describes six constraints. These constraints, applied to the architecture, were originally communicated by Roy Fielding in his doctoral dissertation (see <a href="https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm" target="_blank">https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm</a>) and defines the basis of RESTful-style.</p>
<p><strong>The six constraints are: (click the constraint to read more)</strong></p>
<ul id="constraint-accordian">
<li><a data-toggle="collapse" data-target="#uniform-interface" data-parent="#constraint-accordian" href="#">Uniform Interface</a>
<div class="collapse" id="uniform-interface">
<p>The uniform interface constraint defines the interface between clients and servers. It simplifies and decouples the architecture, which enables each part to evolve independently. The four guiding principles of the uniform interface are:</p>
<h3>Resource-Based</h3>
<p>Individual resources are identified in requests using URIs as resource identifiers. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server does not send its database, but rather, some HTML, XML or JSON that represents some database records expressed, for instance, in Finnish and encoded in UTF-8, depending on the details of the request and the server implementation.</p>
<h3>Manipulation of Resources Through Representations</h3>
<p>When a client holds a representation of a resource, including any metadata attached, it has enough information to modify or delete the resource on the server, provided it has permission to do so.</p>
<h3>Self-descriptive Messages</h3>
<p>Each message includes enough information to describe how to process the message. For example, which parser to invoke may be specified by an Internet media type (previously known as a MIME type). Responses also explicitly indicate their cache-ability.</p>
<h3>Hypermedia as the Engine of Application State (HATEOAS)</h3>
<p>Clients deliver state via body contents, query-string parameters, request headers and the requested URI (the resource name). Services deliver state to clients via body content, response codes, and response headers. This is technically referred-to as hypermedia (or hyperlinks within hypertext).</p>
<p>Aside from the description above, HATEOS also means that, where necessary, links are contained in the returned body (or headers) to supply the URI for retrieval of the object itself or related objects. We'll talk about this in more detail later.</p>
<p>The uniform interface that any REST services must provide is fundamental to its design.</p>
</div>
</li>
<li><a data-toggle="collapse" data-target="#stateless" data-parent="#constraint-accordian" href="#">Stateless</a>
<div class="collapse" id="stateless">
<p>As REST is an acronym for REpresentational State Transfer, statelessness is key. Essentially, what this means is that the necessary state to handle the request is contained within the request itself, whether as part of the URI, query-string parameters, body, or headers. The URI uniquely identifies the resource and the body contains the state (or state change) of that resource. Then after the server does it's processing, the appropriate state, or the piece(s) of state that matter, are communicated back to the client via headers, status and response body.</p>
<p>Most of us who have been in the industry for a while are accustomed to programming within a container which provides us with the concept of “session” which maintains state across multiple HTTP requests. In REST, the client must include all information for the server to fulfill the request, resending state as necessary if that state must span multiple requests. Statelessness enables greater scalability since the server does not have to maintain, update or communicate that session state. Additionally, load balancers don't have to worry about session affinity for stateless systems.</p>
<p>So what's the difference between state and a resource? State, or application state, is that which the server cares about to fulfill a request—data necessary for the current session or request. A resource, or resource state, is the data that defines the resource representation—the data stored in the database, for instance. Consider application state to be data that could vary by client, and per request. Resource state, on the other hand, is constant across every client who requests it.</p>
<p>Ever had back-button issues with a web application where it went AWOL at a certain point because it expected you to do things in a certain order? That's because it violated the statelessness principle. There are cases that don't honor the statelessness principle, such as three-legged OAuth, API call rate limiting, etc. However, make every effort to ensure that application state doesn't span multiple requests of your service(s).</p>
</div>
</li>
<li><a data-toggle="collapse" data-target="#cacheable" data-parent="#constraint-accordian" href="#">Cacheable</a>
<div class="collapse" id="cacheable">
<p>As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests. Well-managed caching partially or completely eliminates some clientserver interactions, further improving scalability and performance.</p>
</div>
</li>
<li><a data-toggle="collapse" data-target="#client-server" data-parent="#constraint-accordian" href="#">Client-Server</a>
<div class="collapse" id="client-server">
<p>The uniform interface separates clients from servers. This separation of concerns means that, for example, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface is not altered.</p>
</div>
</li>
<li><a data-toggle="collapse" data-target="#layered-system" data-parent="#constraint-accordian" href="#">Layered System</a>
<div class="collapse" id="layered-system">
<p>A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches. Layers may also enforce security policies.</p>
</div>
</li>
<li><a data-toggle="collapse" data-target="#code-on-demand" data-parent="#constraint-accordian" href="#">Code on Demand (optional)</a>
<div class="collapse" id="code-on-demand">
<p>Servers are able to temporarily extend or customize the functionality of a client by transferring logic to it that it can execute. Examples of this may include compiled components such as Java applets and client-side scripts such as JavaScript.</p>
<p>Complying with these constraints, and thus conforming to the REST architectural style, will enable any kind of distributed hypermedia system to have desirable emergent properties, such as performance, scalability, simplicity, modifiability, visibility, portability and reliability.</p>
<p><strong>NOTE:</strong> The only optional constraint of REST architecture is code on demand. If a service violates any other constraint, it cannot strictly be referred to as RESTful.</p>
</div>
</li>
</ul>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="../index.html">Home</a></li>
<li class="dropdown active" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="active"><a href="whatisrest.html">What Is REST?</a></li>
<li><a href="restquicktips.html">REST Quick Tips</a></li>
<li><a href="httpmethods.html">HTTP Methods</a></li>
<li><a href="restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="../httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="../resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,134 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>RESTful Web Services Resources</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="REST API eBook for Best Practices and other resources, such as open-source REST Service frameworks, etc.">
<meta name="author" content="Todd Fredrich, Pearson eCollege">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span12 banner-container">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Rest API Tutorial -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2093481943685202"
data-ad-slot="4845828438"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="row">
<div class="span12">
<h1>REST API Resources</h1>
<h2>Translations</h2>
<dl>
<dt><a href="https://www.restapitutorial.ru/">Russian</a></dt>
<dd><a href="http://www.restapitutorial.ru/">http://www.restapitutorial.ru/</a></dd>
</dl>
<h2>REST API Cheat Sheets</h2>
<ul>
<li><a href="https://github.com/RestCheatSheet/api-cheat-sheet#api-design-cheat-sheet">API Design Cheat Sheet</a> - This GitHub repository outlines important tips to consider when designing APIs that developers love.</li>
<li><a href="https://github.com/RestCheatSheet/platform-cheat-sheet#platform-building-cheat-sheet">Platform-Building Cheat Sheet</a> - Everyone wants to build a platform. This GitHub repository is a public receptical of ground rules when building a platform.</li>
</ul>
<h2>REST API Best Practices</h2>
<p>Get the <em>RESTful Design Best Practices</em> guide (choose your format). This guide reduces the world of RESTful services design into easy-to-follow principles. It also provides several cookbook type recipes in critical areas to increase service usability, reduce confusion during implemenation, as well as improve consistency.</p>
<ul>
<li><a href="https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.pdf">PDF</a> (~306KB)</li>
<li><a href="https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.epub">ePub</a> (~46KB). Works on iPad, iPhone, B&amp;N Nook and most other readers.</li>
<li><a href="https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.mobi">Mobi</a> (~86KB). Works on Kindle, Kindle Reader Apps</li>
<li><a href="https://github.com/tfredrich/RestApiTutorial.com/raw/master/media/RESTful%20Best%20Practices-v1_2.odt">Source Document in Libre/Open Office format</a> (~48KB)</li>
</ul>
<h2>Building REST APIs in Java</h2>
<p><a href="https://github.com/RestExpress/RestExpress">RestExpress</a> (GitHub). A lightweight microservices framework for Java, RestExpress composes best-of-breed tools to form a lightweight, minimalist Java framework for quickly creating RESTful APIs.</p>
<h2>Web Resources</h2>
<ul>
<li><a href="https://www.youtube.com/user/restapitutorial">REST API Tutorial YouTube Channel</a> - The companion channel where all of the videos for this site live.</li>
<li><a href="https://www.youtube.com/channel/UCBSlXL7WCE-MR8uuwurqVKA">Sascha Preibisch YouTube Channel</a> - A great resource on Security; Particularly Oauth2 and OpenID Connect (OIDC).</li>
<li><a href="http://www.toddfredrich.com">Todd Fredrich's Blog</a></li>
</ul>
</div>
</div>
<hr>
<footer>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="https://creativecommons.org/ns#" href="https://www.restapitutorial.com/" property="cc:attributionName" rel="cc:attributionURL">RestApiTutorial.com</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.</p>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="https://www.restapitutorial.com">Home</a></li>
<li class="dropdown" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="lessons/whatisrest.html">What Is REST?</a></li>
<li><a href="lessons/restquicktips.html">REST Quick Tips</a></li>
<li><a href="lessons/httpmethods.html">HTTP Methods</a></li>
<li><a href="lessons/restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="lessons/idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="httpstatuscodes.html">HTTP Status Codes</a></li>
<li class="active"><a href="resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,167 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google Analytics Content Experiment code -->
<script>function utmx_section(){}function utmx(){}(function(){var
k='59305729-0',d=document,l=d.location,c=d.cookie;
if(l.search.indexOf('utm_expid='+k)>0)return;
function f(n){if(c){var i=c.indexOf(n+'=');if(i>-1){var j=c.
indexOf(';',i);return escape(c.substring(i+n.length+1,j<0?c.
length:j))}}}var x=f('__utmx'),xx=f('__utmxx'),h=l.hash;d.write(
'<sc'+'ript src="'+'http'+(l.protocol=='https:'?'s://ssl':
'://www')+'.google-analytics.com/ga_exp.js?'+'utmxkey='+k+
'&utmx='+(x?x:'')+'&utmxx='+(xx?xx:'')+'&utmxtime='+new Date().
valueOf()+(h?'&utmxhash='+escape(h.substr(1)):'')+
'" type="text/javascript" charset="utf-8"><\/sc'+'ript>')})();
</script><script>utmx('url','A/B');</script>
<!-- End of Google Analytics Content Experiment code -->
<meta charset="utf-8">
<title>REST API Questions</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Enter your most-pressing REST API question">
<meta name="author" content="Todd Fredrich">
<!-- Le styles -->
<link href="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css" rel="stylesheet">
<link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.banner-container {
}
#mc_embed_signup{background:#8ac; clear:left; padding: 15px; border-radius: 25px; font:14px Helvetica,Arial,sans-serif; }
div.mc-field-group.input-group label{display:inline; margin-left: 10px; }
#mce-QUESTION1{width: 80%; height: 3em;}
#mce-QUESTION2{width: 80%; height: 3em; }
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31328878-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<div class="container">
<div class="row">
<div class="span7">
<h2>What's Your Most Burning REST API Question?</h2>
<p><strong>Hey Fellow REST-afarian!</strong></p>
<p>I'm creating a FREE Webinar about REST API Design and want to answer your most-pressing REST API question.</p>
<p>Enter your question in the form to the right, along with your email address and I'll answer your questions via the Webinar.</p>
<p>REST well,<br>
Todd Fredrich, <em>The REST API Tutor<em></p>
</div>
<div class="span5">
<!-- Begin MailChimp Signup Form -->
<div id="mc_embed_signup">
<form action="https://RestApiTutorial.us1.list-manage.com/subscribe/post?u=3449a65355441906371f87327&amp;id=95beecb082" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll">
<h2>Submit it Now!</h2>
<div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
<div class="mc-field-group">
<label for="mce-EMAIL">Email Address <span class="asterisk">*</span>
</label>
<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
</div>
<div class="mc-field-group">
<label for="mce-FNAME">First Name </label>
<input type="text" value="" name="FNAME" class="" id="mce-FNAME">
</div>
<div class="mc-field-group">
<label for="mce-LNAME">Last Name </label>
<input type="text" value="" name="LNAME" class="" id="mce-LNAME">
</div>
<div class="mc-field-group">
<label for="mce-QUESTION1">My most-pressing REST API question <span class="asterisk">*</span>
</label>
<input type="text" value="" name="QUESTION1" class="required" id="mce-QUESTION1">
</div>
<div class="mc-field-group">
<label for="mce-QUESTION2">I also want to know about... </label>
<input type="text" value="" name="QUESTION2" class="" id="mce-QUESTION2">
</div>
<div class="mc-field-group input-group">
<strong>Additional Preferences </strong>
<ul><li><input type="checkbox" value="1" name="group[7181][1]" id="mce-group[7181]-7181-0"><label for="mce-group[7181]-7181-0">I'd rather have the book!</label></li>
<li><input type="checkbox" value="2" name="group[7181][2]" id="mce-group[7181]-7181-1"><label for="mce-group[7181]-7181-1">I'd rather have the Webinar recording.</label></li>
</ul>
</div>
<div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div>
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_3449a65355441906371f87327_95beecb082" tabindex="-1" value=""></div>
<div class="clear"><input type="submit" value="Submit Now!" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</div>
</form>
</div>
<script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';fnames[2]='LNAME';ftypes[2]='text';fnames[3]='QUESTION1';ftypes[3]='text';fnames[4]='QUESTION2';ftypes[4]='text';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
<!--End mc_embed_signup-->
</div>
</div>
<hr>
<footer>
</footer>
</div> <!-- /container -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a>
<a class="brand" href="https://www.restapitutorial.com">REST API Tutorial</a>
<div class="nav-collapse">
<ul class="nav">
<li><a href="https://www.restapitutorial.com">Home</a></li>
<li class="dropdown" id="api-school"><a class="dropdown-toggle" data-toggle="dropdown" href="#">Tutorials<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="lessons/whatisrest.html">What Is REST?</a></li>
<li><a href="lessons/restquicktips.html">REST Quick Tips</a></li>
<li><a href="lessons/httpmethods.html">HTTP Methods</a></li>
<li><a href="lessons/restfulresourcenaming.html">Resource Naming</a></li>
<li><a href="lessons/idempotency.html">Idempotence</a></li>
</ul>
</li>
<li><a href="httpstatuscodes.html">HTTP Status Codes</a></li>
<li><a href="resources.html">Resources</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/twitter-bootstrap/2.0.4/js/bootstrap.min.js"></script>
<a href="https://github.com/tfredrich/RestApiTutorial.com"><img style="position: absolute; top: 0; right: 0; border: 0; z-index: 1050;" src="https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"></a>
</body>
</html>

View File

@ -1,30 +0,0 @@
<html>
<head>
<title>Moved to new URL: https://www.restapitutorial.com/lessons/restquicktips.html</title>
<meta http-equiv=refresh content="0; url=https://www.restapitutorial.com/lessons/restquicktips.html" />
<meta name="robots" content="noindex,follow" />
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '389059184866929');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=389059184866929&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
</head>
<body>
<h1>This page has been moved to https://www.restapitutorial.com/lessons/restquicktips.html</h1>
<p>If your browser doesn't redirect you to the new location please
<a href="https://www.restapitutorial.com/lessons/restquicktips.html"><strong>click here</strong></a>,
sorry for the hassles!</p>
</body>
</html>

View File

@ -0,0 +1,19 @@
# https://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
trim_trailing_whitespace = true
[*.css]
indent_size = 4
[*.js]
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -0,0 +1,14 @@
name: Build site
description: Builds the Hugo exampleSite for later deploy on GitHub-Pages
runs:
using: composite
steps:
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
- name: Build site
shell: bash
run: |
hugo --source ${GITHUB_WORKSPACE}/exampleSite --destination ${GITHUB_WORKSPACE}/../public --cleanDestinationDir --gc --baseURL https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/ --theme ${GITHUB_WORKSPACE}

View File

@ -0,0 +1,73 @@
name: Check milestone
description: Checks if the given milestone and its according tag are valid to be released
inputs:
milestone:
description: Milestone for this release
required: true
github_token:
description: Secret GitHub token
required: true
outputs:
outcome:
description: Result of the check, success or failure
value: ${{ steps.outcome.outputs.outcome }}
runs:
using: composite
steps:
- name: Get tag uniqueness
id: unique_tag
uses: mukunku/tag-exists-action@v1.0.0
with:
tag: ${{ env.MILESTONE }}
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
- name: Get closed issues for milestone
id: closed_issues
uses: octokit/graphql-action@v2.x
with:
query: |
query {
search(first: 1, type: ISSUE, query: "user:${{ github.repository_owner }} repo:${{ github.event.repository.name }} milestone:${{ env.MILESTONE }} state:closed") {
issueCount
}
}
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
- name: Get open issues for milestone
id: open_issues
uses: octokit/graphql-action@v2.x
with:
query: |
query {
search(first: 1, type: ISSUE, query: "user:${{ github.repository_owner }} repo:${{ github.event.repository.name }} milestone:${{ env.MILESTONE }} state:open") {
issueCount
}
}
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
- name: Set outcome
id: outcome
shell: bash
run: |
if [ "${{ fromJSON(steps.closed_issues.outputs.data).search.issueCount > 0 && fromJSON(steps.open_issues.outputs.data).search.issueCount == 0 && steps.unique_tag.outputs.exists == 'false' }}" = "true" ]; then
echo "::set-output name=outcome::success"
else
echo "::set-output name=outcome::failure"
fi
- name: Log results and exit
shell: bash
run: |
echo outcome : ${{ steps.outcome.outputs.outcome }}
echo has unique tag : ${{ steps.unique_tag.outputs.exists == 'false' }}
echo has closed issues: ${{ fromJSON(steps.closed_issues.outputs.data).search.issueCount > 0 }}
echo has open issues : ${{ fromJSON(steps.open_issues.outputs.data).search.issueCount > 0 }}
if [ "${{ steps.outcome.outputs.outcome }}" = "failure" ]; then
exit 1
fi

View File

@ -0,0 +1,17 @@
name: Deploy site
description: Deploys a built site on GitHub-Pages
inputs:
github_token:
description: Secret GitHub token
required: true
runs:
using: composite
steps:
- name: Deploy site
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ env.GITHUB_TOKEN }}
publish_dir: ${{ env.GITHUB_WORKSPACE }}/../public
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
GITHUB_WORKSPACE: ${{ github.workspace }}

View File

@ -0,0 +1,77 @@
name: Release milestone
description: Creates a release with changelog and tag out of a given milestone
inputs:
milestone:
description: Milestone for this release
required: true
github_token:
description: Secret GitHub token
required: true
runs:
using: composite
steps:
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Close milestone
uses: Akkjon/close-milestone@v2
with:
milestone_name: ${{ env.MILESTONE }}
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
- name: Create provisionary tag
shell: bash
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
run: |
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git tag --message "" "$MILESTONE"
git push origin "$MILESTONE"
- name: Update changelog
shell: bash
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
GREN_GITHUB_TOKEN: ${{ inputs.github_token }}
run: |
echo "$MILESTONE" > layouts/partials/version.html
npx github-release-notes@0.17.1 changelog --generate --override --tags=all
git add *
git commit --message "Ship tag $MILESTONE"
git push origin main
- name: Create final tag
shell: bash
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
run: |
git tag --force --message "" "$MILESTONE"
git push --force origin "$MILESTONE"
- name: Publish release
shell: bash
env:
MILESTONE: ${{ inputs.milestone }}
GREN_GITHUB_TOKEN: ${{ inputs.github_token }}
run: |
npx github-release-notes@0.17.1 release --tags "$MILESTONE"
- name: Update version number to mark non-release version
shell: bash
env:
MILESTONE: ${{ inputs.milestone }}
GITHUB_TOKEN: ${{ inputs.github_token }}
GREN_GITHUB_TOKEN: ${{ inputs.github_token }}
run: |
echo "$MILESTONE+tip" > layouts/partials/version.html
git add *
git commit --message "Mark non-release version"
git push origin main

28
themes/relearn/.github/contributing.md vendored Normal file
View File

@ -0,0 +1,28 @@
# Guidelines
## For Development
- help us putting your code into production by opening a meaningful issue
- stay simple for the user by focusing on the mantra "convention over configuration"
- at installation the site should work reasonable without (m)any configuration
- stay close to the Hugo way
- don't use npm or any preprocessing, our contributors may not be front-end developers
- document new features in exampleSite
- don't break existing features if you don't have to
- remove reported issue from the browser's console
- be compatible to IE11, at least for main functionality, for Javascript this means:
- test in IE11
- check caniuse.com
- don't use arrow functions
- don't use template literals
- don't use other fancy new ES5/6 stuff
## For Release
- create releases following [semver policy](https://semver.org/)
- we are using GitHub actions to create new releases
- a release is based on a milestone named like the release itself - just the version number, eg: 1.1.0
- remember that there have to be at least one closed issue assigned to the milestone
- the release action only runs successfully if all assigned issues for this milestone are closed
- the milestone itself will be closed during execution of the action
- a once released milestone can not be released again

View File

@ -0,0 +1,20 @@
name: Build
on:
push: # Build on all pushes but only deploy for main branch
pull_request: # Build on all PRs regardless what branch
workflow_dispatch: # Allow this task to be manually started (you'll never know)
jobs:
ci:
name: Run build
runs-on: ubuntu-latest
if: github.event_name != 'push' || (github.event_name == 'push' && github.ref != 'refs/heads/main')
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
- name: Build site
uses: ./.github/actions/build_site

View File

@ -0,0 +1,25 @@
name: Deploy
on:
push: # Build on all pushes but only deploy for main branch
workflow_dispatch: # Allow this task to be manually started (you'll never know)
jobs:
deploy:
name: Run deploy
runs-on: ubuntu-latest
if: github.event_name != 'push' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Build site
uses: ./.github/actions/build_site
- name: Deploy site
uses: ./.github/actions/deploy_site
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,42 @@
name: Release
on:
workflow_dispatch:
inputs:
milestone:
description: 'Milestone for this release'
required: true
jobs:
release:
name: Run release
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: true # Fetch Hugo themes (true OR recursive)
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Check milestone
id: check
uses: ./.github/actions/check_milestone
with:
milestone: ${{ github.event.inputs.milestone }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
if: ${{ steps.check.outputs.outcome == 'success' }}
uses: ./.github/actions/release_milestone
with:
milestone: ${{ github.event.inputs.milestone }}
github_token: ${{ secrets.GITHUB_TOKEN }}
# We need to deploy the site again to show the updated changelog
- name: Build site
uses: ./.github/actions/build_site
- name: Deploy site
uses: ./.github/actions/deploy_site
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

5
themes/relearn/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.DS_Store
public/
exampleSite/public
exampleSite/hugo*.exe
.hugo_build.lock

38
themes/relearn/.grenrc.js Normal file
View File

@ -0,0 +1,38 @@
module.exports = {
changelogFilename: "exampleSite/content/basics/CHANGELOG.md",
dataSource: "milestones",
groupBy: {
"Enhancements": [
"feature",
],
"Fixes": [
"bug"
],
"Maintenance": [
"task",
],
"Uncategorised": [
"closed",
],
},
ignoreLabels: [
"hugo",
],
ignoreIssuesWith: [
"discussion",
"documentation",
"duplicate",
"invalid",
"support",
"wontfix",
],
ignoreTagsWith: [
"Relearn",
],
milestoneMatch: "{{tag_name}}",
onlyMilestones: true,
template: {
group: "\n### {{heading}}\n",
release: ({ body, date, release }) => `## ${release} (` + date.replace( /(\d+)\/(\d+)\/(\d+)/, '$3-$2-$1' ) + `)\n${body}`,
},
};

View File

@ -0,0 +1,7 @@
# Integration with Issue Tracker
#
# (note that '\' need to be escaped).
[issuetracker "GitHub Rule"]
regex = "#(\\d+)"
url = "https://github.com/McShelby/hugo-theme-relearn/issues/$1"

23
themes/relearn/LICENSE Normal file
View File

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2021 Sören Weber
Copyright (c) 2017 Valere JEANTET
Copyright (c) 2016 MATHIEU CORNIC
Copyright (c) 2014 Grav
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

63
themes/relearn/README.md Normal file
View File

@ -0,0 +1,63 @@
# Hugo Relearn Theme
A theme for [Hugo](https://gohugo.io/) designed for documentation.
![Overview](https://github.com/McShelby/hugo-theme-relearn/raw/main/images/screenshot.png)
## Motivation
The theme is a fork of the great [Learn theme](https://github.com/matcornic/hugo-theme-learn) with the aim of fixing long outstanding bugs and adepting to latest Hugo features. As far as possible this theme tries to be a drop-in replacement for the Learn theme.
## Main features
- Usable offline, no external dependencies
- Support for Internet Explorer 11
- Responsive design
- Configurable hidden pages
- Automatic next/prev buttons to navigate through menu entries
- Automatic Search
- Print whole chapters or even the complete site
- Multilingual mode for English, Arabic, Simplified Chinese, Traditional Chinesse, Dutch, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Turkish, Vietnamese
- Unrestricted menu configuration relating to amount of items and level of nesting
- Font Awesome icons
- Tagging support
- Image resizing, shadow…
- Syntax highlighting
- Attachments files
- List child pages
- Mermaid diagrams for flowcharts, sequences, gantts, pie, etc.
- Swagger UI for OpenAPI Specifications
- Customizable look and feel
- Predefined (light, dark) and customizable color variants
- Buttons
- Tip/Note/Info/Warning boxes
- Expand
- Tabs
- File inclusion
## Installation
Visit the [installation instructions](https://mcshelby.github.io/hugo-theme-relearn/basics/installation) to learn how to setup the theme in your Hugo installation.
## Usage
Visit the [documentation](https://mcshelby.github.io/hugo-theme-relearn/) to learn about all available features and how to use them.
## Changelog
See the [changelog](https://mcshelby.github.io/hugo-theme-relearn/basics/history) for a complete list of releases.
## Contribution
You are most welcome to contribute to the source code but please visit the [contribution guidelines](https://github.com/McShelby/hugo-theme-relearn/blob/main/.github/contributing.md) first.
## License
This theme is licensed under the [MIT License](https://github.com/McShelby/hugo-theme-relearn/blob/main/LICENSE).
## Credits
Special thanks to [everyone who has contributed](https://github.com/McShelby/hugo-theme-relearn/graphs/contributors) to this project.
Many thanks to [Mathieu Cornic](https://github.com/matcornic) for his work on porting the [Learn theme](https://github.com/matcornic/hugo-theme-learn) to Hugo.
Many thanks to [Andy Miller](https://github.com/rhukster) for initially creating the [Learn theme](https://github.com/getgrav/grav-theme-learn2) for Grav.

View File

@ -0,0 +1,12 @@
+++
chapter = true
pre = "<b>X. </b>"
title = "{{ replace .Name "-" " " | title }}"
weight = 5
+++
### Chapter X
# Some Chapter title
Lorem Ipsum.

View File

@ -0,0 +1,6 @@
+++
title = "{{ replace .Name "-" " " | title }}"
weight = 5
+++
Lorem Ipsum.

View File

@ -0,0 +1,12 @@
[module]
[module.hugoVersion]
min = "0.93.0"
[outputFormats]
[outputFormats.PRINT]
name= "PRINT"
baseName = "index"
path = "_print"
isHTML = true
mediaType = 'text/html'
permalinkable = false

View File

@ -0,0 +1,162 @@
# this is a required setting for this theme to appear on https://themes.gohugo.io/
# change this to a value appropriate for you
baseURL = "https://example.com"
# as the official Hugo documentation recommends, we turn this off for this
# showcase; this allows the published site to be served by both http and https
canonifyURLs = false
# required for official documentation served from subfolder
relativeURLs = false
# the directory where Hugo reads the themes from; this is specific to your
# installation and most certainly needs be deleted or changed
themesdir = "../.."
# yeah, well, obviously a mandatory setting for your site, if you want to
# use this theme ;-)
theme = "hugo-theme-relearn"
# the main language of this site; also an automatic pirrrate translation is
# available in this showcase
languageCode = "en"
defaultContentLanguage = "en"
# if you want to get rrrid o' ourrr pirrrates nonsense uncomment th' next line
# disableLanguages = ['pir']
# the site's title of this showcase; you should change this ;-)
title = "Hugo Relearn Documentation"
# settings specific to this theme's features; choose to your likings and
# consult this documentation for explaination
[params]
editURL = "https://github.com/McShelby/hugo-theme-relearn/edit/main/exampleSite/content/"
description = "Documentation for Hugo Relearn Theme"
author = "Sören Weber"
showVisitedLinks = true
collapsibleMenu = true
disableBreadcrumb = false
disableNextPrev = false
disableLandingPageButton = true
titleSeparator = "::"
themeVariant = [ "relearn-light", "relearn-dark", "learn", "neon", "blue", "green", "red" ]
disableSeoHiddenPages = true
# this is for the stylesheet genertor to allow for interactivity in mermaid
# graphs; you usually will not need it and you should remove this for
# security reasons
mermaidInitialize = "{ \"securityLevel\": \"loose\" }"
[outputs]
# add JSON to the home to support lunr search; This is a mandatory setting
# for the search functionality
# add PRINT to home, section and page to activate feature to print whole
# chapters
home = ["HTML", "RSS", "PRINT", "JSON"]
section = ["HTML", "RSS", "PRINT"]
page = ["HTML", "RSS", "PRINT"]
[markup]
[markup.highlight]
# if `guessSyntax = true`, there will be no unstyled code even if no language
# was given BUT mermaid code fences will not work anymore! So this is a mandatory
# setting for your site
guessSyntax = false
# here in this showcase we use our own modified chroma syntax highlightning style
# which is imported in theme-relearn-light.css / theme-relearn-dark.css;
# if you want to use a predefined style instead:
# - remove the following `noClasses`
# - set the following `style` to a predefined style name
# - remove the `@import` of the self-defined chroma stylesheet from your CSS files
# (here eg.: theme-relearn-light.css / theme-relearn-dark.css)
noClasses = false
# style = "tango"
[markup.goldmark.renderer]
# activated for this showcase to use HTML and JavaScript; decide on your own needs;
# if in doubt, remove this line
unsafe = true
# allows `hugo server` to display this showcase in IE11; this is used for testing, as we
# are still supporting IE11 - although with degraded experience; if you don't care about
# `hugo server` or browsers of ancient times, fell free to remove this whole block
[server]
[[server.headers]]
for = "**.html"
[server.headers.values]
X-UA-Compatible = "IE=edge"
# showcase of the menu shortcuts; you can use relative URLs linking
# to your content or use fully-quallified URLs to link outside of
# your project
[Languages]
[Languages.en]
title = "Hugo Relearn Theme"
weight = 1
languageName = "English"
landingPageURL = "/"
landingPageName = "<i class='fas fa-home'></i> Home"
[[Languages.en.menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-camera'></i> Showcases"
url = "more/showcase/"
weight = 11
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bookmark'></i> Hugo Documentation"
identifier = "hugodoc"
url = "https://gohugo.io/"
weight = 20
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bullhorn'></i> Credits"
url = "more/credits/"
weight = 30
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Tags"
url = "tags/"
weight = 40
# this is ourrr way t' showcase th' multilang settings by
# doing autotrrranlat'n of th' english content; we are
# lazy and don't supporrt furrrther trrranslations; arrr,
# don't take it t' serrrious, fello'; it's prrretty hacky and:
# NOT MEANT FOR PRRRODUCTION! ARRR!
[Languages.pir]
title = "Cap'n Hugo Relearrrn Theme"
weight = 1
languageName = "Arrr! ☠ Pirrrates ☠"
landingPageURL = "/pir/"
landingPageName = "<i class='fas fa-home'></i> Arrr! Home"
[[Languages.pir.menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-camera'></i> Showcases"
url = "more/showcase/"
weight = 11
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bookmark'></i> Cap'n Hugo Documentat'n"
identifier = "hugodoc"
url = "https://gohugo.io/"
weight = 20
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bullhorn'></i> Crrredits"
url = "more/credits/"
weight = 30
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Arrr! Tags"
url = "tags/"
weight = 40

View File

@ -0,0 +1,60 @@
+++
title = "Hugo Relearn Theme"
+++
# Hugo Relearn Theme
The [Relearn theme](http://github.com/McShelby/hugo-theme-relearn) is a theme for [Hugo](https://gohugo.io/), a static website generator written in Go. Where Hugo is often used for blogs, this theme is designed with documentation in mind.
{{% notice info %}}
The theme is a fork of the great [Learn theme](https://github.com/matcornic/hugo-theme-learn) with the aim of fixing long outstanding bugs and adepting to latest Hugo features. As far as possible this theme tries to be a drop-in replacement for the Learn theme.
{{% /notice %}}
## Main features
{{% notice tip %}}
See [what's new]({{% relref "basics/migration" %}}) within the latest update.
{{% /notice %}}
- Usable offline, no external dependencies
- Support for Internet Explorer 11
- Responsive design
- Configurable hidden pages
- Automatic next/prev buttons to navigate through menu entries
- [Automatic Search]({{%relref "basics/configuration#activate-search" %}})
- [Print]({{%relref "basics/configuration#activate-print-support" %}}) whole chapters or even the complete site
- [Multilingual mode]({{%relref "cont/i18n" %}}) for English, Arabic, Simplified Chinese, Traditional Chinesse, Dutch, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Turkish, Vietnamese
- [Unrestricted menu configuration]({{%relref "cont/menushortcuts" %}}) relating to amount of items and level of nesting
- [Font Awesome icons]({{%relref "cont/icons" %}})
- [Tagging support]({{%relref "cont/tags" %}})
- [Image resizing, shadow...]({{%relref "cont/markdown#images" %}})
- [Syntax highlighting]({{%relref "cont/syntaxhighlight" %}})
- [Attachments files]({{%relref "shortcodes/attachments" %}})
- [List child pages]({{%relref "shortcodes/children" %}})
- [Mermaid diagrams]({{%relref "shortcodes/mermaid" %}}) for flowcharts, sequences, gantts, pie, etc.
- [Swagger UI]({{%relref "shortcodes/swagger" %}}) for OpenAPI Specifications
- [Customizable look and feel]({{%relref "basics/customization"%}})
- [Predefined (light, dark) and customizable color variants]({{%relref "basics/generator" %}})
- [Buttons]({{%relref "shortcodes/button" %}})
- [Tip/Note/Info/Warning boxes]({{%relref "shortcodes/notice" %}})
- [Expand]({{%relref "shortcodes/expand" %}})
- [Tabs]({{%relref "shortcodes/tabs" %}})
- [File inclusion]({{%relref "shortcodes/include" %}})
## Getting support
To get support, feel free to open a new [discussion topic](https://github.com/McShelby/hugo-theme-relearn/discussions) or [issue](https://github.com/McShelby/hugo-theme-relearn/issues) in the official repository on GitHub.
## Become a contributor
Feel free to update this documentation by just clicking the **Edit** link displayed on top right of each page. Your changes will be deployed automatically once they were reviewed.
You are most welcome to contribute bugfixes or even new features to the source code by making pull requests to the [official repository](https://github.com/McShelby/hugo-theme-relearn) via GitHub. Please visit the [contribution guidelines](https://github.com/McShelby/hugo-theme-relearn/blob/main/.github/contributing.md) first.
## License
This theme is licensed under the [MIT License](https://github.com/McShelby/hugo-theme-relearn/blob/main/LICENSE).
## Credits
This theme would not be possible without the work of many others. See the [credits]({{%relref "more/credits" %}}) for a detailed list.

View File

@ -0,0 +1,4 @@
+++
title = "Cap'n Hugo Relearrrn Theme"
+++
{{< piratify >}}

View File

@ -0,0 +1,548 @@
# Changelog
## 4.0.3 (2022-06-05)
### Enhancements
- [**feature**] toc: add scrollbar [#262](https://github.com/McShelby/hugo-theme-relearn/issues/262)
---
## 4.0.2 (2022-06-05)
### Fixes
- [**bug**] theme: let browser scroll page on CTRL+f [#242](https://github.com/McShelby/hugo-theme-relearn/issues/242)
---
## 4.0.1 (2022-06-05)
*No changelog for this release.*
---
## 4.0.0 (2022-06-05)
### Enhancements
- [**feature**] shortcodes: add named parameter if missing [#260](https://github.com/McShelby/hugo-theme-relearn/issues/260)
- [**feature**][**breaking**] theme: remove --MAIN-ANCHOR-color from stylesheet [#256](https://github.com/McShelby/hugo-theme-relearn/issues/256)
- [**feature**] i18n: add italian translation [#254](https://github.com/McShelby/hugo-theme-relearn/issues/254)
- [**feature**] attachments: support for brand colors [#252](https://github.com/McShelby/hugo-theme-relearn/issues/252)
- [**feature**] notice: support for brand colors [#251](https://github.com/McShelby/hugo-theme-relearn/issues/251)
- [**feature**][**breaking**] config: remove custom_css [#248](https://github.com/McShelby/hugo-theme-relearn/issues/248)
- [**feature**] theme: use proper file extension for page-meta.go [#246](https://github.com/McShelby/hugo-theme-relearn/issues/246)
- [**feature**] variant: add support for brand color variables [#239](https://github.com/McShelby/hugo-theme-relearn/issues/239)
- [**feature**] i18n: add polish translation [#237](https://github.com/McShelby/hugo-theme-relearn/issues/237)
### Fixes
- [**bug**] shortcodes: accept boolean parameters if given as string [#261](https://github.com/McShelby/hugo-theme-relearn/issues/261)
- [**bug**] print: adjust button and tab size [#259](https://github.com/McShelby/hugo-theme-relearn/issues/259)
- [**bug**] print: show Mermaid if requested in frontmatter [#255](https://github.com/McShelby/hugo-theme-relearn/issues/255)
- [**bug**] theme: adjust thin scrollbar slider [#244](https://github.com/McShelby/hugo-theme-relearn/issues/244)
- [**bug**] mobile: fix broken scrollbar [#243](https://github.com/McShelby/hugo-theme-relearn/issues/243)
- [**bug**] theme: fix display of tooltip for heading anchor [#241](https://github.com/McShelby/hugo-theme-relearn/issues/241)
---
## 3.4.1 (2022-04-03)
### Fixes
- [**bug**] theme: fix IE11 incompatiblities [#234](https://github.com/McShelby/hugo-theme-relearn/issues/234)
---
## 3.4.0 (2022-04-03)
### Enhancements
- [**feature**] i18n: add traditional chinese translation [#233](https://github.com/McShelby/hugo-theme-relearn/issues/233)
- [**feature**] menu: expand/collapse menu items without navigation [#231](https://github.com/McShelby/hugo-theme-relearn/issues/231)
- [**feature**] print: add option to print whole chapter [#230](https://github.com/McShelby/hugo-theme-relearn/issues/230)
- [**feature**][**breaking**] theme: apply user supplied content footer below content [#229](https://github.com/McShelby/hugo-theme-relearn/issues/229)
### Fixes
- [**bug**] theme: scroll to heading on initial load [#232](https://github.com/McShelby/hugo-theme-relearn/issues/232)
---
## 3.3.0 (2022-03-28)
### Enhancements
- [**feature**] theme: add CSS font variables [#227](https://github.com/McShelby/hugo-theme-relearn/issues/227)
- [**feature**] swagger: add support for oas/swagger documentation [#226](https://github.com/McShelby/hugo-theme-relearn/issues/226)
### Fixes
- [**bug**] variant: make variant switch work on slow networks [#228](https://github.com/McShelby/hugo-theme-relearn/issues/228)
---
## 3.2.1 (2022-03-25)
### Fixes
- [**bug**] print: fix minor inconsistencies [#225](https://github.com/McShelby/hugo-theme-relearn/issues/225)
- [**bug**] print: show more than just the title page [#224](https://github.com/McShelby/hugo-theme-relearn/issues/224)
- [**bug**] theme: align content scrollbar to the right on big screens [#223](https://github.com/McShelby/hugo-theme-relearn/issues/223)
---
## 3.2.0 (2022-03-19)
### Enhancements
- [**feature**][**change**] mermaid: support differing themes for color variant switch [#219](https://github.com/McShelby/hugo-theme-relearn/issues/219)
- [**feature**] mermaid: load javascript on demand [#218](https://github.com/McShelby/hugo-theme-relearn/issues/218)
### Maintenance
- [**task**] mermaid: update to 8.14.0 [#220](https://github.com/McShelby/hugo-theme-relearn/issues/220)
---
## 3.1.1 (2022-03-16)
### Enhancements
- [**feature**] i18n: add korean translation [#217](https://github.com/McShelby/hugo-theme-relearn/issues/217)
---
## 3.1.0 (2022-03-15)
### Enhancements
- [**feature**] notice: add icon parameter [#212](https://github.com/McShelby/hugo-theme-relearn/issues/212)
- [**feature**] mobile: remove breadcrumb ellipsis [#211](https://github.com/McShelby/hugo-theme-relearn/issues/211)
### Fixes
- [**bug**] theme: make storage of multiple Hugo sites on same server distinct [#214](https://github.com/McShelby/hugo-theme-relearn/issues/214)
- [**bug**] variant: switch breadcrumb color in Chrome [#213](https://github.com/McShelby/hugo-theme-relearn/issues/213)
- [**bug**] mobile: improve behavior of sidebar menu [#210](https://github.com/McShelby/hugo-theme-relearn/issues/210)
---
## 3.0.4 (2022-02-24)
### Enhancements
- [**feature**] theme: improve font loading [#201](https://github.com/McShelby/hugo-theme-relearn/issues/201)
- [**feature**][**change**] variant: fix inconsistent color variable naming [#200](https://github.com/McShelby/hugo-theme-relearn/issues/200)
### Fixes
- [**bug**] variant: fix occasional fail when resetting generator [#208](https://github.com/McShelby/hugo-theme-relearn/issues/208)
- [**bug**] docs: don't move header on logo hover in IE11 [#207](https://github.com/McShelby/hugo-theme-relearn/issues/207)
- [**bug**] variant: avoid flash of menu header when non default variant is active [#206](https://github.com/McShelby/hugo-theme-relearn/issues/206)
- [**bug**] theme: fix wrong HTML closing tag order in chapters [#205](https://github.com/McShelby/hugo-theme-relearn/issues/205)
- [**bug**] theme: adjust breadcrumb and title for empty home page titles [#202](https://github.com/McShelby/hugo-theme-relearn/issues/202)
---
## 3.0.3 (2022-02-23)
### Enhancements
- [**feature**] tags: show tag count in taxonomy list [#195](https://github.com/McShelby/hugo-theme-relearn/issues/195)
### Fixes
- [**bug**] theme: remove Hugo build warning if page is not file based [#197](https://github.com/McShelby/hugo-theme-relearn/issues/197)
- [**bug**] tags: adhere to titleSeparator [#196](https://github.com/McShelby/hugo-theme-relearn/issues/196)
- [**bug**] theme: hide footer divider and variant selector in IE11 [#194](https://github.com/McShelby/hugo-theme-relearn/issues/194)
---
## 3.0.2 (2022-02-23)
### Enhancements
- [**feature**] tags: sort by name [#193](https://github.com/McShelby/hugo-theme-relearn/issues/193)
---
## 3.0.1 (2022-02-23)
### Enhancements
- [**feature**] children: set containerstyle automatically according to style [#192](https://github.com/McShelby/hugo-theme-relearn/issues/192)
### Fixes
- [**bug**] theme: revert fontawsome to version 5 for IE11 compat [#191](https://github.com/McShelby/hugo-theme-relearn/issues/191)
---
## 3.0.0 (2022-02-22)
### Enhancements
- [**feature**] variant: build a variant generator [#188](https://github.com/McShelby/hugo-theme-relearn/issues/188)
- [**feature**] nav: only show toc if the page has headings [#182](https://github.com/McShelby/hugo-theme-relearn/issues/182)
- [**feature**][**breaking**] theme: change default colors to Relearn defaults [#181](https://github.com/McShelby/hugo-theme-relearn/issues/181)
- [**feature**] variant: add a variant selector [#178](https://github.com/McShelby/hugo-theme-relearn/issues/178)
- [**feature**][**breaking**] menu: rework footer UX [#177](https://github.com/McShelby/hugo-theme-relearn/issues/177)
- [**feature**] theme: support for dark mode [#175](https://github.com/McShelby/hugo-theme-relearn/issues/175)
- [**feature**] docs: use light syntax highlightning theme [#174](https://github.com/McShelby/hugo-theme-relearn/issues/174)
- [**feature**] notice: tweak dull colors [#173](https://github.com/McShelby/hugo-theme-relearn/issues/173)
- [**feature**] theme: rework header UX [#151](https://github.com/McShelby/hugo-theme-relearn/issues/151)
### Fixes
- [**bug**] search: remove additional X in filled out search box in IE11 [#190](https://github.com/McShelby/hugo-theme-relearn/issues/190)
- [**bug**] clipboard: localize tooltips [#186](https://github.com/McShelby/hugo-theme-relearn/issues/186)
- [**bug**] print: hide sidebar on Mac [#183](https://github.com/McShelby/hugo-theme-relearn/issues/183)
- [**bug**] menu: fix scrollbar height [#180](https://github.com/McShelby/hugo-theme-relearn/issues/180)
- [**bug**][**change**] search: fix color change for icons on hover [#176](https://github.com/McShelby/hugo-theme-relearn/issues/176)
---
## 2.9.6 (2022-02-07)
### Fixes
- [**bug**] menu: remove debug output [#171](https://github.com/McShelby/hugo-theme-relearn/issues/171)
---
## 2.9.5 (2022-02-07)
### Fixes
- [**bug**] menu: let arrow navigation respect ordersectionsby configuration [#170](https://github.com/McShelby/hugo-theme-relearn/issues/170)
---
## 2.9.4 (2022-02-06)
### Fixes
- [**bug**] exampleSite: fix links in official documentation [#168](https://github.com/McShelby/hugo-theme-relearn/issues/168)
---
## 2.9.3 (2022-02-06)
### Fixes
- [**bug**] menu: invalid URL when the shortcut is an internal link [#163](https://github.com/McShelby/hugo-theme-relearn/issues/163)
---
## 2.9.2 (2021-11-26)
### Enhancements
- [**feature**] theme: add theme version info to head [#158](https://github.com/McShelby/hugo-theme-relearn/issues/158)
### Fixes
- [**bug**] theme: fix selection of *.ico files as favicons [#160](https://github.com/McShelby/hugo-theme-relearn/issues/160)
---
## 2.9.1 (2021-11-22)
### Fixes
- [**bug**] menu: fix significantly low performance for collecting of meta info [#157](https://github.com/McShelby/hugo-theme-relearn/issues/157)
---
## 2.9.0 (2021-11-19)
### Fixes
- [**bug**][**breaking**] relref: fix inconsistent behavior [#156](https://github.com/McShelby/hugo-theme-relearn/issues/156)
- [**bug**] search: make dropdown stick to search field when scrolling [#155](https://github.com/McShelby/hugo-theme-relearn/issues/155)
- [**bug**] menu: align long text properly [#154](https://github.com/McShelby/hugo-theme-relearn/issues/154)
- [**bug**] copyToClipBoard: add missing right border for inline code if `disableInlineCopyToClipBoard=true` [#153](https://github.com/McShelby/hugo-theme-relearn/issues/153)
- [**bug**] menu: show hidden sibling pages reliably [#152](https://github.com/McShelby/hugo-theme-relearn/issues/152)
- [**bug**] menu: bring active item in sight for large menus [#149](https://github.com/McShelby/hugo-theme-relearn/issues/149)
---
## 2.8.3 (2021-11-09)
### Fixes
- [**bug**] mermaid: let zoom reset to initial size [#145](https://github.com/McShelby/hugo-theme-relearn/issues/145)
- [**bug**] mermaid: remove whitespace from big graphs [#143](https://github.com/McShelby/hugo-theme-relearn/issues/143)
---
## 2.8.2 (2021-11-08)
### Fixes
- [**bug**] mermaid: always load javascript to avoid break if code fences are used [#142](https://github.com/McShelby/hugo-theme-relearn/issues/142)
---
## 2.8.1 (2021-11-04)
### Fixes
- [**bug**] search: don't break JS in multilang setup if search is disabled [#140](https://github.com/McShelby/hugo-theme-relearn/issues/140)
---
## 2.8.0 (2021-11-03)
### Enhancements
- [**feature**] toc: make disableTOC globally available via config.toml [#133](https://github.com/McShelby/hugo-theme-relearn/issues/133)
- [**feature**] mermaid: only load javascript if necessary [#95](https://github.com/McShelby/hugo-theme-relearn/issues/95)
- [**feature**][**change**] theme: switch font [#83](https://github.com/McShelby/hugo-theme-relearn/issues/83)
- [**feature**] theme: make favicon configurable [#2](https://github.com/McShelby/hugo-theme-relearn/issues/2)
### Fixes
- [**bug**] mermaid: assert that window.mermaid is actually mermaid [#136](https://github.com/McShelby/hugo-theme-relearn/issues/136)
- [**bug**] menu: remove usage of Hugos UniqueID [#131](https://github.com/McShelby/hugo-theme-relearn/issues/131)
- [**bug**] theme: reduce margin for children shortcode [#130](https://github.com/McShelby/hugo-theme-relearn/issues/130)
- [**bug**] theme: left-align h3 in chapters [#129](https://github.com/McShelby/hugo-theme-relearn/issues/129)
- [**bug**] theme: align copy link to clipboard [#128](https://github.com/McShelby/hugo-theme-relearn/issues/128)
---
## 2.7.0 (2021-10-24)
### Enhancements
- [**feature**] notice: support custom titles [#124](https://github.com/McShelby/hugo-theme-relearn/issues/124)
---
## 2.6.0 (2021-10-21)
### Fixes
- [**bug**] theme: generate correct links if theme served from subdirectory [#120](https://github.com/McShelby/hugo-theme-relearn/issues/120)
---
## 2.5.1 (2021-10-12)
### Fixes
- [**bug**] security: fix XSS for malicioius image URLs [#117](https://github.com/McShelby/hugo-theme-relearn/issues/117)
---
## 2.5.0 (2021-10-08)
### Enhancements
- [**feature**][**change**] syntax highlight: provide default colors for unknown languages [#113](https://github.com/McShelby/hugo-theme-relearn/issues/113)
### Fixes
- [**bug**] security: fix XSS for malicioius URLs [#114](https://github.com/McShelby/hugo-theme-relearn/issues/114)
- [**bug**] menu: write correct local shortcut links [#112](https://github.com/McShelby/hugo-theme-relearn/issues/112)
---
## 2.4.1 (2021-10-07)
### Fixes
- [**bug**] theme: remove runtime styles from print [#111](https://github.com/McShelby/hugo-theme-relearn/issues/111)
---
## 2.4.0 (2021-10-07)
### Enhancements
- [**feature**] lang: add vietnamese translation [#109](https://github.com/McShelby/hugo-theme-relearn/issues/109)
- [**feature**][**change**] theme: simplify stylesheet for color variants [#107](https://github.com/McShelby/hugo-theme-relearn/issues/107)
- [**feature**] hidden pages: remove from RSS feed, JSON, taxonomy etc [#102](https://github.com/McShelby/hugo-theme-relearn/issues/102)
- [**feature**] theme: announce alternative content in header [#101](https://github.com/McShelby/hugo-theme-relearn/issues/101)
- [**feature**] menu: frontmatter option to change sort predicate [#98](https://github.com/McShelby/hugo-theme-relearn/issues/98)
- [**feature**] menu: add default setting for menu expansion [#97](https://github.com/McShelby/hugo-theme-relearn/issues/97)
- [**feature**] theme: improve print style [#93](https://github.com/McShelby/hugo-theme-relearn/issues/93)
- [**feature**] theme: improve style [#92](https://github.com/McShelby/hugo-theme-relearn/issues/92)
### Fixes
- [**bug**] include: don't generate additional HTML if file should be displayed "as is" [#110](https://github.com/McShelby/hugo-theme-relearn/issues/110)
- [**bug**] attachments: fix broken links if multilang config is used [#105](https://github.com/McShelby/hugo-theme-relearn/issues/105)
- [**bug**] theme: fix sticky header to remove horizontal scrollbar [#82](https://github.com/McShelby/hugo-theme-relearn/issues/82)
### Maintenance
- [**task**] chore: update fontawesome [#94](https://github.com/McShelby/hugo-theme-relearn/issues/94)
---
## 2.3.2 (2021-09-20)
### Fixes
- [**bug**] docs: rename history pirate translation [#91](https://github.com/McShelby/hugo-theme-relearn/issues/91)
---
## 2.3.1 (2021-09-20)
### Fixes
- [**bug**] docs: rename english pirate translation to avoid crash on rendering [#90](https://github.com/McShelby/hugo-theme-relearn/issues/90)
---
## 2.3.0 (2021-09-13)
### Fixes
- [**bug**] theme: fix usage of section element [#88](https://github.com/McShelby/hugo-theme-relearn/issues/88)
### Maintenance
- [**task**] theme: ensure IE11 compatiblity [#89](https://github.com/McShelby/hugo-theme-relearn/issues/89)
- [**task**] docs: Arrr! showcase multilang featurrre [#87](https://github.com/McShelby/hugo-theme-relearn/issues/87)
---
## 2.2.0 (2021-09-09)
### Enhancements
- [**feature**] sitemap: hide hidden pages from sitemap and SEO indexing [#85](https://github.com/McShelby/hugo-theme-relearn/issues/85)
### Fixes
- [**bug**] theme: fix showVisitedLinks in case Hugo is configured to modify relative URLs [#86](https://github.com/McShelby/hugo-theme-relearn/issues/86)
### Maintenance
- [**task**] theme: switch from data-vocabulary to schema [#84](https://github.com/McShelby/hugo-theme-relearn/issues/84)
---
## 2.1.0 (2021-09-07)
### Enhancements
- [**feature**] search: open expand if it contains search term [#80](https://github.com/McShelby/hugo-theme-relearn/issues/80)
- [**feature**] menu: scroll active item into view [#79](https://github.com/McShelby/hugo-theme-relearn/issues/79)
- [**feature**] search: disable search in hidden pages [#76](https://github.com/McShelby/hugo-theme-relearn/issues/76)
- [**feature**] search: improve readablility of index.json [#75](https://github.com/McShelby/hugo-theme-relearn/issues/75)
- [**feature**] search: increase performance [#74](https://github.com/McShelby/hugo-theme-relearn/issues/74)
- [**feature**] search: improve search context preview [#73](https://github.com/McShelby/hugo-theme-relearn/issues/73)
### Fixes
- [**bug**][**change**] search: hide non-site content [#81](https://github.com/McShelby/hugo-theme-relearn/issues/81)
- [**bug**] menu: always hide hidden sub pages [#77](https://github.com/McShelby/hugo-theme-relearn/issues/77)
---
## 2.0.0 (2021-08-28)
### Enhancements
- [**feature**] tabs: enhance styling [#65](https://github.com/McShelby/hugo-theme-relearn/issues/65)
- [**feature**] theme: improve readability [#64](https://github.com/McShelby/hugo-theme-relearn/issues/64)
- [**feature**] menu: show hidden pages if accessed directly [#60](https://github.com/McShelby/hugo-theme-relearn/issues/60)
- [**feature**][**change**] theme: treat pages without title as hidden [#59](https://github.com/McShelby/hugo-theme-relearn/issues/59)
- [**feature**] search: show search results if field gains focus [#58](https://github.com/McShelby/hugo-theme-relearn/issues/58)
- [**feature**] theme: add partial templates for pre/post menu entries [#56](https://github.com/McShelby/hugo-theme-relearn/issues/56)
- [**feature**] theme: make chapter archetype more readable [#55](https://github.com/McShelby/hugo-theme-relearn/issues/55)
- [**feature**] children: add parameter for container style [#53](https://github.com/McShelby/hugo-theme-relearn/issues/53)
- [**feature**] theme: make content a template [#50](https://github.com/McShelby/hugo-theme-relearn/issues/50)
- [**feature**] menu: control menu expansion with alwaysopen parameter [#49](https://github.com/McShelby/hugo-theme-relearn/issues/49)
- [**feature**] include: new shortcode to include other files [#43](https://github.com/McShelby/hugo-theme-relearn/issues/43)
- [**feature**] theme: adjust print styles [#35](https://github.com/McShelby/hugo-theme-relearn/issues/35)
- [**feature**][**change**] code highligher: switch to standard hugo highlighter [#32](https://github.com/McShelby/hugo-theme-relearn/issues/32)
### Fixes
- [**bug**][**change**] arrow-nav: default sorting ignores ordersectionsby [#63](https://github.com/McShelby/hugo-theme-relearn/issues/63)
- [**bug**][**change**] children: default sorting ignores ordersectionsby [#62](https://github.com/McShelby/hugo-theme-relearn/issues/62)
- [**bug**][**change**] arrow-nav: fix broken links on (and below) hidden pages [#61](https://github.com/McShelby/hugo-theme-relearn/issues/61)
- [**bug**] theme: remove superflous singular taxonomy from taxonomy title [#46](https://github.com/McShelby/hugo-theme-relearn/issues/46)
- [**bug**][**change**] theme: missing --MENU-HOME-LINK-HOVER-color in documentation [#45](https://github.com/McShelby/hugo-theme-relearn/issues/45)
- [**bug**] theme: fix home link when base URL has some path [#44](https://github.com/McShelby/hugo-theme-relearn/issues/44)
### Maintenance
- [**task**] docs: include changelog in exampleSite [#33](https://github.com/McShelby/hugo-theme-relearn/issues/33)
---
## 1.2.0 (2021-07-26)
### Enhancements
- [**feature**] theme: adjust copy-to-clipboard [#29](https://github.com/McShelby/hugo-theme-relearn/issues/29)
- [**feature**] attachments: adjust style between notice boxes and attachments [#28](https://github.com/McShelby/hugo-theme-relearn/issues/28)
- [**feature**] theme: adjust blockquote contrast [#27](https://github.com/McShelby/hugo-theme-relearn/issues/27)
- [**feature**] expand: add option to open on page load [#25](https://github.com/McShelby/hugo-theme-relearn/issues/25)
- [**feature**] expand: rework styling [#24](https://github.com/McShelby/hugo-theme-relearn/issues/24)
- [**feature**] attachments: sort output [#23](https://github.com/McShelby/hugo-theme-relearn/issues/23)
- [**feature**] notice: make restyling of notice boxes more robust [#20](https://github.com/McShelby/hugo-theme-relearn/issues/20)
- [**feature**] notice: fix contrast issues [#19](https://github.com/McShelby/hugo-theme-relearn/issues/19)
- [**feature**] notice: align box colors to common standards [#18](https://github.com/McShelby/hugo-theme-relearn/issues/18)
- [**feature**] notice: use distinct icons for notice box type [#17](https://github.com/McShelby/hugo-theme-relearn/issues/17)
### Fixes
- [**bug**] attachments: support i18n for attachment size [#21](https://github.com/McShelby/hugo-theme-relearn/issues/21)
- [**bug**] notice: support i18n for box labels [#16](https://github.com/McShelby/hugo-theme-relearn/issues/16)
- [**bug**] notice: support multiple blocks in one box [#15](https://github.com/McShelby/hugo-theme-relearn/issues/15)
### Maintenance
- [**task**] dependency: upgrade jquery to 3.6.0 [#30](https://github.com/McShelby/hugo-theme-relearn/issues/30)
---
## 1.1.1 (2021-07-04)
### Maintenance
- [**task**] theme: prepare for new hugo theme registration [#13](https://github.com/McShelby/hugo-theme-relearn/issues/13)
---
## 1.1.0 (2021-07-02)
### Enhancements
- [**feature**] mermaid: expose options in config.toml [#4](https://github.com/McShelby/hugo-theme-relearn/issues/4)
### Fixes
- [**bug**] mermaid: config option for CDN url not used [#12](https://github.com/McShelby/hugo-theme-relearn/issues/12)
- [**bug**] mermaid: only highlight text in HTML elements [#10](https://github.com/McShelby/hugo-theme-relearn/issues/10)
- [**bug**] mermaid: support pan & zoom for graphs [#9](https://github.com/McShelby/hugo-theme-relearn/issues/9)
- [**bug**] mermaid: code fences not always rendered [#6](https://github.com/McShelby/hugo-theme-relearn/issues/6)
- [**bug**] mermaid: search term on load may bomb chart [#5](https://github.com/McShelby/hugo-theme-relearn/issues/5)
### Maintenance
- [**task**] mermaid: update to 8.10.2 [#7](https://github.com/McShelby/hugo-theme-relearn/issues/7)
---
## 1.0.1 (2021-07-01)
### Maintenance
- [**task**] Prepare for hugo showcase [#3](https://github.com/McShelby/hugo-theme-relearn/issues/3)
---
## 1.0.0 (2021-07-01)
### Maintenance
- [**task**] Fork project [#1](https://github.com/McShelby/hugo-theme-relearn/issues/1)

View File

@ -0,0 +1,11 @@
+++
chapter = true
title = "Basics"
weight = 1
+++
### Chapter 1
# Basics
Discover what this Hugo theme is all about and the core-concepts behind it.

View File

@ -0,0 +1,6 @@
+++
chapter = true
title = "Basics"
weight = 1
+++
{{< piratify >}}

View File

@ -0,0 +1,160 @@
+++
title = "Configuration"
weight = 20
+++
## Global site parameters
On top of [Hugo global configuration](https://gohugo.io/overview/configuration/), the Relearn theme lets you define the following parameters in your `config.toml` (here, values are default).
Note that some of these parameters are explained in details in other sections of this documentation.
```toml
[params]
# This controls whether submenus will be expanded (true), or collapsed (false) in the
# menu; if no setting is given, the first menu level is set to false, all others to true;
# this can be overridden in the pages frontmatter
alwaysopen = true
# Prefix URL to edit current page. Will display an "Edit" button on top right hand corner of every page.
# Useful to give opportunity to people to create merge request for your doc.
# See the config.toml file from this documentation site to have an example.
editURL = ""
# Author of the site, will be used in meta information
author = ""
# Description of the site, will be used in meta information
description = ""
# Shows a checkmark for visited pages on the menu
showVisitedLinks = false
# Disable search function. It will hide search bar
disableSearch = false
# Disable search in hidden pages, otherwise they will be shown in search box
disableSearchHiddenPages = false
# Disables hidden pages from showing up in the sitemap and on Google (et all), otherwise they may be indexed by search engines
disableSeoHiddenPages = false
# Disables hidden pages from showing up on the tags page although the tag term will be displayed even if all pages are hidden
disableTagHiddenPages = false
# Javascript and CSS cache are automatically busted when new version of site is generated.
# Set this to true to disable this behavior (some proxies don't handle well this optimization)
disableAssetsBusting = false
# Set this to true to disable copy-to-clipboard button for inline code.
disableInlineCopyToClipBoard = false
# A title for shortcuts in menu is set by default. Set this to true to disable it.
disableShortcutsTitle = false
# If set to false, a Home button will appear below the search bar on the menu.
# It is redirecting to the landing page of the current language if specified. (Default is "/")
disableLandingPageButton = true
# When using mulitlingual website, disable the switch language button.
disableLanguageSwitchingButton = false
# Hide breadcrumbs in the header and only show the current page title
disableBreadcrumb = true
# If set to true, hide table of contents menu in the header of all pages
disableToc = false
# If set to false, load the Mermaid module on every page regardless if a Mermaid shortcode or Mermaid codefence is present
disableMermaid = false
# Specifies the remote location of the Mermaid js
customMermaidURL = "https://unpkg.com/mermaid/dist/mermaid.min.js"
# Initialization parameter for Mermaid, see Mermaid documentation
mermaidInitialize = "{ \"theme\": \"default\" }"
# If set to false, load the Swagger module on every page regardless if a Swagger shortcode is present
disableSwagger = false
# Specifies the remote location of the RapiDoc js
customSwaggerURL = ""https://unpkg.com/rapidoc/dist/rapidoc-min.js"
# Initialization parameter for Swagger, see RapiDoc documentation
swaggerInitialize = "{ \"theme\": \"light\" }"
# Hide Next and Previous page buttons normally displayed full height beside content
disableNextPrev = true
# Order sections in menu by "weight" or "title". Default to "weight";
# this can be overridden in the pages frontmatter
ordersectionsby = "weight"
# Change default color scheme with a variant one. Eg. can be "red", "blue", "green" or an array like [ "blue", "green" ].
themeVariant = "relearn-light"
# Change the title separator. Default to "::".
titleSeparator = "-"
# If set to true, the menu in the sidebar will be displayed in a collapsible tree view.
collapsibleMenu = false
```
## A word on running your site in a subfolder
The theme runs best if your site is installed in the root of your webserver. If your site is served from a subfolder, eg. `https://example.com/mysite/`, you have to set the following lines to your `config.toml`
````toml
baseURL = "https://example.com/mysite/"
canonifyURLs = true
````
Without `canonifyURLs=true` URLs in sublemental pages (like `sitemap.xml`, `rss.xml`) will be generated falsly while your HTML files will still work. See https://github.com/gohugoio/hugo/issues/5226.
## Activate search
If not already present, add the follow lines in the same `config.toml` file.
```toml
[outputs]
home = ["HTML", "RSS", "JSON"]
```
Relearn theme uses the last improvement available in hugo version 20+ to generate a json index file ready to be consumed by lunr.js javascript search engine.
> Hugo generate lunrjs index.json at the root of public folder.
> When you build the site with `hugo server`, hugo generates it internally and of course it doesnt show up in the filesystem
## Activate print support
You can activate print support to add the capability to print whole chapters or even the complete site. Just add the `PRINT` output format to your home, section and page in your `config.toml` as seen below:
```toml
[outputs]
home = ["HTML", "RSS", "PRINT", "JSON"]
section = ["HTML", "RSS", "PRINT"]
page = ["HTML", "RSS", "PRINT"]
```
This will add a little printer icon in the top bar. It will switch the page to print preview when clicked. You can then send this page to the printer by using your browser's usual print functionality.
{{% notice note %}}
While colors of your chosen color variant are reset to the theme's light standard values for printing, this does not apply for Mermaid diagrams and Swagger/OpenAPI Specification. Those will still use the colors of your chosen color variant which may cause a non coherent look on paper.
{{% /notice %}}
## Mermaid
The Mermaid configuration parameters can also be set on a specific page. In this case, the global parameter would be overwritten by the local one. See [Mermaid]({{< relref "shortcodes/mermaid" >}}) for additional documentation.
> Example:
>
> Mermaid is globally disabled. By default it won't be loaded by any page.
> On page "Architecture" you need a class diagram. You can set the Mermaid parameters locally to only load mermaid on this page (not on the others).
You also can disable Mermaid for specific pages while globally enabled.
## Home Button Configuration
If the `disableLandingPageButton` option is set to `false`, a Home button will appear
on the left menu. It is an alternative for clicking on the logo. To edit the
appearance, you will have to configure two parameters for the defined languages:
```toml
[Languages]
[Languages.en]
...
landingPageURL = "/"
landingPageName = "<i class='fas fa-home'></i> Home"
...
[Languages.pir]
...
landingPageURL = "/pir/"
landingPageName = "<i class='fas fa-home'></i> Arrr! Homme"
...
```
If those params are not configured for a specific language, they will get their
default values:
```toml
landingPageURL = "/"
landingPageName = "<i class='fas fa-home'></i> Home"
```
The home button is going to look like this:
![Default Home Button](images/home_button_defaults.png?classes=shadow&width=300px)

View File

@ -0,0 +1,5 @@
+++
title = "Configurrrat'n"
weight = 20
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,81 @@
+++
title = "Customization"
weight = 25
+++
The Relearn theme has been built to be as configurable as possible by defining multiple [partials](https://gohugo.io/templates/partials/)
In `themes/hugo-theme-relearn/layouts/partials/`, you will find all the partials defined for this theme. If you need to overwrite something, don't change the code directly. Instead [follow this page](https://gohugo.io/themes/customizing/). You'd create a new partial in the `layouts/partials` folder of your local project. This partial will have the priority.
This theme defines the following partials :
- `header.html`: the header of the page. _Not meant to be overwritten_
- `footer.html`: the footer of the page._Not meant to be overwritten_
- `menu.html`: left menu. _Not meant to be overwritten_
- `search.html`: search box. _Not meant to be overwritten_
- `custom-header.html`: custom headers in page. Meant to be overwritten when adding CSS imports. Don't forget to include `style` HTML tag directive in your file.
- `custom-footer.html`: custom footer in page. Meant to be overwritten when adding Javacript. Don't forget to include `javascript` HTML tag directive in your file.
- `favicon.html`: the favicon
- `logo.html`: the logo, on top left hand corner
- `meta.html`: HTML meta tags, if you want to change default behavior
- `menu-pre.html`: side-wide configuration to prepend to menu items. If you override this, it is your responsiblity to take the page's `pre` setting into account.
- `menu-post.html`: side-wide configuration to append to menu items. If you override this, it is your responsiblity to take the page's `post` setting into account.
- `menu-footer.html`: footer of the the left menu
- `toc.html`: table of contents
- `content.html`: the content page itself. This can be overridden if you wan't to display page's meta data above or below the content.
- `content-footer`: footer below the content, has a default implementation but you can overwrite it if you don't like it.
## Change the logo
Create a new file in `layouts/partials/` named `logo.html`. Then write any HTML you want.
You could use an `img` HTML tag and reference an image created under the *static* folder, or you could paste a SVG definition!
{{% notice note %}}
The size of the logo will adapt automatically
{{% /notice %}}
## Change the favicon
If your favicon is a SVG, PNG or ICO, just drop off your image in your local `static/images/` folder and name it `favicon.svg`, `favicon.png` or `favicon.ico` respectivly.
If no favicon file is found, the theme will lookup the alternative filename `logo` in the same location and will repeat the search for the list of supported file types.
If you need to change this default behavior, create a new file in `layouts/partials/` named `favicon.html`. Then write something like this:
```html
<link rel="icon" href="/images/favicon.bmp" type="image/bmp" />
```
## Change the colors {#theme-variant}
The Relearn theme lets you choose between some predefined color variants in light or dark mode, but feel free to add one yourself!
You can preview the shipped variants by changing them in the variant selector at the bottom of the menu.
### Single variant
Set the `themeVariant` value with the name of your theme file. That's it!
```toml
[params]
themeVariant = "relearn-light"
```
In the above exaple your theme file has to be named `theme-relearn-light.css`
### Multiple variants
You can also set multiple variants. In this case, the first variant is the default choosen on first view and a variant switch will be shown in the menu footer.
```toml
[params]
# Change default color scheme with a variant one.
themeVariant = [ "relearn-light", "relearn-dark" ]
```
{{% notice tip %}}
If you want to switch the syntax highlightning theme together with your color variant, generate a syntax highlighting stylesheet and configure your installation [according to Hugo's documentation](https://gohugo.io/content-management/syntax-highlighting/), and `@import` this stylesheet in your color variant stylesheet. For an example, take a look into `theme-relearn-light.css` and `config.toml` of the exampleSite.
{{% /notice %}}
### Roll your own
If you are not happy with the shipped variants you can either copy one of the shipped files, edit them in a text editor and configure the `themeVariant` parameter in your `config.toml` or just use the [interactive variant generator]({{%relref "basics/generator" %}}).

View File

@ -0,0 +1,5 @@
+++
title = "Customizat'n"
weight = 25
+++
{{< piratify >}}

View File

@ -0,0 +1,37 @@
+++
disableMermaid = false
title = "Stylesheet generator"
weight = 26
+++
This interactive tool may help you to generate your own color variant stylesheet.
To get started, first select a color variant from the variant switch that fits you best as a starting point.
The graph is interactive and reflect the current colors. You can click on any of the colored boxes to adjust the respective color. The graph and the page will update accordingly.
The arrowed lines reflects how colors are inherited thru different parts of the theme if the descendent isn't overwritten. If you want to delete a color and let it inherit from its parent, just delete the value from the input field.
To better understand this select the `neon` variant and modify the differnet heading colors. There, colors for the heading `h2`, `h3` and `h4` are explicitly set. `h5` is not set and inherits its value from `h4`. `h6` is also not set and inherits its value from `h5`.
Once you've changed a color, the variant switch will show a "My custom variant" entry and your changes are stored in the browser. You can change pages and even close the browser without losing your changes.
Once you are satisfied, you can download the new variants file and install it in your site.
{{% notice note %}}
This only works in modern browsers.
{{% /notice %}}
## Variant generator
<span class="btn cstyle secondary"><a class="vardownload"><i class="fa-fw fas fa-download"></i> Download variant</a></span>
<span class="btn cstyle warning"><a class="varreset"><i class="fa-fw fas fa-trash"></i> Reset variant</a></span>
<div id="vargenerator" class="mermaid" style="background-color: var(--INTERNAL-MAIN-TEXT-color);" align="center">Graph</div>
<span class="btn cstyle secondary"><a class="vardownload"><i class="fa-fw fas fa-download"></i> Download variant</a></span>
<span class="btn cstyle warning"><a class="varreset"><i class="fa-fw fas fa-trash"></i> Reset variant</a></span>
<script>
variants.generator( '#vargenerator', '.vardownload', '.varreset' );
</script>

View File

@ -0,0 +1,5 @@
+++
title = "Stylesheet generrrat'r"
weight = 26
+++
{{< piratify >}}

View File

@ -0,0 +1,6 @@
+++
disableToc = false
title = "History"
weight = 30
+++
{{% include "basics/CHANGELOG.md" false %}}

View File

@ -0,0 +1,6 @@
+++
disableToc = false
title = "Historrry"
weight = 30
+++
{{< piratify >}}

View File

@ -0,0 +1,102 @@
+++
title = "Installation"
weight = 15
+++
The following steps are here to help you initialize your new website. If you don't know Hugo at all, we strongly suggest you learn more about it by following this [great documentation for beginners](https://gohugo.io/overview/quickstart/).
## Create your project
Hugo provides a `new` command to create a new website.
```
hugo new site <new_project>
```
## Install the theme
Install the Relearn theme by following [this documentation](https://gohugo.io/getting-started/quick-start/#step-3-add-a-theme)
This theme's repository is: https://github.com/McShelby/hugo-theme-relearn.git
Alternatively, you can [download the theme as .zip](https://github.com/McShelby/hugo-theme-relearn/archive/main.zip) file and extract it in the `themes` directory
## Basic configuration
When building the website, you can set a theme by using `--theme` option. However, we suggest you modify the configuration file (`config.toml`) and set the theme as the default. You can also add the `[outputs]` section to enable the search functionality.
```toml
# Change the default theme to be use when building the site with Hugo
theme = "hugo-theme-relearn"
# For search functionality
[outputs]
home = [ "HTML", "RSS", "JSON"]
```
## Create your first chapter page
Chapters are pages that contain other child pages. It has a special layout style and usually just contains a _chapter name_, the _title_ and a _brief abstract_ of the section.
```markdown
### Chapter 1
# Basics
Discover what this Hugo theme is all about and the core concepts behind it.
```
renders as
![A Chapter](images/chapter.png?classes=shadow&width=60pc)
The Relearn theme provides archetypes to create skeletons for your website. Begin by creating your first chapter page with the following command
```shell
hugo new --kind chapter basics/_index.md
```
By opening the given file, you should see the property `chapter=true` on top, meaning this page is a _chapter_.
By default all chapters and pages are created as a draft. If you want to render these pages, remove the property `draft: true` from the metadata.
## Create your first content pages
Then, create content pages inside the previously created chapter. Here are two ways to create content in the chapter:
```shell
hugo new basics/first-content.md
hugo new basics/second-content/_index.md
```
Feel free to edit those files by adding some sample content and replacing the `title` value in the beginning of the files.
## Launching the website locally
Launch by using the following command:
```shell
hugo serve
```
Go to `http://localhost:1313`
You should notice three things:
1. You have a left-side **Basics** menu, containing two submenus with names equal to the `title` properties in the previously created files.
2. The home page explains how to customize it by following the instructions.
3. When you run `hugo serve`, when the contents of the files change, the page automatically refreshes with the changes. Neat!
## Build the website
When your site is ready to deploy, run the following command:
```shell
hugo
```
A `public` folder will be generated, containing all static content and assets for your website. It can now be deployed on any web server.
{{% notice note %}}
This website can be automatically published and hosted with [Netlify](https://www.netlify.com/) (Read more about [Automated HUGO deployments with Netlify](https://www.netlify.com/blog/2015/07/30/hosting-hugo-on-netlifyinsanely-fast-deploys/)). Alternatively, you can use [GitHub pages](https://gohugo.io/hosting-and-deployment/hosting-on-github/)
{{% /notice %}}

View File

@ -0,0 +1,5 @@
+++
title = "Installat'n"
weight = 15
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -0,0 +1,247 @@
+++
disableToc = false
title = "What's new"
weight = 2
+++
This document shows you what's new in the latest release. For a detailed list of changes, see the [history page]({{%relref "basics/history" %}}).
**Breaking**: A change that requires action by you after upgrading to assure the site is still functional.
**Change**: A change in default behavior. This may requires action by you / may or may not be revertable by configuration.
**New**: Marks new behavior you might find interesting or comes configurable.
---
## 4.0.0
- **Breaking**: The `custom_css` config parameter was removed from the configuration. If used in an existing installation, it can be achieved by overriding the `custom-header.html` template in a much more generic manner.
- **Breaking**: Because anchor hover color was not configurable without introducing more complexitity to the variant stylesheets, we decided to remove `--MAIN-ANCHOR-color` instead. You don't need to change anything in your custom color stylesheet as the anchors now get their colors from `--MAIN-LINK-color` and `--MAIN-ANCHOR-HOVER-color` respectivley.
- **New**: All shortcodes now support named parameter. The positional parameter are still supported but will not be enhanced with new features, so you don't need to change anything in your installation.
This applies to [`expand`]({{% relref "shortcodes/expand" %}}) , [`include`]({{% relref "shortcodes/include" %}}) , [`notice`]({{% relref "shortcodes/notice" %}}) and [`siteparam`]({{% relref "shortcodes/siteparam" %}}) .
- **New**: The [`button`]({{% relref "shortcodes/button" %}}) shortcode received some love and now has a parameter for the color style similar to other shortcodes.
- **New**: New colors `--PRIMARY-color` and `--SECONDARY-color` were added to provide easier modification of your custom style. Shortcodes with a color style can now have `primary` or `secondary` as additional values.
These two colors are the default for other, more specific color variables. You don't need to change anything in your existing custom color stylesheets as those variables get reasonable default values.
- **New**: The documentation for all shortcodes were revised.
---
## 3.4.0
- **Breaking**: If you had previously overwritten the `custom-footer.html` partial to add visual elements below the content of your page, you have to move this content to the new partial `content-footer.html`. `custom-footer.html` was never meant to contain HTML other than additional styles and JavaScript.
- **New**: If you prefer expandable/collapsible menu items, you can now set `collapsibleMenu=true` in your `config.toml`. This will add arrows to all menu items that contain sub menus. The menu will expand/collapse without navigation if you click on an arrow.
- **New**: You can activate [print support]({{%relref "basics/configuration#activate-print-support" %}}) in your `config.toml` to add the capability to print whole chapters or even the complete site.
- **New**: Translation for Traditional Chinese.
---
## 3.3.0
- **New**: Introduction of new CSS variables to set the font. The theme distinguishs between `--MAIN-font` for all content text and `--CODE-font` for inline or block code. There are additional overrides for all headings. See the [theme variant generator]({{%relref "basics/generator" %}}) of the exampleSite for all available variables.
- **New**: The new shortcode `swagger` is available to include a UI for REST OpenAPI Specifications. See the [documentation]({{% relref "shortcodes/swagger" %}}) for available features. This feature will not work with Internet Explorer 11.
---
## 3.2.0
- **Change**: In this release the Mermaid JavaScript library will only be loaded on demand if the page contains a Mermaid shortcode or is using Mermaid codefences. This changes the behavior of `disableMermaid` config option as follows: If a Mermaid shortcode or codefence is found, the option will be ignored and Mermaid will be loaded regardlessly.
The option is still useful in case you are using scripting to set up your graph. In this case no shortcode or codefence is involved and the library is not loaded by default. In this case you can set `disableMermaid=false` in your frontmatter to force the library to be loaded. See the [theme variant generator]({{%relref "basics/generator" %}}) of the exampleSite for an example.
**This change requires at least Hugo 0.93.0 to be used**. The minimum requirement will be reported during build on the console if not met.
- **New**: Additional color variant variable `--MERMAID-theme` to set the variant's Mermaid theme. This causes the Mermaid theme to switch with the color variant if it defers from the setting of the formerly selected color variant.
---
## 3.1.0
- **New**: [`attachment`]({{% relref "shortcodes/attachments" %}}) and [`notice`]({{% relref "shortcodes/notice" %}}) shortcodes have a new parameter to override the default icon. Allowed values are all [Font Awesome 5 Free](https://fontawesome.com/v5/search?m=free) icons.
---
## 3.0.0
- **Breaking**: We made changes to the menu footer. If you have your `menu-footer.html` [partial overridden]({{%relref "basics/customization" %}}), you may have to review the styling (eg. margins/paddings) in your partial. For a reference take a look into the `menu-footer.html` partial that is coming with the exampleSite.
This change was made to allow your own menu footer to be placed right after the so called prefooter that comes with the theme (containing the language switch and *Clear history* functionality).
- **Breaking**: We have changed the default colors from the original Learn theme (the purple menu header) to the Relearn defaults (the light green menu header) as used in the official documentation.
This change will only affect your installation if you've not set the `themeVariant` parameter in your `config.toml`. [If you still want to use the Learn color variant]({{%relref "basics/customization/#theme-variant" %}}), you have to explicitly set `themeVariant="learn"` in your `config.toml`.
Note, that this will also affect your site if viewed with Internet Explorer 11 but in this case it can not be reconfigured as Internet Explorer does not support CSS variables.
- **Change**: Due to a bug, that we couldn't fix in a general manner for color variants, we decided to remove `--MENU-SEARCH-BOX-ICONS-color` and introduced `--MENU-SEARCH-color` instead. You don't need to change anything in your custom color stylesheet as the old name will be used as a fallback.
- **Change**: For consistency reasons, we renamed `--MENU-SEARCH-BOX-color` to `--MENU-SEARCH-BORDER-color`. You don't need to change anything in your custom color stylesheet as the old name will be used as a fallback.
- **New**: With this release you are now capable to define your own *dark mode* variants.
To make this possible, we have introduced a lot more color variables you can use in [your color variants]({{%relref "basics/customization/#theme-variant" %}}). Your old variants will still work and don't need to be changed as apropriate fallback values are used by the theme. Nevertheless, the new colors allow for much more customization.
To see what's now possible, see the new variants `relearn-dark` and `neon` that are coming with this release.
- **New**: To make the creation of new variants easier for you, we've added a new interactive [theme variant generator]({{%relref "basics/generator" %}}). This feature will not work with Internet Explorer 11.
- **New**: You can now configure multiple color variants in your `config.toml`. In this case, the first variant is the default chosen on first view and a variant switch will be shown in the menu footer. See the [documentation]({{%relref "basics/customization/#multiple-variants" %}}) for configuration.
Note, that the new variant switch will not work with Internet Explorer 11 as it does not support CSS variables. Therefore, the variant switcher will not be displayed with Internet Explorer 11.
---
## 2.9.0
- **Breaking**: This release removes the themes implementation of `ref`/`relref` in favor for Hugos standard implementation. This is because of inconsistencies with the themes implementation. In advantage, your project becomes standard complient and exchanging this theme in your project to some other theme will be effortless.
In a standard complient form you must not link to the `*.md` file but to its logical name. You'll see, referencing other pages becomes much easier. All three types result in the same reference:
| Type | Non-Standard | Standard |
| ------------- | -------------------------------- | ---------------------- |
| Branch bundle | `basics/configuration/_index.md` | `basics/configuration` |
| Leaf bundle | `basics/configuration/index.md` | `basics/configuration` |
| Page | `basics/configuration.md` | `basics/configuration` |
If you've linked from a page of one language to a page of another language, conversion is a bit more difficult but [Hugo got you covered](https://gohugo.io/content-management/cross-references/#link-to-another-language-version) as well.
Also, the old themes implementation allowed refs to non-existing content. This will cause Hugos implementation to show the error below and abort the generation. If your project relies on this old behavior, you can [reconfigure the error handling](https://gohugo.io/content-management/cross-references/#link-to-another-language-version) of Hugos implementation.
In the best case your usage of the old implementation is already standard complient and you don't need to change anything. You'll notice this very easily once you've started `hugo server` after an upgrade and no errors are written to the console.
You may see errors on the console after the update in the form:
````sh
ERROR 2021/11/19 22:29:10 [en] REF_NOT_FOUND: Ref "basics/configuration/_index.md": "hugo-theme-relearn\exampleSite\content\_index.en.md:19:22": page not found
````
In this case, you must apply one of two options:
1. Copy the old implementation files `theme/hugo-theme-relearn/layouts/shortcode/ref.html` and `theme/hugo-theme-relearn/layouts/shortcode/relref.html` to your own projects `layouts/shortcode/ref.html` and `layouts/shortcode/relref.html` respectively. **This is not recommended** as your project will still rely on non-standard behavior afterwards.
2. Start up a text editor with regular expression support for search and replace. Apply the following conversions in the given order on all `*.md` files. **This is the recommended choice**.
| Type | Search | Replace by |
| ------------- | ---------------------------- | ---------- |
| Branch bundle | `(ref\s+"[^"]*)/_index\.md"` | `$1"` |
| Leaf bundle | `(ref\s+"[^"]*)/index\.md"` | `$1"` |
| Page | `(ref\s+"[^"]*)\.md"` | `$1"` |
---
## 2.8.0
- **Change**: Although never officially documented, this release removes the font `Novacento`/`Novecento`. If you use it in an overwritten CSS please replace it with `Work Sans`. This change was necessary as Novacento did not provide all Latin special characters and lead to mixed styled character text eg. for czech.
- **New**: The theme now supports favicons served from `static/images/` named as `favicon` or `logo` in SVG, PNG or ICO format [out of the box]({{% relref "basics/customization/#change-the-favicon" %}}). An overridden partial `layouts/partials/favicon.html` may not be necessary anymore in most cases.
- **New**: You can hide the table of contents menu for the whole site by setting the `disableToc` option in your `config.toml`. For an example see [the example configuration]({{%relref "basics/configuration/#global-site-parameters" %}}).
---
## 2.7.0
- **New**: Optional second parameter for [`notice`]({{% relref "shortcodes/notice" %}}) shortcode to set title in box header.
---
## 2.6.0
- **New**: Your site can now be served from a subfolder if you set `baseURL` and `canonifyURLs=true` in your `config.toml`. See the [documentation]({{% relref "basics/configuration/#a-word-on-running-your-site-in-a-subfolder" %}}) for a detailed example.
---
## 2.5.0
- **Change**: New colors `--CODE-BLOCK-color` and `--CODE-BLOCK-BG-color` were added to provide a fallback for Hugos syntax highlightning in case `guessSyntax=true` is set. Ideally the colors are set to the same values as the ones from your chosen chroma style.
---
## 2.4.0
- **Change**: Creation of customized stylesheets was simplified down to only contain the CSS variables. Everything else can and should be deleted from your custom stylesheet to assure everything works fine. For the predefined stylesheet variants, this change is already included.
- **New**: Hidden pages are displayed by default in their according tags page. You can now turn off this behavior by setting `disableTagHiddenPages=true` in your `config.toml`.
- **New**: You can define the expansion state of your menus for the whole site by setting the `alwaysopen` option in your `config.toml`. Please see further [documentation]({{%relref "cont/pages/#override-expand-state-rules-for-menu-entries" %}}) for possible values and default behavior.
- **New**: New frontmatter `ordersectionsby` option to change immediate children sorting in menu and `children` shortcode. Possible values are `title` or `weight`.
- **New**: Alternate content of a page is now advertised in the HTML meta tags. See [Hugo documentation](https://gohugo.io/templates/rss/#reference-your-rss-feed-in-head).
---
## 2.3.0
- **New**: Showcase multilanguage features by provding a documentation translation "fer us pirrrates". There will be no other translations besides the original English one and the Pirates one due to maintenance constraints.
---
## 2.2.0
- **New**: Hidden pages are displayed by default in the sitemap generated by Hugo and are therefore visible for search engine indexing. You can now turn off this behavior by setting `disableSeoHiddenPages=true` in your `config.toml`.
---
## 2.1.0
- **Change**: In case the site's structure contains addional *.md files not part of the site (eg files that are meant to be included by site pages - see `CHANGELOG.md` in the exampleSite), they will now be ignored by the search.
- **New**: Hidden pages are indexed for the site search by default. You can now turn off this behavior by setting `disableSearchHiddenPages=true` in your `config.toml`.
- **New**: If a search term is found in an `expand` shortcode, the expand will be opened.
- **New**: The menu will scroll the active item into view on load.
---
## 2.0.0
- **Change**: Syntaxhighlightning was switched to the [built in Hugo mechanism](https://gohugo.io/content-management/syntax-highlighting/). You may need to configure a new stylesheet or decide to roll you own as described on in the Hugo documentation
- **Change**: In the predefined stylesheets there was a typo and `--MENU-HOME-LINK-HOVERED-color` must be changed to `--MENU-HOME-LINK-HOVER-color`. You don't need to change anything in your custom color stylesheet as the old name will be used as a fallback.
- **Change**: `--MENU-HOME-LINK-color` and `--MENU-HOME-LINK-HOVER-color` were missing in the documentation. You should add them to your custom stylesheets if you want to override the defaults.
- **Change**: Arrow navigation and `children` shortcode were ignoring setting for `ordersectionsby`. This is now changed and may result in different sorting order of your sub pages.
- **Change**: If hidden pages are accessed directly by typing their URL, they will be exposed in the menu.
- **Change**: A page without a `title` will be treated as `hidden=true`.
- **New**: You can define the expansion state of your menus in the frontmatter. Please see further [documentation]({{%relref "cont/pages/#override-expand-state-rules-for-menu-entries" %}}) for possible values and default behavior.
- **New**: New partials for defining pre/post content for menu items and the content. See [documentation]({{% relref "basics/customization" %}}) for further reading.
- **New**: Shortcode [`children`]({{% relref "shortcodes/children" %}}) with new parameter `containerstyle`.
- **New**: New shortcode [`include`]({{% relref "shortcodes/include" %}}) to include arbitrary file content into a page.
---
## 1.2.0
- **New**: Shortcode [`expand`]({{% relref "shortcodes/expand" %}}) with new parameter to open on page load.
---
## 1.1.0
- **New**: [`Mermaid`]({{% relref "shortcodes/mermaid#configuration" %}}) config options can be set in `config.toml`.
---
## 1.0.0
- **New**: Initial fork of the [Learn theme](https://github.com/matcornic/hugo-theme-learn) based on Learn 2.5.0 on 2021-07-01. This introduces no new features besides a global rename to `Relearn` and a new logo. For the reasons behind forking the Learn theme, see [this comment](https://github.com/matcornic/hugo-theme-learn/issues/442#issuecomment-907863495) in the Learn issues.

View File

@ -0,0 +1,6 @@
+++
disableToc = false
title = "Migrrrat'n"
weight = 17
+++
{{< piratify >}}

View File

@ -0,0 +1,11 @@
+++
disableToc = true
title = "Requirements"
weight = 10
+++
Thanks to the simplicity of Hugo, this page is as empty as this theme needs requirements.
Just download latest version of [Hugo binary](https://gohugo.io/getting-started/installing/) for your OS (Windows, Linux, Mac) : it's that simple.
![Magic](images/magic.gif?classes=shadow)

View File

@ -0,0 +1,6 @@
+++
disableToc = true
title = "Requirrrements"
weight = 10
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -0,0 +1,11 @@
+++
chapter = true
title = "Content"
weight = 2
+++
### Chapter 2
# Content
Find out how to create and organize your content quickly and intuitively.

View File

@ -0,0 +1,6 @@
+++
chapter = true
title = "Rambl'n"
weight = 2
+++
{{< piratify >}}

View File

@ -0,0 +1,58 @@
+++
title = "Archetypes"
weight = 10
+++
Using the command: `hugo new [relative new content path]`, you can start a content file with the date and title automatically set. While this is a welcome feature, active writers need more: [archetypes](https://gohugo.io/content/archetypes/).
It is pre-configured skeleton pages with default front matter. Please refer to the documentation for types of page to understand the differences.
## Chapter {#archetypes-chapter}
To create a Chapter page, run the following commands
```shell
hugo new --kind chapter <name>/_index.md
```
It will create a page with predefined Front-Matter:
```toml
+++
chapter = true
pre = "<b>X. </b>"
title = "{{ replace .Name "-" " " | title }}"
weight = 5
+++
### Chapter X
# Some Chapter title
Lorem Ipsum.
```
## Default
To create a default page, run either one of the following commands either
```shell
hugo new <chapter>/<name>/_index.md
```
or
```shell
hugo new <chapter>/<name>.md
```
It will create a page with predefined Front-Matter:
```toml
+++
title = "{{ replace .Name "-" " " | title }}"
weight = 5
+++
Lorem Ipsum.
```

View File

@ -0,0 +1,5 @@
+++
title = "Arrrchetypes"
weight = 10
+++
{{< piratify >}}

View File

@ -0,0 +1,71 @@
+++
title = "Multilingual and i18n"
weight = 30
+++
The Relearn theme is fully compatible with Hugo multilingual mode.
It provides:
- Translation strings for default values (English, Piratized English, Arabic, Simplified Chinese, Traditional Chinesse, Dutch, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Polish, Portuguese, Russian, Spanish, Turkish, Vietnamese). Feel free to contribute!
- Automatic menu generation from multilingual content
- In-browser language switching
![I18n menu](images/i18n-menu.gif?classes=shadow&width=300px)
## Basic configuration
After learning [how Hugo handle multilingual websites](https://gohugo.io/content-management/multilingual), define your languages in your `config.toml` file.
For example with current English and Piratized English website.
```toml
# English is the default language
defaultContentLanguage = "en"
[Languages]
[Languages.en]
title = "Hugo Relearn Theme"
weight = 1
languageName = "English"
[Languages.pir]
title = "Cap'n Hugo Relearrrn Theme"
weight = 2
languageName = "Arrr! Pirrrates"
```
Then, for each new page, append the *id* of the language to the file.
- Single file `my-page.md` is split in two files:
- in English: `my-page.md`
- in Piratized English: `my-page.pir.md`
- Single file `_index.md` is split in two files:
- in English: `_index.md`
- in Piratized English: `_index.pir.md`
{{% notice info %}}
Be aware that only translated pages are displayed in menu. It's not replaced with default language content.
{{% /notice %}}
{{% notice tip %}}
Use [slug](https://gohugo.io/content-management/multilingual/#translate-your-content) Front Matter parameter to translate urls too.
{{% /notice %}}
## Overwrite translation strings
Translations strings are used for common default values used in the theme (*Edit* button, *Search placeholder* and so on). Translations are available in English and Piratized English but you may use another language or want to override default values.
To override these values, create a new file in your local i18n folder `i18n/<idlanguage>.toml` and inspire yourself from the theme `themes/hugo-theme-relearn/i18n/en.toml`
## Disable language switching
Switching the language in the browser is a great feature, but for some reasons you may want to disable it.
Just set `disableLanguageSwitchingButton=true` in your `config.toml`
```toml
[params]
# When using mulitlingual website, disable the switch language button.
disableLanguageSwitchingButton = true
```

View File

@ -0,0 +1,5 @@
+++
title = "Multilingual an' i18n"
weight = 30
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,41 @@
+++
title = "Icons and logos"
weight = 27
+++
The Relearn theme for Hugo loads the [**Font Awesome**](https://fontawesome.com) library, allowing you to easily display any icon or logo available in the Font Awesome free collection.
## Finding an icon
Browse through the available icons in the [Font Awesome Gallery](https://fontawesome.com/v5/search?m=free). Notice that the **free** filter is enabled, as only the free icons are available by default.
Once on the Font Awesome page for a specific icon, for example the page for the [heart](https://fontawesome.com/v5/icons/heart?s=solid), copy the HTML reference and paste into the Markdown content.
The HTML to include the heart icon is:
```html
<i class="fas fa-heart"></i>
```
## Including in markdown
Paste the `<i>` HTML into markup and Font Awesome will load the relevant icon.
```html
Built with <i class="fas fa-heart"></i> by Relearn and Hugo
```
Which appears as
Built with <i class="fas fa-heart"></i> by Relearn and Hugo
## Customising icons
Font Awesome provides many ways to modify the icon
* Change color (by default the icon will inherit the parent color)
* Increase or decrease size
* Rotate
* Combine with other icons
Check the full documentation on [web fonts with CSS](https://fontawesome.com/how-to-use/web-fonts-with-css) for more.

View File

@ -0,0 +1,5 @@
+++
title = "Ay'cons an' logos"
weight = 27
+++
{{< piratify >}}

View File

@ -0,0 +1,696 @@
+++
title = "Markdown syntax"
weight = 15
+++
Let's face it: Writing content for the Web is tiresome. WYSIWYG editors help alleviate this task, but they generally result in horrible code, or worse yet, ugly web pages.
**Markdown** is a better way to write **HTML**, without all the complexities and ugliness that usually accompanies it.
Some of the key benefits are:
1. Markdown is simple to learn, with minimal extra characters so it's also quicker to write content.
2. Less chance of errors when writing in Markdown.
3. Produces valid XHTML output.
4. Keeps the content and the visual display separate, so you cannot mess up the look of your site.
5. Write in any text editor or Markdown application you like.
6. Markdown is a joy to use!
John Gruber, the author of Markdown, puts it like this:
> The overriding design goal for Markdowns formatting syntax is to make it as readable as possible. The idea is that a Markdown-formatted document should be publishable as-is, as plain text, without looking like its been marked up with tags or formatting instructions. While Markdowns syntax has been influenced by several existing text-to-HTML filters, the single biggest source of inspiration for Markdowns syntax is the format of plain text email.
> <cite>John Gruber</cite>
Without further delay, let us go over the main elements of Markdown and what the resulting HTML looks like:
{{% notice info %}}
<i class="fas fa-bookmark"></i> Bookmark this page and the [official Commonmark reference](https://commonmark.org/help/) for easy future reference!
{{% /notice %}}
## Headings
Headings from `h1` through `h6` are constructed with a `#` for each level:
```markdown
# h1 Heading
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
```
Renders to:
<!-- markdownlint-disable MD025 -->
# h1 Heading
<!-- markdownlint-enable MD025 -->
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
HTML:
```html
<h1>h1 Heading</h1>
<h2>h2 Heading</h2>
<h3>h3 Heading</h3>
<h4>h4 Heading</h4>
<h5>h5 Heading</h5>
<h6>h6 Heading</h6>
```
## Comments
Comments should be HTML compatible
```html
<!--
This is a comment
-->
```
Comment below should **NOT** be seen:
<!--
This is a comment
-->
## Horizontal Rules
The HTML `<hr>` element is for creating a "thematic break" between paragraph-level elements. In Markdown, you can create a `<hr>` with `---` - three consecutive dashes
renders to:
---
## Paragraphs
Any text not starting with a special sign is written as normal, plain text and will be wrapped within `<p></p>` tags in the rendered HTML.
So this body copy:
```markdown
Lorem ipsum dolor sit amet, graecis denique ei vel, at duo primis mandamus. Et legere ocurreret pri, animal tacimates complectitur ad cum. Cu eum inermis inimicus efficiendi. Labore officiis his ex, soluta officiis concludaturque ei qui, vide sensibus vim ad.
```
renders to this HTML:
```html
<p>Lorem ipsum dolor sit amet, graecis denique ei vel, at duo primis mandamus. Et legere ocurreret pri, animal tacimates complectitur ad cum. Cu eum inermis inimicus efficiendi. Labore officiis his ex, soluta officiis concludaturque ei qui, vide sensibus vim ad.</p>
```
## Text Markers
### Bold
For emphasizing a snippet of text with a heavier font-weight.
The following snippet of text is **rendered as bold text**.
```markdown
**rendered as bold text**
```
renders to:
<!-- markdownlint-disable MD036 -->
**rendered as bold text**
<!-- markdownlint-enable MD036 -->
and this HTML
```html
<strong>rendered as bold text</strong>
```
### Italics
For emphasizing a snippet of text with italics.
The following snippet of text is _rendered as italicized text_.
```markdown
_rendered as italicized text_
```
renders to:
<!-- markdownlint-disable MD036 -->
_rendered as italicized text_
<!-- markdownlint-enable MD036 -->
and this HTML:
```html
<em>rendered as italicized text</em>
```
### Strikethrough
In GFM (GitHub flavored Markdown) you can do strikethroughs.
```markdown
~~Strike through this text.~~
```
Which renders to:
~~Strike through this text.~~
HTML:
```html
<del>Strike through this text.</del>
```
## Blockquotes
For quoting blocks of content from another source within your document.
Add `>` before any text you want to quote.
```markdown
> **Fusion Drive** combines a hard drive with a flash storage (solid-state drive) and presents it as a single logical volume with the space of both drives combined.
```
Renders to:
> **Fusion Drive** combines a hard drive with a flash storage (solid-state drive) and presents it as a single logical volume with the space of both drives combined.
and this HTML:
```html
<blockquote>
<p><strong>Fusion Drive</strong> combines a hard drive with a flash storage (solid-state drive) and presents it as a single logical volume with the space of both drives combined.</p>
</blockquote>
```
Blockquotes can also be nested:
```markdown
> Donec massa lacus, ultricies a ullamcorper in, fermentum sed augue. Nunc augue augue, aliquam non hendrerit ac, commodo vel nisi.
>
> > Sed adipiscing elit vitae augue consectetur a gravida nunc vehicula. Donec auctor odio non est accumsan facilisis. Aliquam id turpis in dolor tincidunt mollis ac eu diam.
>
> Mauris sit amet ligula egestas, feugiat metus tincidunt, luctus libero. Donec congue finibus tempor. Vestibulum aliquet sollicitudin erat, ut aliquet purus posuere luctus.
```
Renders to:
> Donec massa lacus, ultricies a ullamcorper in, fermentum sed augue. Nunc augue augue, aliquam non hendrerit ac, commodo vel nisi.
>
> > Sed adipiscing elit vitae augue consectetur a gravida nunc vehicula. Donec auctor odio non est accumsan facilisis. Aliquam id turpis in dolor tincidunt mollis ac eu diam.
>
> Mauris sit amet ligula egestas, feugiat metus tincidunt, luctus libero. Donec congue finibus tempor. Vestibulum aliquet sollicitudin erat, ut aliquet purus posuere luctus.
## Lists
### Unordered
A list of items in which the order of the items does not explicitly matter.
You may use any of the following symbols to denote bullets for each list item:
```markdown
* valid bullet
- valid bullet
+ valid bullet
```
For example
```markdown
+ Lorem ipsum dolor sit amet
+ Consectetur adipiscing elit
+ Integer molestie lorem at massa
+ Facilisis in pretium nisl aliquet
+ Nulla volutpat aliquam velit
- Phasellus iaculis neque
- Purus sodales ultricies
- Vestibulum laoreet porttitor sem
- Ac tristique libero volutpat at
+ Faucibus porta lacus fringilla vel
+ Aenean sit amet erat nunc
+ Eget porttitor lorem
```
Renders to:
<!-- markdownlint-disable MD004 -->
+ Lorem ipsum dolor sit amet
+ Consectetur adipiscing elit
+ Integer molestie lorem at massa
+ Facilisis in pretium nisl aliquet
+ Nulla volutpat aliquam velit
- Phasellus iaculis neque
- Purus sodales ultricies
- Vestibulum laoreet porttitor sem
- Ac tristique libero volutpat at
+ Faucibus porta lacus fringilla vel
+ Aenean sit amet erat nunc
+ Eget porttitor lorem
<!-- markdownlint-enable MD004 -->
And this HTML
```html
<ul>
<li>Lorem ipsum dolor sit amet</li>
<li>Consectetur adipiscing elit</li>
<li>Integer molestie lorem at massa</li>
<li>Facilisis in pretium nisl aliquet</li>
<li>Nulla volutpat aliquam velit
<ul>
<li>Phasellus iaculis neque</li>
<li>Purus sodales ultricies</li>
<li>Vestibulum laoreet porttitor sem</li>
<li>Ac tristique libero volutpat at</li>
</ul>
</li>
<li>Faucibus porta lacus fringilla vel</li>
<li>Aenean sit amet erat nunc</li>
<li>Eget porttitor lorem</li>
</ul>
```
### Ordered
A list of items in which the order of items does explicitly matter.
```markdown
1. Lorem ipsum dolor sit amet
4. Consectetur adipiscing elit
2. Integer molestie lorem at massa
8. Facilisis in pretium nisl aliquet
4. Nulla volutpat aliquam velit
99. Faucibus porta lacus fringilla vel
21. Aenean sit amet erat nunc
6. Eget porttitor lorem
```
Renders to:
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
4. Facilisis in pretium nisl aliquet
5. Nulla volutpat aliquam velit
6. Faucibus porta lacus fringilla vel
7. Aenean sit amet erat nunc
8. Eget porttitor lorem
And this HTML:
```html
<ol>
<li>Lorem ipsum dolor sit amet</li>
<li>Consectetur adipiscing elit</li>
<li>Integer molestie lorem at massa</li>
<li>Facilisis in pretium nisl aliquet</li>
<li>Nulla volutpat aliquam velit</li>
<li>Faucibus porta lacus fringilla vel</li>
<li>Aenean sit amet erat nunc</li>
<li>Eget porttitor lorem</li>
</ol>
```
{{% notice tip %}}
If you just use `1.` for each number, Markdown will automatically number each item. For example:
{{% /notice %}}
```markdown
1. Lorem ipsum dolor sit amet
1. Consectetur adipiscing elit
1. Integer molestie lorem at massa
1. Facilisis in pretium nisl aliquet
1. Nulla volutpat aliquam velit
1. Faucibus porta lacus fringilla vel
1. Aenean sit amet erat nunc
1. Eget porttitor lorem
```
Renders to:
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
3. Integer molestie lorem at massa
4. Facilisis in pretium nisl aliquet
5. Nulla volutpat aliquam velit
6. Faucibus porta lacus fringilla vel
7. Aenean sit amet erat nunc
8. Eget porttitor lorem
## Code
### Inline code
Wrap inline snippets of code with `` ` ``.
```markdown
In this example, `<div></div>` should be wrapped as **code**.
```
Renders to:
In this example, `<div></div>` should be wrapped as **code**.
HTML:
```html
<p>In this example, <code>&lt;div&gt;&lt;/div&gt;</code> should be wrapped as <strong>code</strong>.</p>
```
### Indented code
Or indent several lines of code by at least two spaces, as in:
```markdown
// Some comments
line 1 of code
line 2 of code
line 3 of code
```
Renders to:
<!-- markdownlint-disable MD046 -->
// Some comments
line 1 of code
line 2 of code
line 3 of code
<!-- markdownlint-enable MD046 -->
HTML:
```html
<pre>
<code>
// Some comments
line 1 of code
line 2 of code
line 3 of code
</code>
</pre>
```
### Block code "fences"
Use "fences" ```` ``` ```` to block in multiple lines of code.
````plaintext
```
Sample text here...
```
````
HTML:
```html
<pre>
<code>Sample text here...</code>
</pre>
```
### Syntax highlighting
GFM, or "GitHub Flavored Markdown" also supports syntax highlighting. To activate it, usually you simply add the file extension of the language you want to use directly after the first code "fence", ` ```js `, and syntax highlighting will automatically be applied in the rendered HTML.
See [Code Highlighting]({{% relref "syntaxhighlight" %}}) for additional documentation.
For example, to apply syntax highlighting to JavaScript code:
````plaintext
```js
grunt.initConfig({
assemble: {
options: {
assets: 'docs/assets',
data: 'src/data/*.{json,yml}',
helpers: 'src/custom-helpers.js',
partials: ['src/partials/**/*.{hbs,md}']
},
pages: {
options: {
layout: 'default.hbs'
},
files: {
'./': ['src/templates/pages/index.hbs']
}
}
}
};
```
````
Renders to:
```js
grunt.initConfig({
assemble: {
options: {
assets: 'docs/assets',
data: 'src/data/*.{json,yml}',
helpers: 'src/custom-helpers.js',
partials: ['src/partials/**/*.{hbs,md}']
},
pages: {
options: {
layout: 'default.hbs'
},
files: {
'./': ['src/templates/pages/index.hbs']
}
}
}
};
```
## Tables
Tables are created by adding pipes as dividers between each cell, and by adding a line of dashes (also separated by bars) beneath the header. Note that the pipes do not need to be vertically aligned.
```markdown
| Option | Description |
| ------ | ----------- |
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
```
Renders to:
| Option | Description |
| ------ | ----------- |
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
And this HTML:
```html
<table>
<tr>
<th>Option</th>
<th>Description</th>
</tr>
<tr>
<td>data</td>
<td>path to data files to supply the data that will be passed into templates.</td>
</tr>
<tr>
<td>engine</td>
<td>engine to be used for processing templates. Handlebars is the default.</td>
</tr>
<tr>
<td>ext</td>
<td>extension to be used for dest files.</td>
</tr>
</table>
```
### Right aligned text
Adding a colon on the right side of the dashes below any heading will right align text for that column.
```markdown
| Option | Description |
| ------:| -----------:|
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
```
| Option | Description |
| ------:| -----------:|
| data | path to data files to supply the data that will be passed into templates. |
| engine | engine to be used for processing templates. Handlebars is the default. |
| ext | extension to be used for dest files. |
### Two tables adjacent
| Option | Description |
| ------ | ----------- |
| ext | extension to be used for dest files. |
| Option | Description |
| ------ | ----------- |
| ext | extension to be used for dest files. |
## Links
### Basic link
```markdown
[Assemble](http://assemble.io)
```
Renders to (hover over the link, there is no tooltip):
[Assemble](http://assemble.io)
HTML:
```html
<a href="http://assemble.io">Assemble</a>
```
### Add a tooltip
```markdown
[Upstage](https://github.com/upstage/ "Visit Upstage!")
```
Renders to (hover over the link, there should be a tooltip):
[Upstage](https://github.com/upstage/ "Visit Upstage!")
HTML:
```html
<a href="https://github.com/upstage/" title="Visit Upstage!">Upstage</a>
```
### Named Anchors
Named anchors enable you to jump to the specified anchor point on the same page. For example, each of these chapters:
```markdown
# Table of Contents
* [Chapter 1](#chapter-1)
* [Chapter 2](#chapter-2)
* [Chapter 3](#chapter-3)
```
will jump to these sections:
```markdown
## Chapter 1 <a id="chapter-1"></a>
Content for chapter one.
## Chapter 2 <a id="chapter-2"></a>
Content for chapter one.
## Chapter 3 <a id="chapter-3"></a>
Content for chapter one.
```
**NOTE** that specific placement of the anchor tag seems to be arbitrary. They are placed inline here since it seems to be unobtrusive, and it works.
## Images {#images}
Images have a similar syntax to links but include a preceding exclamation point.
```markdown
![Minion](https://octodex.github.com/images/minion.png)
```
![Minion](https://octodex.github.com/images/minion.png)
or
```markdown
![Alt text](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
```
![Alt text](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")
Like links, Images also have a footnote style syntax
### Alternative usage : note images
```markdown
![Alt text][id]
```
![Alt text][id]
With a reference later in the document defining the URL location:
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
### Further image formatting
The Hugo Markdown parser supports additional non-standard functionality.
#### Resizing image
Add HTTP parameters `width` and/or `height` to the link image to resize the image. Values are CSS values (default is `auto`).
```markdown
![Minion](https://octodex.github.com/images/minion.png?width=20pc)
```
![Minion](https://octodex.github.com/images/minion.png?width=20pc)
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.png?width=20pc)
```markdown
![Minion](https://octodex.github.com/images/minion.png?height=50px)
```
![Minion](https://octodex.github.com/images/minion.png?height=50px)
```markdown
![Minion](https://octodex.github.com/images/minion.png?height=50px&width=300px)
```
![Minion](https://octodex.github.com/images/minion.png?height=50px&width=300px)
#### Add CSS classes
Add a HTTP `classes` parameter to the link image to add CSS classes. `shadow`and `border` are available but you could define other ones.
```markdown
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?classes=shadow)
```
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?width=40pc&classes=shadow)
```markdown
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?classes=border)
```
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?width=40pc&classes=border)
```markdown
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?classes=border,shadow)
```
![stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg?width=40pc&classes=border,shadow)
#### Lightbox
Add a HTTP `featherlight` parameter to the link image to disable lightbox. By default lightbox is enabled using the featherlight.js plugin. You can disable this by defining `featherlight` to `false`.
```markdown
![Minion](https://octodex.github.com/images/minion.png?featherlight=false)
```
![Minion](https://octodex.github.com/images/minion.png?featherlight=false)

View File

@ -0,0 +1,5 @@
+++
title = "Marrrkdown rules"
weight = 15
+++
{{< piratify >}}

View File

@ -0,0 +1,132 @@
+++
title = "Menu extra shortcuts"
weight = 25
+++
You can define additional menu entries or shortcuts in the navigation menu without any link to content.
## Basic configuration
Edit the website configuration `config.toml` and add a `[[menu.shortcuts]]` entry for each link your want to add.
Example from the current website:
````toml
[[menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[menu.shortcuts]]
name = "<i class='fas fa-fw fa-camera'></i> Showcases"
url = "more/showcase/"
weight = 11
[[menu.shortcuts]]
name = "<i class='fas fa-fw fa-bookmark'></i> Hugo Documentation"
identifier = "hugodoc"
url = "https://gohugo.io/"
weight = 20
[[menu.shortcuts]]
name = "<i class='fas fa-fw fa-bullhorn'></i> Credits"
url = "more/credits/"
weight = 30
[[menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Tags"
url = "tags/"
weight = 40
````
By default, shortcuts are preceded by a title. This title can be disabled by setting `disableShortcutsTitle=true`.
However, if you want to keep the title but change its value, it can be overriden by changing your local i18n translation string configuration.
For example, in your local `i18n/en.toml` file, add the following content
````toml
[Shortcuts-Title]
other = "<Your value>"
````
Read more about [hugo menu](https://gohugo.io/extras/menus/) and [hugo i18n translation strings](https://gohugo.io/content-management/multilingual/#translation-of-strings)
## Configuration for Multilingual mode {#i18n}
When using a multilingual website, you can set different menus for each language. In the `config.toml` file, prefix your menu configuration by `Languages.<language-id>`.
Example from the current website:
````toml
[Languages]
[Languages.en]
title = "Hugo Relearn Theme"
weight = 1
languageName = "English"
landingPageURL = "/"
landingPageName = "<i class='fas fa-home'></i> Home"
[[Languages.en.menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-camera'></i> Showcases"
url = "more/showcase/"
weight = 11
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bookmark'></i> Hugo Documentation"
identifier = "hugodoc"
url = "https://gohugo.io/"
weight = 20
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bullhorn'></i> Credits"
url = "more/credits/"
weight = 30
[[Languages.en.menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Tags"
url = "tags/"
weight = 40
[Languages.pir]
title = "Cap'n Hugo Relearrrn Theme"
weight = 1
languageName = "Arrr! Pirrrates"
landingPageURL = "/pir/"
landingPageName = "<i class='fas fa-home'></i> Arrr! Home"
[[Languages.pir.menu.shortcuts]]
name = "<i class='fab fa-fw fa-github'></i> GitHub repo"
identifier = "ds"
url = "https://github.com/McShelby/hugo-theme-relearn"
weight = 10
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-camera'></i> Showcases"
url = "more/showcase/"
weight = 11
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bookmark'></i> Cap'n Hugo Documentat'n"
identifier = "hugodoc"
url = "https://gohugo.io/"
weight = 20
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-bullhorn'></i> Crrredits"
url = "more/credits/"
weight = 30
[[Languages.pir.menu.shortcuts]]
name = "<i class='fas fa-fw fa-tags'></i> Arrr! Tags"
url = "tags/"
weight = 40
````
Read more about [hugo menu](https://gohugo.io/extras/menus/) and [hugo multilingual menus](https://gohugo.io/content-management/multilingual/#menus)

View File

@ -0,0 +1,5 @@
+++
title = "Menu extrrra shorrrtcuts"
weight = 25
+++
{{< piratify >}}

View File

@ -0,0 +1,191 @@
+++
title = "Pages organization"
weight = 5
+++
In **Hugo**, pages are the core of your site. Once it is configured, pages are definitely the added value to your documentation site.
## Folders
Organize your site like [any other Hugo project](https://gohugo.io/content/organization/). Typically, you will have a *content* folder with all your pages.
````plaintext
content
├── level-one
│ ├── level-two
│ │ ├── level-three
│ │ │ ├── level-four
│ │ │ │ ├── _index.md <-- /level-one/level-two/level-three/level-four
│ │ │ │ ├── page-4-a.md <-- /level-one/level-two/level-three/level-four/page-4-a
│ │ │ │ ├── page-4-b.md <-- /level-one/level-two/level-three/level-four/page-4-b
│ │ │ │ └── page-4-c.md <-- /level-one/level-two/level-three/level-four/page-4-c
│ │ │ ├── _index.md <-- /level-one/level-two/level-three
│ │ │ ├── page-3-a.md <-- /level-one/level-two/level-three/page-3-a
│ │ │ ├── page-3-b.md <-- /level-one/level-two/level-three/page-3-b
│ │ │ └── page-3-c.md <-- /level-one/level-two/level-three/page-3-c
│ │ ├── _index.md <-- /level-one/level-two
│ │ ├── page-2-a.md <-- /level-one/level-two/page-2-a
│ │ ├── page-2-b.md <-- /level-one/level-two/page-2-b
│ │ └── page-2-c.md <-- /level-one/level-two/page-2-c
│ ├── _index.md <-- /level-one
│ ├── page-1-a.md <-- /level-one/page-1-a
│ ├── page-1-b.md <-- /level-one/page-1-b
│ └── page-1-c.md <-- /level-one/page-1-c
├── _index.md <-- /
└── page-top.md <-- /page-top
````
{{% notice note %}}
`_index.md` is required in each folder, its your “folder home page”
{{% /notice %}}
## Types
The Relearn theme defines two types of pages. *Default* and *Chapter*. Both can be used at any level of the documentation, the only difference being layout display.
### Chapter {#chapter-style}
A **Chapter** displays a page meant to be used as introduction for a set of child pages. Commonly, it contains a simple title and a catch line to define content that can be found under it.
You can define any HTML as prefix for the menu. In the example below, it's just a number but that could be an [icon](https://fortawesome.github.io/Font-Awesome/).
![Chapter page](images/pages-chapter.png?classes=shadow&width=60pc)
```markdown
+++
chapter = true
pre = "<b>1. </b>"
title = "Basics"
weight = 5
+++
### Chapter 1
# Basics
Discover what this Hugo theme is all about and the core-concepts behind it.
```
To tell the Relearn theme to consider a page as a chapter, set `chapter=true` in the Front Matter of the page.
### Default
A **Default** page is any other content page.
![Default page](images/pages-default.png?classes=shadow&width=60pc)
```toml
+++
title = "Installation"
weight = 15
+++
```
The following steps are here to help you initialize your new website. If you don't know Hugo at all, we strongly suggest you to train by following this [great documentation for beginners](https://gohugo.io/overview/quickstart/).
## Create your project
Hugo provides a `new` command to create a new website.
```shell
hugo new site <new_project>
```
The Relearn theme provides [archetypes]({{%relref "cont/archetypes" %}}) to help you create this kind of pages.
## Front Matter configuration
Each Hugo page has to define a [Front Matter](https://gohugo.io/content/front-matter/) in *toml*, *yaml* or *json*. This site will use *toml* in all cases.
The Relearn theme uses the following parameters on top of Hugo ones :
```toml
+++
# Table of contents (toc) is enabled by default. Set this parameter to true to disable it.
# Note: Toc is always disabled for chapter pages
disableToc = false
# If set, this will be used for the page's menu entry (instead of the `title` attribute)
menuTitle = ""
# If set, this will explicitly override common rules for the expand state of a page's menu entry
alwaysopen = true
# If set, this will explicitly override common rules for the sorting order of a page's submenu entries
ordersectionsby = "title"
# The title of the page in menu will be prefixed by this HTML content
pre = ""
# The title of the page in menu will be postfixed by this HTML content
post = ""
# Set the page as a chapter, changing the way it's displayed
chapter = false
# Hide a menu entry by setting this to true
hidden = false
# Display name of this page modifier. If set, it will be displayed in the footer.
LastModifierDisplayName = ""
# Email of this page modifier. If set with LastModifierDisplayName, it will be displayed in the footer
LastModifierEmail = ""
+++
```
### Add icon to a menu entry
In the page frontmatter, add a `pre` param to insert any HTML code before the menu label. The example below uses the GitHub icon.
```toml
+++
title = "GitHub repo"
pre = "<i class='fab fa-github'></i> "
+++
```
![Title with icon](images/frontmatter-icon.png?classes=shadow&width=300px)
### Ordering sibling menu/page entries
Hugo provides a [flexible way](https://gohugo.io/content/ordering/) to handle order for your pages.
The simplest way is to set `weight` parameter to a number.
```toml
+++
title = "My page"
weight = 5
+++
```
### Using a custom title for menu entries
By default, the Relearn theme will use a page's `title` attribute for the menu item (or `linkTitle` if defined).
But a page's title has to be descriptive on its own while the menu is a hierarchy.
We've added the `menuTitle` parameter for that purpose:
For example (for a page named `content/install/linux.md`):
```toml
+++
title = "Install on Linux"
menuTitle = "Linux"
+++
```
### Override expand state rules for menu entries
You can change how the theme expands menu entries on the side of the content with the `alwaysopen` setting on a per page basis. If `alwaysopen=false` for any given entry, its children will not be shown in the menu as long as it is not necessary for the sake of navigation.
The theme generates the menu based on the following rules:
- all parent entries of the active page including their siblings are shown regardless of any settings
- immediate children entries of the active page are shown regardless of any settings
- if not overridden, all other first level entries behave like they would have been given `alwaysopen=false`
- if not overridden, all other entries of levels besides the first behave like they would have been given `alwaysopen=true`
- all visible entries show their immediate children entries if `alwaysopen=true`; this proceeds recursivley
- all remaining entries are not shown
You can see this feature in action on the example page for [children shortcode]({{< relref "shortcodes/children" >}}) and its children pages.
## Your Page
To configure your page, you basically have three choices:
1. Create an `_index.md` document in `content` folder and fill the file with *Markdown content*
2. Create an `index.html` file in the `static` folder and fill the file with *HTML content*
3. Configure your server to automatically redirect home page to one your documentation page

View File

@ -0,0 +1,5 @@
+++
title = "Planks orrrganizat'n"
weight = 5
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

View File

@ -0,0 +1,66 @@
+++
title = "Code highlighting"
weight = 16
+++
The Relearn theme uses [Hugo's built-in syntax highlighting](https://gohugo.io/content-management/syntax-highlighting/) for code.
## Markdown syntax
Wrap the code block with three backticks and the name of the language. Highlight will try to auto detect the language if one is not provided.
<!-- markdownlint-disable MD046 -->
````plaintext
```json
[
{
"title": "apples",
"count": [12000, 20000],
"description": {"text": "...", "sensitive": false}
},
{
"title": "oranges",
"count": [17500, null],
"description": {"text": "...", "sensitive": false}
}
]
```
````
<!-- markdownlint-disable MD046 -->
Renders to:
```json
[
{
"title": "apples",
"count": [12000, 20000],
"description": {"text": "...", "sensitive": false}
},
{
"title": "oranges",
"count": [17500, null],
"description": {"text": "...", "sensitive": false}
}
]
```
## Supported languages
Hugo comes with a [remarkable list](https://gohugo.io/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages) of supported languages.
## Recommended configuration
You can choose a color theme from the [list of supported themes](https://xyproto.github.io/splash/docs/all.html) and add it in your `config.toml`
````toml
[markup]
[markup.highlight]
# if set to `guessSyntax = true`, there will be no unstyled code even if no language
# was given BUT mermaid code fences will not work anymore! So this is a mandatory
# setting for your site
guessSyntax = false
# choose a color theme or create your own
style = "base16-snazzy"
````

View File

@ -0,0 +1,5 @@
+++
title = "Code highlight'n"
weight = 16
+++
{{< piratify >}}

View File

@ -0,0 +1,36 @@
+++
tags = ["documentation", "tutorial"]
title = "Tags"
weight = 40
+++
The Relearn theme supports one default taxonomy of Hugo: the *tag* feature.
## Configuration
Just add tags to any page:
```toml
+++
tags = ["tutorial", "theme"]
title = "Theme tutorial"
weight = 15
+++
```
## Behavior
The tags are displayed at the top of the page, in their insertion order.
Each tag is a link to a *Taxonomy* page displaying all the articles with the given tag.
## List all the tags
In the `config.toml` file you can add a shortcut to display all the tags
```toml
[[menu.shortcuts]]
name = "<i class='fas fa-tags'></i> Tags"
url = "/tags"
weight = 30
```

View File

@ -0,0 +1,6 @@
+++
tags = ["documentat'n", "tutorrrial"]
title = "Tags"
weight = 40
+++
{{< piratify >}}

View File

@ -0,0 +1,9 @@
+++
title = "More"
[_build]
render = "never"
list = "never"
publishResources = false
+++
{{%children containerstyle="div" style="h2" description="true" %}}

View File

@ -0,0 +1,8 @@
+++
title = "Morrre"
[_build]
render = "never"
list = "never"
publishResources = false
+++
{{< piratify >}}

View File

@ -0,0 +1,31 @@
+++
disableToc = true
title = "Credits"
+++
## Contributors
Special thanks to [everyone who has contributed](https://github.com/McShelby/hugo-theme-relearn/graphs/contributors) to this project.
Many thanks to [Mathieu Cornic](https://github.com/matcornic) for his work on porting the [Learn theme](https://github.com/matcornic/hugo-theme-learn) to Hugo.
Many thanks to [Andy Miller](https://github.com/rhukster) for initially creating the [Learn theme](https://github.com/getgrav/grav-theme-learn2) for Grav.
## Packages and libraries
* [autoComplete](https://github.com/Pixabay/JavaScript-autoComplete) - A lightweight and powerful vanilla JavaScript completion suggester
* [clipboard.js](https://clipboardjs.com) - A modern approach to copy text to clipboard
* [Featherlight](https://noelboss.github.io/featherlight) - A lightweight jQuery lightbox plugin
* [Font Awesome](https://fontawesome.com) - The internet's icon library and toolkit
* [jQuery](https://jquery.com) - The "Write less, do more" JavaScript library
* [jquery-svg-zoom-pan](https://github.com/DanielHoffmann/jquery-svg-pan-zoom) - A jQuery plugin to enable pan and zoom in SVG images
* [Lunr](https://lunrjs.com) - Enables a great search experience without the need for external, server-side, search services
* [Mermaid](https://mermaid-js.github.io/mermaid) - Generation of diagram and flowchart from text in a similar manner as markdown
* [Perfect Scrollbar](https://perfectscrollbar.com) - A minimalistic but perfect custom scrollbar plugin
* [RapiDoc](https://mrin9.github.io/RapiDoc) - Create beautiful, customizable, interactive API documentation from OpenAPI Specifications
## Tooling
* [GitHub](https://github.com) - Continuous deployement, testing and hosting of this project's sources and its documentation
* [gren](https://github.com/github-tools/github-release-notes) - A releasenotes generator for GitHub
* [Hugo](https://gohugo.io/) - The static site generator of your choice

View File

@ -0,0 +1,5 @@
+++
disableToc = true
title = "Crrredits"
+++
{{< piratify >}}

View File

@ -0,0 +1,15 @@
+++
title = "Showcase"
+++
## [GoboLinux Wiki](https://wiki.gobolinux.org/) by NEONsys.org
![GoboLinux image](images/gobolinux.png?width=60pc&classes=shadow)
## [BITS](https://bits-training.de/training/) by Dr. Lutz Gollan
![BITS image](images/bits-train.png?width=60pc&classes=shadow)
## [Pamasol Electrics](https://pamasol.github.io/de/) by Pamasol Swiss Aerosol Solutions
![Pamasol Electrics](images/pamasol-electrics-portal.png?width=60pc&classes=shadow)

View File

@ -0,0 +1,4 @@
+++
title = "Showcase"
+++
{{< piratify >}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View File

@ -0,0 +1,13 @@
You can add standard markdown syntax:
- multiple paragraphs
- bullet point lists
- _emphasized_, **bold** and even **_bold emphasized_** text
- [links](https://example.com)
- etc.
```plaintext
...and even source code
```
> the possiblities are endless (almost - including other shortcodes may or may not work) (almost - including other shortcodes may or may not work)

Some files were not shown because too many files have changed in this diff Show More