Compare commits
2 commits
7756515f96
...
c85a9fa00b
Author | SHA1 | Date | |
---|---|---|---|
c85a9fa00b | |||
f4c1d12c59 |
7 changed files with 441 additions and 494 deletions
2
config
2
config
|
@ -1,6 +1,6 @@
|
||||||
# vim:ft=sh:
|
# vim:ft=sh:
|
||||||
ngx_addon_name=ngx_http_awesomeindex_module
|
ngx_addon_name=ngx_http_awesomeindex_module
|
||||||
ngx_module_libs="-lmarkdown"
|
ngx_module_libs="-lmd4c-html"
|
||||||
|
|
||||||
if [ "$ngx_module_link" = DYNAMIC ] ; then
|
if [ "$ngx_module_link" = DYNAMIC ] ; then
|
||||||
ngx_module_type=HTTP
|
ngx_module_type=HTTP
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
#include <ngx_core.h>
|
#include <ngx_core.h>
|
||||||
#include <ngx_http.h>
|
#include <ngx_http.h>
|
||||||
#include <ngx_log.h>
|
#include <ngx_log.h>
|
||||||
|
#include "ngx_buf.h"
|
||||||
#include "ngx_string.h"
|
#include "ngx_string.h"
|
||||||
|
|
||||||
#include <mkdio.h>
|
#include "md4c-html.h"
|
||||||
|
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
#if defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
|
@ -328,7 +328,85 @@ ngx_awesomeindex_conf_set_headerfooter(ngx_conf_t *cf, ngx_command_t *cmd, void
|
||||||
#define ngx_has_flag(_where, _what) \
|
#define ngx_has_flag(_where, _what) \
|
||||||
(((_where) & (_what)) == (_what))
|
(((_where) & (_what)) == (_what))
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
*** Simple grow-able buffer ***
|
||||||
|
*********************************/
|
||||||
|
|
||||||
|
/* We render to a memory buffer instead of directly outputting the rendered
|
||||||
|
* documents, as this allows using this utility for evaluating performance
|
||||||
|
* of MD4C (--stat option). This allows us to measure just time of the parser,
|
||||||
|
* without the I/O.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct membuffer {
|
||||||
|
char* data;
|
||||||
|
size_t asize;
|
||||||
|
size_t size;
|
||||||
|
u_char fail;
|
||||||
|
};
|
||||||
|
|
||||||
|
static u_char
|
||||||
|
membuf_init(struct membuffer* buf, MD_SIZE new_asize)
|
||||||
|
{
|
||||||
|
buf->size = 0;
|
||||||
|
buf->asize = new_asize;
|
||||||
|
buf->data = malloc(buf->asize);
|
||||||
|
if(buf->data == NULL) {
|
||||||
|
buf->fail = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
buf->fail = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
membuf_free(struct membuffer* buf)
|
||||||
|
{
|
||||||
|
if(buf && buf->data) free(buf->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
membuf_grow(struct membuffer* buf, size_t new_asize)
|
||||||
|
{
|
||||||
|
buf->data = realloc(buf->data, new_asize);
|
||||||
|
if(buf->data == NULL) {
|
||||||
|
buf->fail = 1;
|
||||||
|
}
|
||||||
|
buf->asize = new_asize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
membuf_append(struct membuffer* buf, const char* data, MD_SIZE size)
|
||||||
|
{
|
||||||
|
if(buf->asize < buf->size + size)
|
||||||
|
membuf_grow(buf, buf->size + buf->size / 2 + size);
|
||||||
|
memcpy(buf->data + buf->size, data, size);
|
||||||
|
buf->size += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_md_output(const MD_CHAR* text, MD_SIZE size, void* userdata)
|
||||||
|
{
|
||||||
|
struct membuffer *buf = (struct membuffer*) userdata;
|
||||||
|
if (!buf->fail) membuf_append(buf, text, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ngx_awesomeindex_read_file(ngx_http_request_t *r, u_char* filename, size_t file_len, u_char* dest)
|
||||||
|
{
|
||||||
|
ngx_file_t file;
|
||||||
|
ngx_memzero(&file, sizeof(ngx_file_t));
|
||||||
|
file.fd = ngx_open_file(filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
|
||||||
|
if (file.fd == NGX_INVALID_FILE) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
||||||
|
"cannot open readme file \"%V\"", filename);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
file.log = r->connection->log;
|
||||||
|
|
||||||
|
ssize_t n = ngx_read_file(&file, dest, file_len, 0);
|
||||||
|
ngx_close_file(file.fd);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -559,11 +637,21 @@ static const ngx_str_t img_icon_pre =
|
||||||
ngx_string("<img src=\"");
|
ngx_string("<img src=\"");
|
||||||
static const ngx_str_t img_icon_post =
|
static const ngx_str_t img_icon_post =
|
||||||
ngx_string("\" alt=\"\" height=\"32\" width=\"32\">");
|
ngx_string("\" alt=\"\" height=\"32\" width=\"32\">");
|
||||||
static const ngx_str_t footer_pre =
|
static const ngx_str_t footer_md_pre =
|
||||||
ngx_string("<footer class=\"markup\">");
|
ngx_string("<footer class=\"markup\">");
|
||||||
|
static const ngx_str_t codeblock_pre =
|
||||||
|
ngx_string("<pre>");
|
||||||
|
static const ngx_str_t codeblock_post =
|
||||||
|
ngx_string("</pre>");
|
||||||
|
static const ngx_str_t footer_pre =
|
||||||
|
ngx_string("<footer>");
|
||||||
static const ngx_str_t footer_post =
|
static const ngx_str_t footer_post =
|
||||||
ngx_string("</footer>");
|
ngx_string("</footer>");
|
||||||
|
|
||||||
|
#define README_TXT 0
|
||||||
|
#define README_HTML 1
|
||||||
|
#define README_MD 2
|
||||||
|
|
||||||
|
|
||||||
#ifdef NGX_ESCAPE_URI_COMPONENT
|
#ifdef NGX_ESCAPE_URI_COMPONENT
|
||||||
static inline uintptr_t
|
static inline uintptr_t
|
||||||
|
@ -740,7 +828,7 @@ make_content_buf(
|
||||||
ngx_dir_t dir;
|
ngx_dir_t dir;
|
||||||
ngx_buf_t *b;
|
ngx_buf_t *b;
|
||||||
u_char *readme_path = NULL;
|
u_char *readme_path = NULL;
|
||||||
u_char readme_md = 0;
|
u_char readme_type = README_TXT;
|
||||||
off_t readme_file_len = 0;
|
off_t readme_file_len = 0;
|
||||||
|
|
||||||
static const char *sizes[] = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" };
|
static const char *sizes[] = { "EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B" };
|
||||||
|
@ -925,7 +1013,11 @@ make_content_buf(
|
||||||
ngx_cpystrn(readme_path, filename, allocated);
|
ngx_cpystrn(readme_path, filename, allocated);
|
||||||
|
|
||||||
readme_file_len = entry->size;
|
readme_file_len = entry->size;
|
||||||
readme_md = entry->name.len > 6 && ngx_strncasecmp(entry->name.data + 6, (u_char*) ".md", 3) == 0;
|
readme_type = README_TXT;
|
||||||
|
if (entry->name.len > 6) {
|
||||||
|
if (ngx_strncasecmp(entry->name.data + 6, (u_char*) ".md", 3) == 0) readme_type = README_MD;
|
||||||
|
else if (ngx_strncasecmp(entry->name.data + 6, (u_char*) ".html", 3) == 0) readme_type = README_HTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +1033,7 @@ make_content_buf(
|
||||||
|
|
||||||
if (readme_path) {
|
if (readme_path) {
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"HTTP awesomeindex README: %s, MD%d, len: %d", readme_path, readme_md, readme_file_len);
|
"http awesomeindex README: %s, type: %d, len: %d", readme_path, readme_type, readme_file_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1019,21 +1111,47 @@ make_content_buf(
|
||||||
if (entry[i].link) len += ngx_sizeof_ssz("-shortcut");
|
if (entry[i].link) len += ngx_sizeof_ssz("-shortcut");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *readme_md_content;
|
struct membuffer readme_md_content = {0};
|
||||||
if (readme_file_len) {
|
if (readme_file_len) {
|
||||||
if (readme_md) {
|
if (readme_type == README_MD) {
|
||||||
FILE *md_file = fopen((char *)readme_path, "r");
|
ngx_buf_t *buf_in = ngx_create_temp_buf(r->pool, readme_file_len);
|
||||||
MMIOT *mkd = mkd_in(md_file, MKD_FLAGS);
|
ssize_t rbts = ngx_awesomeindex_read_file(r, readme_path, readme_file_len, buf_in->last);
|
||||||
mkd_compile(mkd, MKD_FLAGS);
|
|
||||||
readme_file_len = mkd_document(mkd, &readme_md_content);
|
if (rbts != NGX_ERROR) {
|
||||||
fclose(md_file);
|
buf_in->last += rbts;
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "converted %s, len=%d", readme_path, readme_file_len);
|
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, ngx_errno, "http awesomeindex: read %d bytes from %s", rbts, readme_path);
|
||||||
|
|
||||||
|
// Allocating buffer for parsing readme
|
||||||
|
if (!membuf_init(&readme_md_content, readme_file_len + readme_file_len/5)) {
|
||||||
|
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, ngx_errno, "MEMBUF INITTED");
|
||||||
|
int ret = md_html((MD_CHAR*) buf_in->start, readme_file_len, process_md_output,
|
||||||
|
&readme_md_content, MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_TABLES, 0);
|
||||||
|
if (ret) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "error parsing markdown %s", readme_path);
|
||||||
|
} else if (readme_md_content.fail) {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "could not allocate memory for parsing readme");
|
||||||
|
} else {
|
||||||
|
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "parsed markdown len=%d", readme_md_content.size);
|
||||||
|
len += footer_md_pre.len + readme_md_content.size + footer_post.len;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "could not allocate memory for parsing readme");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
readme_md_content.fail = 1;
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "cannot read file \"%V\"", readme_path);
|
||||||
|
}
|
||||||
|
} else if (readme_type == README_TXT) {
|
||||||
|
len += footer_pre.len + codeblock_pre.len + readme_file_len + codeblock_post.len + footer_post.len;
|
||||||
|
} else {
|
||||||
len += footer_pre.len + readme_file_len + footer_post.len;
|
len += footer_pre.len + readme_file_len + footer_post.len;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((b = ngx_create_temp_buf(r->pool, len)) == NULL)
|
if ((b = ngx_create_temp_buf(r->pool, len)) == NULL) {
|
||||||
|
membuf_free(&readme_md_content);
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the sorting criteria. URL arguments look like:
|
* Determine the sorting criteria. URL arguments look like:
|
||||||
|
@ -1299,41 +1417,27 @@ make_content_buf(
|
||||||
|
|
||||||
// Readme file
|
// Readme file
|
||||||
if (readme_file_len) {
|
if (readme_file_len) {
|
||||||
b->last = ngx_cpymem_str(b->last, footer_pre);
|
if (readme_type == README_MD) {
|
||||||
|
if (!readme_md_content.fail) {
|
||||||
if (readme_md) {
|
b->last = ngx_cpymem_str(b->last, footer_md_pre);
|
||||||
b->last = ngx_cpymem(b->last, readme_md_content, readme_file_len);
|
b->last = ngx_cpymem(b->last, readme_md_content.data, readme_md_content.size);
|
||||||
} else {
|
|
||||||
ngx_file_t file;
|
|
||||||
ngx_memzero(&file, sizeof(ngx_file_t));
|
|
||||||
file.fd = ngx_open_file(readme_path, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
|
|
||||||
if (file.fd == NGX_INVALID_FILE) {
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
|
||||||
"cannot open readme file \"%V\"", readme_path);
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
file.log = r->connection->log;
|
|
||||||
ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "opened file %d", file);
|
|
||||||
|
|
||||||
ssize_t n = readme_file_len;
|
|
||||||
while (n > 0) {
|
|
||||||
ssize_t rbts = ngx_read_file(&file,
|
|
||||||
b->last + file.offset,
|
|
||||||
n,
|
|
||||||
file.offset);
|
|
||||||
if (rbts == NGX_ERROR) {
|
|
||||||
ngx_close_file(file.fd);
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
|
||||||
"cannot read readme file \"%V\"", readme_path);
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
b->last += rbts;
|
|
||||||
n -= rbts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b->last = ngx_cpymem_str(b->last, footer_post);
|
b->last = ngx_cpymem_str(b->last, footer_post);
|
||||||
}
|
}
|
||||||
|
membuf_free(&readme_md_content);
|
||||||
|
} else {
|
||||||
|
b->last = ngx_cpymem_str(b->last, footer_pre);
|
||||||
|
if (readme_type == README_TXT) b->last = ngx_cpymem_str(b->last, codeblock_pre);
|
||||||
|
|
||||||
|
ssize_t rbts = ngx_awesomeindex_read_file(r, readme_path, readme_file_len, b->last);
|
||||||
|
if (rbts != NGX_ERROR) b->last += rbts;
|
||||||
|
else {
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, "cannot read file \"%V\"", readme_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readme_type == README_TXT) b->last = ngx_cpymem_str(b->last, codeblock_post);
|
||||||
|
b->last = ngx_cpymem_str(b->last, footer_post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*pb = b;
|
*pb = b;
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
|
17
t/README.md
17
t/README.md
|
@ -1,22 +1,5 @@
|
||||||
# Markdown: Syntax
|
# Markdown: Syntax
|
||||||
|
|
||||||
* [Overview](#Overview)
|
|
||||||
* [Philosophy](#Philosophy)
|
|
||||||
* [Block Elements](#Block-Elements)
|
|
||||||
* [Paragraphs and Line Breaks](#Paragraphs-and-Line-Breaks)
|
|
||||||
* [Headers](#Headers)
|
|
||||||
* [Blockquotes](#Blockquotes)
|
|
||||||
* [Lists](#Lists)
|
|
||||||
* [Code Blocks](#Code-Blocks)
|
|
||||||
* [Horizontal Rules](#Horizontal-Rules)
|
|
||||||
* [Span Elements](#Span-Elements)
|
|
||||||
* [Links](#Links)
|
|
||||||
* [Emphasis](#Emphasis)
|
|
||||||
* [Code](#Code)
|
|
||||||
* [Table](#Table)
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
### Philosophy
|
### Philosophy
|
||||||
|
|
7
t/child-directory/README.txt
Normal file
7
t/child-directory/README.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Folder with several child directories
|
||||||
|
|
||||||
|
├── c2
|
||||||
|
│ └── c3
|
||||||
|
│ └── empty-file.txt
|
||||||
|
├── empty-file.txt
|
||||||
|
└── README.txt
|
3
t/show_dotfiles/README.html
Normal file
3
t/show_dotfiles/README.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<h1>Hello World</h1>
|
||||||
|
|
||||||
|
Hello World, this is me ;-)
|
|
@ -128,11 +128,11 @@ static const u_char t01_head1[] = ""
|
||||||
"}"
|
"}"
|
||||||
"footer {"
|
"footer {"
|
||||||
" padding: 40px 20px;"
|
" padding: 40px 20px;"
|
||||||
|
" font-size: 16px;"
|
||||||
"}"
|
"}"
|
||||||
".markup {"
|
".markup {"
|
||||||
" max-width: 790px;"
|
" max-width: 790px;"
|
||||||
" word-wrap: break-word;"
|
" word-wrap: break-word;"
|
||||||
" font-size: 16px;"
|
|
||||||
" overflow: hidden;"
|
" overflow: hidden;"
|
||||||
" line-height: 1.5 !important;"
|
" line-height: 1.5 !important;"
|
||||||
"}"
|
"}"
|
||||||
|
@ -385,9 +385,6 @@ static const u_char t01_head1[] = ""
|
||||||
" .meta {"
|
" .meta {"
|
||||||
" border-bottom: 1px solid #212121;"
|
" border-bottom: 1px solid #212121;"
|
||||||
" }"
|
" }"
|
||||||
" footer code, footer pre {"
|
|
||||||
" background-color: rgb(8, 36, 55);"
|
|
||||||
" }"
|
|
||||||
" }"
|
" }"
|
||||||
" </style>"
|
" </style>"
|
||||||
;
|
;
|
||||||
|
|
685
template.html
685
template.html
|
@ -127,11 +127,11 @@ main {
|
||||||
}
|
}
|
||||||
footer {
|
footer {
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.markup {
|
.markup {
|
||||||
max-width: 790px;
|
max-width: 790px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
font-size: 16px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 1.5 !important;
|
line-height: 1.5 !important;
|
||||||
}
|
}
|
||||||
|
@ -384,9 +384,6 @@ footer {
|
||||||
.meta {
|
.meta {
|
||||||
border-bottom: 1px solid #212121;
|
border-bottom: 1px solid #212121;
|
||||||
}
|
}
|
||||||
footer code, footer pre {
|
|
||||||
background-color: rgb(8, 36, 55);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<!-- var NONE -->
|
<!-- var NONE -->
|
||||||
|
@ -609,431 +606,287 @@ Index of /path/to/somewhere
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- var NONE -->
|
<!-- var NONE -->
|
||||||
<h1><a href="https://google.github.io/styleguide/">styleguide</a></h1>
|
<footer class="markup"><h1>Markdown: Syntax</h1>
|
||||||
|
<h2>Overview</h2>
|
||||||
|
<h3>Philosophy</h3>
|
||||||
<h1 id="markdown-style-guide">Markdown style guide</h1>
|
<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>
|
||||||
|
<p>Readability, however, is emphasized above all else. A Markdown-formatted
|
||||||
<p>Much of what makes Markdown great is the ability to write plain text, and get
|
document should be publishable as-is, as plain text, without looking
|
||||||
great formatted output as a result. To keep the slate clean for the next author,
|
like it's been marked up with tags or formatting instructions. While
|
||||||
your Markdown should be simple and consistent with the whole corpus wherever
|
Markdown's syntax has been influenced by several existing text-to-HTML
|
||||||
possible.</p>
|
filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>,
|
||||||
|
<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of
|
||||||
<p>We seek to balance three goals:</p>
|
inspiration for Markdown's syntax is the format of plain text email.</p>
|
||||||
|
<h2>Block Elements</h2>
|
||||||
|
<h3>Paragraphs and Line Breaks</h3>
|
||||||
|
<p>A paragraph is simply one or more consecutive lines of text, separated
|
||||||
|
by one or more blank lines. (A blank line is any line that looks like a
|
||||||
|
blank line -- a line containing nothing but spaces or tabs is considered
|
||||||
|
blank.) Normal paragraphs should not be indented with spaces or tabs.</p>
|
||||||
|
<p>The implication of the "one or more consecutive lines of text" rule is
|
||||||
|
that Markdown supports "hard-wrapped" text paragraphs. This differs
|
||||||
|
significantly from most other text-to-HTML formatters (including Movable
|
||||||
|
Type's "Convert Line Breaks" option) which translate every line break
|
||||||
|
character in a paragraph into a <code><br /></code> tag.</p>
|
||||||
|
<p>When you <em>do</em> want to insert a <code><br /></code> break tag using Markdown, you
|
||||||
|
end a line with two or more spaces, then type return.</p>
|
||||||
|
<h3>Headers</h3>
|
||||||
|
<p>Markdown supports two styles of headers, [Setext] [1] and [atx] [2].</p>
|
||||||
|
<p>Optionally, you may "close" atx-style headers. This is purely
|
||||||
|
cosmetic -- you can use this if you think it looks better. The
|
||||||
|
closing hashes don't even need to match the number of hashes
|
||||||
|
used to open the header. (The number of opening hashes
|
||||||
|
determines the header level.)</p>
|
||||||
|
<h3>Blockquotes</h3>
|
||||||
|
<p>Markdown uses email-style <code>></code> characters for blockquoting. If you're
|
||||||
|
familiar with quoting passages of text in an email message, then you
|
||||||
|
know how to create a blockquote in Markdown. It looks best if you hard
|
||||||
|
wrap the text and put a <code>></code> before every line:</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||||
|
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||||
|
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
|
||||||
|
<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||||
|
id sem consectetuer libero luctus adipiscing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Markdown allows you to be lazy and only put the <code>></code> before the first
|
||||||
|
line of a hard-wrapped paragraph:</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
|
||||||
|
consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
|
||||||
|
Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.</p>
|
||||||
|
</blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<p>Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
|
||||||
|
id sem consectetuer libero luctus adipiscing.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by
|
||||||
|
adding additional levels of <code>></code>:</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>This is the first level of quoting.</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>This is nested blockquote.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Back to the first level.</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>Blockquotes can contain other Markdown elements, including headers, lists,
|
||||||
|
and code blocks:</p>
|
||||||
|
<blockquote>
|
||||||
|
<h2>This is a header.</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li><em>Source text is readable and portable.</em></li>
|
<li>This is the first list item.</li>
|
||||||
<li><em>Markdown files are maintainable over time and across teams.</em></li>
|
<li>This is the second list item.</li>
|
||||||
<li><em>The syntax is simple and easy to remember.</em></li>
|
|
||||||
</ol>
|
</ol>
|
||||||
|
<p>Here's some example code:</p>
|
||||||
<p>Contents:</p>
|
<pre><code>return shell_exec("echo $input | $markdown_script");
|
||||||
|
</code></pre>
|
||||||
|
</blockquote>
|
||||||
|
<p>Any decent text editor should make email-style quoting easy. For
|
||||||
|
example, with BBEdit, you can make a selection and choose Increase
|
||||||
|
Quote Level from the Text menu.</p>
|
||||||
|
<h3>Lists</h3>
|
||||||
|
<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>
|
||||||
|
<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably
|
||||||
|
-- as list markers:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Red</li>
|
||||||
|
<li>Green</li>
|
||||||
|
<li>Blue</li>
|
||||||
|
</ul>
|
||||||
|
<p>is equivalent to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Red</li>
|
||||||
|
<li>Green</li>
|
||||||
|
<li>Blue</li>
|
||||||
|
</ul>
|
||||||
|
<p>and:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Red</li>
|
||||||
|
<li>Green</li>
|
||||||
|
<li>Blue</li>
|
||||||
|
</ul>
|
||||||
|
<p>Ordered lists use numbers followed by periods:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#document-layout">Document layout</a></li>
|
<li>Bird</li>
|
||||||
<li><a href="#character-line-limit">Character line limit</a></li>
|
<li>McHale</li>
|
||||||
<li><a href="#trailing-whitespace">Trailing whitespace</a></li>
|
<li>Parish</li>
|
||||||
<li><a href="#headings">Headings</a>
|
|
||||||
<ol>
|
|
||||||
<li><a href="#atx-style-headings">ATX-style headings</a></li>
|
|
||||||
<li><a href="#add-spacing-to-headings">Add spacing to headings</a></li>
|
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
<p>It's important to note that the actual numbers you use to mark the
|
||||||
<li><a href="#lists">Lists</a>
|
list have no effect on the HTML output Markdown produces. The HTML
|
||||||
|
Markdown produces from the above list is:</p>
|
||||||
|
<p>If you instead wrote the list in Markdown like this:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#use-lazy-numbering-for-long-lists">Use lazy numbering for long lists</a></li>
|
<li>Bird</li>
|
||||||
<li><a href="#nested-list-spacing">Nested list spacing</a></li>
|
<li>McHale</li>
|
||||||
|
<li>Parish</li>
|
||||||
</ol>
|
</ol>
|
||||||
</li>
|
<p>or even:</p>
|
||||||
<li><a href="#code">Code</a>
|
<ol start="3">
|
||||||
|
<li>Bird</li>
|
||||||
|
<li>McHale</li>
|
||||||
|
<li>Parish</li>
|
||||||
|
</ol>
|
||||||
|
<p>you'd get the exact same HTML output. The point is, if you want to,
|
||||||
|
you can use ordinal numbers in your ordered Markdown lists, so that
|
||||||
|
the numbers in your source match the numbers in your published HTML.
|
||||||
|
But if you want to be lazy, you don't have to.</p>
|
||||||
|
<p>To make lists look nice, you can wrap items with hanging indents:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||||
|
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
|
||||||
|
viverra nec, fringilla in, laoreet vitae, risus.</li>
|
||||||
|
<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
|
||||||
|
Suspendisse id sem consectetuer libero luctus adipiscing.</li>
|
||||||
|
</ul>
|
||||||
|
<p>But if you want to be lazy, you don't have to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||||
|
Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
|
||||||
|
viverra nec, fringilla in, laoreet vitae, risus.</li>
|
||||||
|
<li>Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
|
||||||
|
Suspendisse id sem consectetuer libero luctus adipiscing.</li>
|
||||||
|
</ul>
|
||||||
|
<p>List items may consist of multiple paragraphs. Each subsequent
|
||||||
|
paragraph in a list item must be indented by either 4 spaces
|
||||||
|
or one tab:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#inline">Inline</a></li>
|
<li><p>This is a list item with two paragraphs. Lorem ipsum dolor
|
||||||
<li><a href="#codeblocks">Codeblocks</a></li>
|
sit amet, consectetuer adipiscing elit. Aliquam hendrerit
|
||||||
<li><a href="#declare-the-language">Declare the language</a></li>
|
mi posuere lectus.</p>
|
||||||
<li><a href="#escape-newlines">Escape newlines</a></li>
|
<p>Vestibulum enim wisi, viverra nec, fringilla in, laoreet
|
||||||
<li><a href="#nest-codeblocks-within-lists">Nest codeblocks within lists</a></li>
|
vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
|
||||||
</ol>
|
sit amet velit.</p>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#links">Links</a>
|
<li><p>Suspendisse id sem consectetuer libero luctus adipiscing.</p>
|
||||||
<ol>
|
|
||||||
<li><a href="#use-informative-markdown-link-titles">Use informative Markdown link titles</a></li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
<li><a href="#images">Images</a></li>
|
|
||||||
<li><a href="#prefer-lists-to-tables">Prefer lists to tables</a></li>
|
|
||||||
<li><a href="#strongly-prefer-markdown-to-html">Strongly prefer Markdown to HTML</a></li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<h2 id="document-layout">Document layout</h2>
|
|
||||||
|
|
||||||
<p>In general, most documents benefit from some variation of the following layout:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh"># Document Title</span>
|
|
||||||
|
|
||||||
Short introduction.
|
|
||||||
|
|
||||||
[TOC]
|
|
||||||
|
|
||||||
<span class="gu">## Topic</span>
|
|
||||||
|
|
||||||
Content.
|
|
||||||
|
|
||||||
<span class="gu">## See also</span>
|
|
||||||
<span class="p">
|
|
||||||
*</span> https://link-to-more-info
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge"># Document Title</code>: The first heading should be a level one heading, and
|
|
||||||
should ideally be the same or nearly the same as the filename. The first
|
|
||||||
level one heading is used as the page <code class="language-plaintext highlighter-rouge"><title></code>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge">author</code>: <em>Optional</em>. If you’d like to claim ownership of the document or
|
|
||||||
if you are very proud of it, add yourself under the title. However,
|
|
||||||
revision history generally suffices.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge">Short introduction.</code> 1-3 sentences providing a high-level overview of the
|
|
||||||
topic. Imagine yourself as a complete newbie, who landed on your “Extending
|
|
||||||
Foo” doc and needs to know the most basic assumptions you take for granted.
|
|
||||||
“What is Foo? Why would I extend it?”</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge">[TOC]</code>: if you use hosting that supports table of contents, such as Gitiles,
|
|
||||||
put <code class="language-plaintext highlighter-rouge">[TOC]</code> after the short introduction. See
|
|
||||||
<a href="https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md#Table-of-contents"><code class="language-plaintext highlighter-rouge">[TOC]</code> documentation</a>.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge">## Topic</code>: The rest of your headings should start from level 2.</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><code class="language-plaintext highlighter-rouge">## See also</code>: Put miscellaneous links at the bottom for the user who wants
|
|
||||||
to know more or didn’t find what she needed.</p>
|
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
<p>It looks nice if you indent every line of the subsequent
|
||||||
<h2 id="character-line-limit">Character line limit</h2>
|
paragraphs, but here again, Markdown will allow you to be
|
||||||
|
lazy:</p>
|
||||||
<p>Obey projects’ character line limit wherever possible. Long URLs and tables are
|
<ul>
|
||||||
the usual suspects when breaking the rule. (Headings also can’t be wrapped, but
|
<li><p>This is a list item with two paragraphs.</p>
|
||||||
we encourage keeping them short). Otherwise, wrap your text:</p>
|
<p>This is the second paragraph in the list item. You're
|
||||||
|
only required to indent the first line. Lorem ipsum dolor
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Lorem ipsum dolor sit amet, nec eius volumus patrioque cu, nec et commodo
|
sit amet, consectetuer adipiscing elit.</p>
|
||||||
hendrerit, id nobis saperet fuisset ius.
|
</li>
|
||||||
<span class="p">
|
<li><p>Another item in the same list.</p>
|
||||||
*</span> Malorum moderatius vim eu. In vix dico persecuti. Te nam saperet percipitur
|
</li>
|
||||||
interesset. See the <span class="p">[</span><span class="nv">foo docs</span><span class="p">](</span><span class="sx">https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md</span><span class="p">)</span>.
|
</ul>
|
||||||
</code></pre></div></div>
|
<p>To put a blockquote within a list item, the blockquote's <code>></code>
|
||||||
|
delimiters need to be indented:</p>
|
||||||
<p>Often, inserting a newline before a long link preserves readability while
|
<ul>
|
||||||
minimizing the overflow:</p>
|
<li><p>A list item with a blockquote:</p>
|
||||||
|
<blockquote>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Lorem ipsum dolor sit amet. See the
|
<p>This is a blockquote
|
||||||
<span class="p">[</span><span class="nv">foo docs</span><span class="p">](</span><span class="sx">https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md</span><span class="p">)</span>
|
inside a list item.</p>
|
||||||
for details.
|
</blockquote>
|
||||||
</code></pre></div></div>
|
</li>
|
||||||
|
</ul>
|
||||||
<h2 id="trailing-whitespace">Trailing whitespace</h2>
|
<p>To put a code block within a list item, the code block needs
|
||||||
|
to be indented <em>twice</em> -- 8 spaces or two tabs:</p>
|
||||||
<p>Don’t use trailing whitespace, use a trailing backslash.</p>
|
<ul>
|
||||||
|
<li><p>A list item with a code block:</p>
|
||||||
<p>The <a href="http://spec.commonmark.org/0.20/#hard-line-breaks">CommonMark spec</a> decrees
|
<pre><code><code goes here>
|
||||||
that two spaces at the end of a line should insert a <code class="language-plaintext highlighter-rouge"><br /></code> tag. However, many
|
</code></pre>
|
||||||
directories have a trailing whitespace presubmit check in place, and many IDEs
|
</li>
|
||||||
will clean it up anyway.</p>
|
</ul>
|
||||||
|
<h3>Code Blocks</h3>
|
||||||
<p>Best practice is to avoid the need for a <code class="language-plaintext highlighter-rouge"><br /></code> altogether. Markdown creates
|
<p>Pre-formatted code blocks are used for writing about programming or
|
||||||
paragraph tags for you simply with newlines: get used to that.</p>
|
markup source code. Rather than forming normal paragraphs, the lines
|
||||||
|
of a code block are interpreted literally. Markdown wraps a code block
|
||||||
<h2 id="headings">Headings</h2>
|
in both <code><pre></code> and <code><code></code> tags.</p>
|
||||||
|
<p>To produce a code block in Markdown, simply indent every line of the
|
||||||
<h3 id="atx-style-headings">ATX-style headings</h3>
|
block by at least 4 spaces or 1 tab.</p>
|
||||||
|
<p>This is a normal paragraph:</p>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gu">## Heading 2</span>
|
<pre><code>This is a code block.
|
||||||
</code></pre></div></div>
|
</code></pre>
|
||||||
|
<p>Here is an example of AppleScript:</p>
|
||||||
<p>Headings with <code class="language-plaintext highlighter-rouge">=</code> or <code class="language-plaintext highlighter-rouge">-</code> underlines can be annoying to maintain and don’t fit
|
<pre><code>tell application "Foo"
|
||||||
with the rest of the heading syntax. The user has to ask: Does <code class="language-plaintext highlighter-rouge">---</code> mean H1 or
|
beep
|
||||||
H2?</p>
|
end tell
|
||||||
|
</code></pre>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gh">Heading - do you remember what level? DO NOT DO THIS.
|
<p>A code block continues until it reaches a line that is not indented
|
||||||
---------
|
(or the end of the article).</p>
|
||||||
</span></code></pre></div></div>
|
<p>Within a code block, ampersands (<code>&</code>) and angle brackets (<code><</code> and <code>></code>)
|
||||||
|
are automatically converted into HTML entities. This makes it very
|
||||||
<h3 id="add-spacing-to-headings">Add spacing to headings</h3>
|
easy to include example HTML source code using Markdown -- just paste
|
||||||
|
it and indent it, and Markdown will handle the hassle of encoding the
|
||||||
<p>Prefer spacing after <code class="language-plaintext highlighter-rouge">#</code> and newlines before and after:</p>
|
ampersands and angle brackets. For example, this:</p>
|
||||||
|
<pre><code><div class="footer">
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...text before.
|
&copy; 2004 Foo Corporation
|
||||||
|
</div>
|
||||||
<span class="gh"># Heading 1</span>
|
</code></pre>
|
||||||
|
<p>Regular Markdown syntax is not processed within code blocks. E.g.,
|
||||||
Text after...
|
asterisks are just literal asterisks within a code block. This means
|
||||||
</code></pre></div></div>
|
it's also easy to use Markdown to write about Markdown's own syntax.</p>
|
||||||
|
<pre><code>tell application "Foo"
|
||||||
<p>Lack of spacing makes it a little harder to read in source:</p>
|
beep
|
||||||
|
end tell
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...text before.
|
</code></pre>
|
||||||
|
<h2>Span Elements</h2>
|
||||||
<span class="gh">#Heading 1</span>
|
<h3>Links</h3>
|
||||||
Text after... DO NOT DO THIS.
|
<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>
|
||||||
</code></pre></div></div>
|
<p>In both styles, the link text is delimited by [square brackets].</p>
|
||||||
|
<p>To create an inline link, use a set of regular parentheses immediately
|
||||||
<h2 id="lists">Lists</h2>
|
after the link text's closing square bracket. Inside the parentheses,
|
||||||
|
put the URL where you want the link to point, along with an <em>optional</em>
|
||||||
<h3 id="use-lazy-numbering-for-long-lists">Use lazy numbering for long lists</h3>
|
title for the link, surrounded in quotes. For example:</p>
|
||||||
|
<p>This is <a href="http://example.com/">an example</a> inline link.</p>
|
||||||
<p>Markdown is smart enough to let the resulting HTML render your numbered lists
|
<p><a href="http://example.net/">This link</a> has no title attribute.</p>
|
||||||
correctly. For longer lists that may change, especially long nested lists, use
|
<h3>Emphasis</h3>
|
||||||
“lazy” numbering:</p>
|
<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of
|
||||||
|
emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">1.</span> Foo.
|
HTML <code><em></code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML
|
||||||
<span class="p">1.</span> Bar.
|
<code><strong></code> tag. E.g., this input:</p>
|
||||||
<span class="p"> 1.</span> Foofoo.
|
<p><em>single asterisks</em></p>
|
||||||
<span class="p"> 1.</span> Barbar.
|
<p><em>single underscores</em></p>
|
||||||
<span class="p">1.</span> Baz.
|
<p><strong>double asterisks</strong></p>
|
||||||
</code></pre></div></div>
|
<p><strong>double underscores</strong></p>
|
||||||
|
<h3>Code</h3>
|
||||||
<p>However, if the list is small and you don’t anticipate changing it, prefer fully
|
<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).
|
||||||
numbered lists, because it’s nicer to read in source:</p>
|
Unlike a pre-formatted code block, a code span indicates code within a
|
||||||
|
normal paragraph. For example:</p>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">1.</span> Foo.
|
<p>Use the <code>printf()</code> function.</p>
|
||||||
<span class="p">2.</span> Bar.
|
<h3>Table</h3>
|
||||||
<span class="p">3.</span> Baz.
|
<table>
|
||||||
</code></pre></div></div>
|
<thead>
|
||||||
|
<tr>
|
||||||
<h3 id="nested-list-spacing">Nested list spacing</h3>
|
<th>Item</th>
|
||||||
|
<th>Price</th>
|
||||||
<p>When nesting lists, use a 4 space indent for both numbered and bulleted lists:</p>
|
<th># In stock</th>
|
||||||
|
</tr>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">1.</span> 2 spaces after a numbered list.
|
</thead>
|
||||||
4 space indent for wrapped text.
|
<tbody>
|
||||||
<span class="p">2.</span> 2 spaces again.
|
<tr>
|
||||||
<span class="p">
|
<td>Juicy Apples</td>
|
||||||
*</span> 3 spaces after a bullet.
|
<td>1.99</td>
|
||||||
4 space indent for wrapped text.
|
<td><em>7</em></td>
|
||||||
<span class="p"> 1.</span> 2 spaces after a numbered list.
|
</tr>
|
||||||
8 space indent for the wrapped text of a nested list.
|
<tr>
|
||||||
<span class="p"> 2.</span> Looks nice, don't it?
|
<td>Bananas</td>
|
||||||
<span class="p">*</span> 3 spaces after a bullet.
|
<td><strong>1.89</strong></td>
|
||||||
</code></pre></div></div>
|
<td>5234</td>
|
||||||
|
</tr>
|
||||||
<p>The following works, but it’s very messy:</p>
|
<tr>
|
||||||
|
<td>Tomatoes</td>
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">*</span> One space,
|
<td><strong>1.89</strong></td>
|
||||||
with no indent for wrapped text.
|
<td>5234</td>
|
||||||
<span class="p"> 1.</span> Irregular nesting... DO NOT DO THIS.
|
</tr>
|
||||||
</code></pre></div></div>
|
</tbody>
|
||||||
|
</table>
|
||||||
<p>Even when there’s no nesting, using the 4 space indent makes layout consistent
|
</footer>
|
||||||
for wrapped text:</p>
|
<footer>
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">*</span> Foo,
|
|
||||||
wrapped.
|
|
||||||
<span class="p">
|
|
||||||
1.</span> 2 spaces
|
|
||||||
and 4 space indenting.
|
|
||||||
<span class="p">2.</span> 2 spaces again.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>However, when lists are small, not nested, and a single line, one space can
|
|
||||||
suffice for both kinds of lists:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">*</span> Foo
|
|
||||||
<span class="p">*</span> Bar
|
|
||||||
<span class="p">*</span> Baz.
|
|
||||||
<span class="p">
|
|
||||||
1.</span> Foo.
|
|
||||||
<span class="p">2.</span> Bar.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<h2 id="code">Code</h2>
|
|
||||||
|
|
||||||
<h3 id="inline">Inline</h3>
|
|
||||||
|
|
||||||
<p>`Backticks` designate <code class="language-plaintext highlighter-rouge">inline code</code>, and will render all wrapped content
|
|
||||||
literally. Use them for short code quotations and field names:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You'll want to run <span class="sb">`really_cool_script.sh arg`</span>.
|
|
||||||
|
|
||||||
Pay attention to the <span class="sb">`foo_bar_whammy`</span> field in that table.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>Use inline code when referring to file types in an abstract sense, rather than a
|
|
||||||
specific file:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Be sure to update your <span class="sb">`README.md`</span>!
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>Backticks are the most common approach for “escaping” Markdown metacharacters;
|
|
||||||
in most situations where escaping would be needed, code font just makes sense
|
|
||||||
anyway.</p>
|
|
||||||
|
|
||||||
<h3 id="codeblocks">Codeblocks</h3>
|
|
||||||
|
|
||||||
<p>For code quotations longer than a single line, use a codeblock:</p>
|
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
```python
|
Folder with several child directories
|
||||||
def Foo(self, bar):
|
|
||||||
self.bar = bar
|
├── c2
|
||||||
```
|
│ └── c3
|
||||||
|
│ └── empty-file.txt
|
||||||
|
├── empty-file.txt
|
||||||
|
└── README.txt
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h4 id="declare-the-language">Declare the language</h4>
|
</footer>
|
||||||
|
|
||||||
<p>It is best practice to explicitly declare the language, so that neither the
|
|
||||||
syntax highlighter nor the next editor must guess.</p>
|
|
||||||
|
|
||||||
<h4 id="indented-codeblocks-are-sometimes-cleaner">Indented codeblocks are sometimes cleaner</h4>
|
|
||||||
|
|
||||||
<p>Four-space indenting is also interpreted as a codeblock. These can look
|
|
||||||
cleaner and be easier to read in source, but there is no way to specify the
|
|
||||||
language. We encourage their use when writing many short snippets:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>You'll need to run:<span class="sb">
|
|
||||||
|
|
||||||
bazel run :thing -- --foo
|
|
||||||
|
|
||||||
</span>And then:<span class="sb">
|
|
||||||
|
|
||||||
bazel run :another_thing -- --bar
|
|
||||||
|
|
||||||
</span>And again:<span class="sb">
|
|
||||||
|
|
||||||
bazel run :yet_again -- --baz
|
|
||||||
</span></code></pre></div></div>
|
|
||||||
|
|
||||||
<h4 id="escape-newlines">Escape newlines</h4>
|
|
||||||
|
|
||||||
<p>Because most commandline snippets are intended to be copied and pasted directly
|
|
||||||
into a terminal, it’s best practice to escape any newlines. Use a single
|
|
||||||
backslash at the end of the line:</p>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
```shell
|
|
||||||
bazel run :target -- --flag --foo=longlonglonglonglongvalue \
|
|
||||||
--bar=anotherlonglonglonglonglonglonglonglonglonglongvalue
|
|
||||||
```
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h4 id="nest-codeblocks-within-lists">Nest codeblocks within lists</h4>
|
|
||||||
|
|
||||||
<p>If you need a codeblock within a list, make sure to indent it so as to not break
|
|
||||||
the list:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">*</span> Bullet.<span class="sb">
|
|
||||||
|
|
||||||
```c++
|
|
||||||
int foo;
|
|
||||||
```
|
|
||||||
|
|
||||||
</span><span class="p">*</span> Next bullet.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>You can also create a nested code block with 4 spaces. Simply indent 4
|
|
||||||
additional spaces from the list indentation:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">*</span> Bullet.<span class="sb">
|
|
||||||
|
|
||||||
int foo;
|
|
||||||
|
|
||||||
</span><span class="p">*</span> Next bullet.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<h2 id="links">Links</h2>
|
|
||||||
|
|
||||||
<p>Long links make source Markdown difficult to read and break the 80 character
|
|
||||||
wrapping. <strong>Wherever possible, shorten your links</strong>.</p>
|
|
||||||
|
|
||||||
<h3 id="use-informative-markdown-link-titles">Use informative Markdown link titles</h3>
|
|
||||||
|
|
||||||
<p>Markdown link syntax allows you to set a link title, just as HTML does. Use it
|
|
||||||
wisely.</p>
|
|
||||||
|
|
||||||
<p>Titling your links as “link” or “here” tells the reader precisely nothing when
|
|
||||||
quickly scanning your doc and is a waste of space:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>See the syntax guide for more info: <span class="p">[</span><span class="nv">link</span><span class="p">](</span><span class="sx">syntax_guide.md</span><span class="p">)</span>.
|
|
||||||
Or, check out the style guide <span class="p">[</span><span class="nv">here</span><span class="p">](</span><span class="sx">style_guide.md</span><span class="p">)</span>.
|
|
||||||
DO NOT DO THIS.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>Instead, write the sentence naturally, then go back and wrap the most
|
|
||||||
appropriate phrase with the link:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>See the <span class="p">[</span><span class="nv">syntax guide</span><span class="p">](</span><span class="sx">syntax_guide.md</span><span class="p">)</span> for more info.
|
|
||||||
Or, check out the <span class="p">[</span><span class="nv">style guide</span><span class="p">](</span><span class="sx">style_guide.md</span><span class="p">)</span>.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<h2 id="images">Images</h2>
|
|
||||||
|
|
||||||
<p>Use images sparingly, and prefer simple screenshots. This guide is designed
|
|
||||||
around the idea that plain text gets users down to the business of communication
|
|
||||||
faster with less reader distraction and author procrastination. However, it’s
|
|
||||||
sometimes very helpful to show what you mean.</p>
|
|
||||||
|
|
||||||
<p>See <a href="https://gerrit.googlesource.com/gitiles/+/master/Documentation/markdown.md#Images">image syntax</a>.</p>
|
|
||||||
|
|
||||||
<h2 id="prefer-lists-to-tables">Prefer lists to tables</h2>
|
|
||||||
|
|
||||||
<p>Any tables in your Markdown should be small. Complex, large tables are difficult
|
|
||||||
to read in source and most importantly, <strong>a pain to modify later</strong>.</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Fruit | Attribute | Notes
|
|
||||||
--- | --- | --- | ---
|
|
||||||
Apple | <span class="p">[</span><span class="nv">Juicy</span><span class="p">](</span><span class="sx">https://example.com/SomeReallyReallyReallyReallyReallyReallyReallyReallyLongQuery</span><span class="p">)</span>, Firm, Sweet | Apples keep doctors away.
|
|
||||||
Banana | <span class="p">[</span><span class="nv">Convenient</span><span class="p">](</span><span class="sx">https://example.com/SomeDifferentReallyReallyReallyReallyReallyReallyReallyReallyLongQuery</span><span class="p">)</span>, Soft, Sweet | Contrary to popular belief, most apes prefer mangoes.
|
|
||||||
|
|
||||||
DO NOT DO THIS
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p><a href="#lists">Lists</a> and subheadings usually suffice to present the same information
|
|
||||||
in a slightly less compact, though much more edit-friendly way:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gu">## Fruits</span>
|
|
||||||
|
|
||||||
<span class="gu">### Apple</span>
|
|
||||||
<span class="p">
|
|
||||||
*</span> <span class="p">[</span><span class="nv">Juicy</span><span class="p">](</span><span class="sx">https://SomeReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongURL</span><span class="p">)</span>
|
|
||||||
<span class="p">*</span> Firm
|
|
||||||
<span class="p">*</span> Sweet
|
|
||||||
|
|
||||||
Apples keep doctors away.
|
|
||||||
|
|
||||||
<span class="gu">### Banana</span>
|
|
||||||
<span class="p">
|
|
||||||
*</span> <span class="p">[</span><span class="nv">Convenient</span><span class="p">](</span><span class="sx">https://example.com/SomeDifferentReallyReallyReallyReallyReallyReallyReallyReallyLongQuery</span><span class="p">)</span>
|
|
||||||
<span class="p">*</span> Soft
|
|
||||||
<span class="p">*</span> Sweet
|
|
||||||
|
|
||||||
Contrary to popular belief, most apes prefer mangoes.
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<p>However, there are times when a small table is called for:</p>
|
|
||||||
|
|
||||||
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Transport | Favored by | Advantages
|
|
||||||
--- | --- | ---
|
|
||||||
Swallow | Coconuts | Otherwise unladen
|
|
||||||
Bicycle | Miss Gulch | Weatherproof
|
|
||||||
X-34 landspeeder | Whiny farmboys | Cheap since the X-38 came out
|
|
||||||
</code></pre></div></div>
|
|
||||||
|
|
||||||
<h2 id="strongly-prefer-markdown-to-html">Strongly prefer Markdown to HTML</h2>
|
|
||||||
|
|
||||||
<p>Please prefer standard Markdown syntax wherever possible and avoid HTML hacks.
|
|
||||||
If you can’t seem to accomplish what you want, reconsider whether you really
|
|
||||||
need it. Except for <a href="#prefer-lists-to-tables">big tables</a>, Markdown meets almost
|
|
||||||
all needs already.</p>
|
|
||||||
|
|
||||||
<p>Every bit of HTML or Javascript hacking reduces the readability and portability.
|
|
||||||
This in turn limits the usefulness of integrations with
|
|
||||||
other tools, which may either present the source as plain text or render it. See
|
|
||||||
<a href="/styleguide/docguide/philosophy.html">Philosophy</a>.</p>
|
|
||||||
|
|
||||||
<p>Gitiles does not render HTML.</p>
|
|
||||||
<!-- var t08_foot -->
|
<!-- var t08_foot -->
|
||||||
<script>
|
<script>
|
||||||
var filterEl = document.getElementById("filter");
|
var filterEl = document.getElementById("filter");
|
||||||
|
|
Loading…
Reference in a new issue