Last active
June 7, 2022 01:43
-
-
Save coderofsalvation/4496972 to your computer and use it in GitHub Desktop.
Quickndirty bash-utility to generate REST-documentation from sourcecode comments into css-styles html (or plainhtml).
Can be handy for inclusion into phpdoc/phpdoctor/doxygen-dochains, instead of using heavyweight alternatives.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# A quickndirty bash-utility to generate REST-documentation from sourcecode comments. | |
# (initially aimed at php-files, but js should also work) | |
# Basically its a c-style comment -> markdown -> html converter | |
# Dependancies: | |
# - awk | |
# - sed | |
# - bash | |
# - php | |
# | |
# demo-url: http://pastie.org/5657190 | |
# | |
# license: {{{1 | |
# Copyright 2012, Leon van Kammen / Coder of Salvation. All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without modification, are | |
# permitted provided that the following conditions are met: | |
# | |
# 1. Redistributions of source code must retain the above copyright notice, this list of | |
# conditions and the following disclaimer. | |
# | |
# 2. Redistributions in binary form must reproduce the above copyright notice, this list | |
# of conditions and the following disclaimer in the documentation and/or other materials | |
# provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR | |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
# | |
# The views and conclusions contained in the software and documentation are those of the | |
# authors and should not be interpreted as representing official policies, either expressed | |
# or implied, of Coder of Salvation. | |
# | |
# 1}}} | |
USAGE=' | |
Usage: RESTdoc <inputdir> <outputdir> <html|htmlcss>{{{ | |
Example: ./RESTdoc inputdir output.html htmlcss | |
(this will search all .php files in inputdir for the tags below, | |
and will generate html/css documentation into output.html) | |
/* | |
* @RESTdoc_name get\_foo | |
* @RESTdoc_param `date` (string, eg. '2012-12-12') | |
* @RESTdoc_param `apikey` (string, eg. 'qwoeiuqewer') | |
* @RESTdoc_test http://foo.com/REST?date=2012-12-12&apikey=2323oiu23 | |
* @RESTdoc_desc Lorem dolor sit _amet_ | |
* @RESTdoc_desc Dolor fascismus corpus delictus | |
*/ | |
' | |
# WARNING: if you don't view this file with vim you might go crazy (folding) | |
SELF_ABS=`readlink -f $0` | |
SELF_PATH=`dirname $SELF_ABS` | |
SELF=$( basename $0 ) | |
SELF_LONG=$0 | |
NAVIGATION="" | |
requirements="awk cat printf echo ls" | |
regex_external='[^`_*]{!' | |
# HTML_HEAD: {{{1 | |
html_head='<!DOCTYPE html> | |
<html id="home" lang="en"> | |
<head> | |
<meta charset=utf-8 /> | |
<meta name="viewport" content="width=620" /> | |
<title>%s</title> | |
</head> | |
<body> | |
%s | |
' | |
# 1}}} | |
# HTML_NAVIGATION: {{{1 | |
html_navigation_option='<option %s value="%s">%s</option>' | |
html_navigation=' | |
'$HTML_BANNER' | |
<div style="width:20.0em;float:right"> | |
<select style="width:100%%" onchange="document.location.href = this.options[ this.selectedIndex ].value"> | |
%s | |
</select> | |
</div> | |
<div style="clear:both;border-bottom:1px solid #CCC; "></div> | |
' | |
# 1}}} | |
# HTML_CSS: {{{1 | |
html_css=' | |
<style type="text/css"> | |
/* Kevin Burke wondefull CSS (http://kevinburke.bitbucket.org/markdowncss/) */ | |
body{ | |
margin: 0 auto; | |
font-family: Georgia, Palatino, serif; | |
color: #444444; | |
line-height: 1; | |
max-width: 960px; | |
padding: 30px; | |
} | |
code, | |
a:visited, | |
a:link, | |
a:active | |
{ | |
color:#007799 | |
} | |
i, cite, em, var, address, dfn { | |
color:#666 | |
} | |
h1, h2, h3, h4 { | |
color: #111111; | |
font-weight: 400; | |
} | |
h1, h2, h3, h4, h5, p { | |
margin-bottom: 24px; | |
padding: 0; | |
} | |
h1 { | |
font-size: 48px; | |
} | |
h2 { | |
font-size: 36px; | |
/* The bottom margin is small. Its designed to be used with gray meta text | |
* below a post title. */ | |
margin: 24px 0 6px; | |
} | |
h3 { | |
font-size: 24px; | |
} | |
h4 { | |
font-size: 21px; | |
} | |
h5 { | |
font-size: 18px; | |
} | |
a { | |
margin: 0; | |
padding: 0; | |
vertical-align: baseline; | |
} | |
a:hover { | |
text-decoration: none; | |
color: #ff6600; | |
} | |
ul, ol { | |
padding: 0; | |
margin: 0px 0px 0px 42px; | |
} | |
li { | |
line-height: 24px; | |
} | |
li ul, li ul { | |
margin-left: 24px; | |
} | |
p, ul, ol { | |
font-size: 16px; | |
line-height: 24px; | |
max-width: 540px; | |
} | |
pre { | |
padding: 0px 24px; | |
max-width: 800px; | |
white-space: pre-wrap; | |
} | |
code { | |
font-family: Consolas, Monaco, Andale Mono, monospace; | |
line-height: 1.5; | |
font-size: 13px; | |
} | |
aside { | |
display: block; | |
float: right; | |
width: 390px; | |
} | |
blockquote { | |
border-left:.5em solid #eee; | |
padding: 0 2em; | |
margin-left:0; | |
max-width: 476px; | |
} | |
blockquote cite { | |
font-size:14px; | |
line-height:20px; | |
color:#bfbfbf; | |
} | |
blockquote cite:before { | |
content: "\2014 \00A0"; | |
} | |
blockquote p { | |
color: #666; | |
max-width: 460px; | |
} | |
hr { | |
width: 540px; | |
text-align: left; | |
margin: 0 auto 0 0; | |
color: #999; | |
} | |
/* Code below this line is copyright Twitter Inc. */ | |
button, | |
input, | |
select, | |
textarea { | |
font-size: 100%; | |
margin: 0; | |
vertical-align: baseline; | |
*vertical-align: middle; | |
} | |
button, input { | |
line-height: normal; | |
*overflow: visible; | |
} | |
button::-moz-focus-inner, input::-moz-focus-inner { | |
border: 0; | |
padding: 0; | |
} | |
button, | |
input[type="button"], | |
input[type="reset"], | |
input[type="submit"] { | |
cursor: pointer; | |
-webkit-appearance: button; | |
} | |
input[type=checkbox], input[type=radio] { | |
cursor: pointer; | |
} | |
/* override default chrome & firefox settings */ | |
input:not([type="image"]), textarea { | |
-webkit-box-sizing: content-box; | |
-moz-box-sizing: content-box; | |
box-sizing: content-box; | |
} | |
input[type="search"] { | |
-webkit-appearance: textfield; | |
-webkit-box-sizing: content-box; | |
-moz-box-sizing: content-box; | |
box-sizing: content-box; | |
} | |
input[type="search"]::-webkit-search-decoration { | |
-webkit-appearance: none; | |
} | |
label, | |
input, | |
select, | |
textarea { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
font-size: 13px; | |
font-weight: normal; | |
line-height: normal; | |
margin-bottom: 18px; | |
} | |
input[type=checkbox], input[type=radio] { | |
cursor: pointer; | |
margin-bottom: 0; | |
} | |
input[type=text], | |
input[type=password], | |
textarea, | |
select { | |
display: inline-block; | |
width: 210px; | |
padding: 4px; | |
font-size: 13px; | |
font-weight: normal; | |
line-height: 18px; | |
height: 18px; | |
color: #808080; | |
border: 1px solid #ccc; | |
-webkit-border-radius: 3px; | |
-moz-border-radius: 3px; | |
border-radius: 3px; | |
} | |
select, input[type=file] { | |
height: 27px; | |
line-height: 27px; | |
} | |
textarea { | |
height: auto; | |
} | |
/* grey out placeholders */ | |
:-moz-placeholder { | |
color: #bfbfbf; | |
} | |
::-webkit-input-placeholder { | |
color: #bfbfbf; | |
} | |
input[type=text], | |
input[type=password], | |
select, | |
textarea { | |
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s; | |
-moz-transition: border linear 0.2s, box-shadow linear 0.2s; | |
transition: border linear 0.2s, box-shadow linear 0.2s; | |
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); | |
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); | |
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); | |
} | |
input[type=text]:focus, input[type=password]:focus, textarea:focus { | |
outline: none; | |
border-color: rgba(82, 168, 236, 0.8); | |
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); | |
-moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); | |
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); | |
} | |
/* buttons */ | |
button { | |
display: inline-block; | |
padding: 4px 14px; | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
font-size: 13px; | |
line-height: 18px; | |
-webkit-border-radius: 4px; | |
-moz-border-radius: 4px; | |
border-radius: 4px; | |
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); | |
background-color: #0064cd; | |
background-repeat: repeat-x; | |
background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); | |
background-image: -moz-linear-gradient(top, #049cdb, #0064cd); | |
background-image: -ms-linear-gradient(top, #049cdb, #0064cd); | |
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); | |
background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); | |
background-image: -o-linear-gradient(top, #049cdb, #0064cd); | |
background-image: linear-gradient(top, #049cdb, #0064cd); | |
color: #fff; | |
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); | |
border: 1px solid #004b9a; | |
border-bottom-color: #003f81; | |
-webkit-transition: 0.1s linear all; | |
-moz-transition: 0.1s linear all; | |
transition: 0.1s linear all; | |
border-color: #0064cd #0064cd #003f81; | |
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); | |
} | |
button:hover { | |
color: #fff; | |
background-position: 0 -15px; | |
text-decoration: none; | |
} | |
button:active { | |
-webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
-moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); | |
} | |
button::-moz-focus-inner { | |
padding: 0; | |
border: 0; | |
} | |
</style> | |
' | |
# 1}}} | |
# HTML_FOOT: {{{1 | |
html_foot=''"$HTML_FOOTER"'</body></html>' | |
# 1}}} | |
# md2html.awk: {{{1 | |
md2html='#!/usr/bin/awk -f | |
# | |
# by: Jesus Galan (yiyus) 2009 | |
# | |
# Usage: md2html.awk file.md > file.html | |
# See: http://4l77.com/src/md2html.awk | |
function eschtml(t) { | |
gsub("&", "\\&", t); | |
gsub("<", "\\<", t); | |
return t; | |
} | |
function oprint(t){ | |
if(nr == 0) | |
print t; | |
else | |
otext = otext "\n" t; | |
} | |
function subref(id){ | |
for(; nr > 0 && sub("<<" id, ref[id], otext); nr--); | |
if(nr == 0 && otext) { | |
print otext; | |
otext = ""; | |
} | |
} | |
function nextil(t) { | |
if(!match(t, /[`<&\[*_\\-]|(\!\[)/)) | |
return t; | |
t1 = substr(t, 1, RSTART - 1); | |
tag = substr(t, RSTART, RLENGTH); | |
t2 = substr(t, RSTART + RLENGTH); | |
if(ilcode && tag != "`") | |
return eschtml(t1 tag) nextil(t2); | |
# Backslash escaping | |
if(tag == "\\"){ | |
if(match(t2, /^[\\`*_{}\[\]()#+\-\.!]/)){ | |
tag = substr(t2, 1, 1); | |
t2 = substr(t2, 2); | |
} | |
return t1 tag nextil(t2); | |
} | |
# Dashes | |
if(tag == "-"){ | |
if(sub(/^-/, "", t2)) | |
tag = "—"; | |
return t1 tag nextil(t2); | |
} | |
# Inline Code | |
if(tag == "`"){ | |
if(sub(/^`/, "", t2)){ | |
if(!match(t2, /``/)) | |
return t1 "”" nextil(t2); | |
ilcode2 = !ilcode2; | |
} | |
else if(ilcode2) | |
return t1 tag nextil(t2); | |
tag = "<code>"; | |
if(ilcode){ | |
t1 = eschtml(t1); | |
tag = "</code>"; | |
} | |
ilcode = !ilcode; | |
return t1 tag nextil(t2); | |
} | |
if(tag == "<"){ | |
# Autolinks | |
if(match(t2, /^[^ ]+[\.@][^ ]+>/)){ | |
url = eschtml(substr(t2, 1, RLENGTH - 1)); | |
t2 = substr(t2, RLENGTH + 1); | |
linktext = url; | |
if(match(url, /@/) && !match(url, /^mailto:/)) | |
url = "mailto:" url; | |
return t1 "<a href=\"" url "\">" linktext "</a>" nextil(t2); | |
} | |
# Html tags | |
if(match(t2, /^[A-Za-z\/!][^>]*>/)){ | |
tag = tag substr(t2, RSTART, RLENGTH); | |
t2 = substr(t2, RLENGTH + 1); | |
return t1 tag nextil(t2); | |
} | |
return t1 "<" nextil(t2); | |
} | |
# Html special entities | |
if(tag == "&"){ | |
if(match(t2, /^#?[A-Za-z0-9]+;/)){ | |
tag = tag substr(t2, RSTART, RLENGTH); | |
t2 = substr(t2, RLENGTH + 1); | |
return t1 tag nextil(t2); | |
} | |
return t1 "&" nextil(t2); | |
} | |
# Images | |
if(tag == "!["){ | |
if(!match(t2, /(\[.*\])|(\(.*\))/)) | |
return t1 tag nextil(t2); | |
match(t2, /^[^\]]*/); | |
alt = substr(t2, 1, RLENGTH); | |
t2 = substr(t2, RLENGTH + 2); | |
if(match(t2, /^\(/)){ | |
# Inline | |
sub(/^\(/, "", t2); | |
match(t2, /^[^\)]+/); | |
url = eschtml(substr(t2, 1, RLENGTH)); | |
t2 = substr(t2, RLENGTH + 2); | |
title = ""; | |
if(match(url, /[ ]+\".*\"[ ]*$/)) { | |
title = substr(url, RSTART, RLENGTH); | |
url = substr(url, 1, RSTART - 1); | |
match(title, /\".*\"/); | |
title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; | |
} | |
if(match(url, /^<.*>$/)) | |
url = substr(url, 2, RLENGTH - 2); | |
return t1 "<img src=\"" url "\" alt=\"" alt "\"" title " />" nextil(t2); | |
} | |
else{ | |
# Referenced | |
sub(/^ ?\[/, "", t2); | |
id = alt; | |
if(match(t2, /^[^\]]+/)) | |
id = substr(t2, 1, RLENGTH); | |
t2 = substr(t2, RLENGTH + 2); | |
if(ref[id]) | |
r = ref[id]; | |
else{ | |
r = "<<" id; | |
nr++; | |
} | |
return t1 "<img src=\"" r "\" alt=\"" alt "\" />" nextil(t2); | |
} | |
} | |
# Links | |
if(tag == "["){ | |
if(!match(t2, /(\[.*\])|(\(.*\))/)) | |
return t1 tag nextil(t2); | |
match(t2, /^[^\]]*(\[[^\]]*\][^\]]*)*/); | |
linktext = substr(t2, 1, RLENGTH); | |
t2 = substr(t2, RLENGTH + 2); | |
if(match(t2, /^\(/)){ | |
# Inline | |
match(t2, /^[^\)]+(\([^\)]+\)[^\)]*)*/); | |
url = substr(t2, 2, RLENGTH - 1); | |
pt2 = substr(t2, RLENGTH + 2); | |
title = ""; | |
if(match(url, /[ ]+\".*\"[ ]*$/)) { | |
title = substr(url, RSTART, RLENGTH); | |
url = substr(url, 1, RSTART - 1); | |
match(title, /\".*\"/); | |
title = " title=\"" substr(title, RSTART + 1, RLENGTH - 2) "\""; | |
} | |
if(match(url, /^<.*>$/)) | |
url = substr(url, 2, RLENGTH - 2); | |
url = eschtml(url); | |
return t1 "<a href=\"" url "\"" title ">" nextil(linktext) "</a>" nextil(pt2); | |
} | |
else{ | |
# Referenced | |
sub(/^ ?\[/, "", t2); | |
id = linktext; | |
if(match(t2, /^[^\]]+/)) | |
id = substr(t2, 1, RLENGTH); | |
t2 = substr(t2, RLENGTH + 2); | |
if(ref[id]) | |
r = ref[id]; | |
else{ | |
r = "<<" id; | |
nr++; | |
} | |
pt2 = t2; | |
return t1 "<a href=\"" r "\" />" nextil(linktext) "</a>" nextil(pt2); | |
} | |
} | |
# Emphasis | |
if(match(tag, /[*_]/)){ | |
ntag = tag; | |
if(sub("^" tag, "", t2)){ | |
if(stag[ns] == tag && match(t2, "^" tag)) | |
t2 = tag t2; | |
else | |
ntag = tag tag | |
} | |
n = length(ntag); | |
tag = (n == 2) ? "strong" : "em"; | |
if(match(t1, / $/) && match(t2, /^ /)) | |
return t1 tag nextil(t2); | |
if(stag[ns] == ntag){ | |
tag = "/" tag; | |
ns--; | |
} | |
else | |
stag[++ns] = ntag; | |
tag = "<" tag ">"; | |
return t1 tag nextil(t2); | |
} | |
} | |
function inline(t) { | |
ilcode = 0; | |
ilcode2 = 0; | |
ns = 0; | |
return nextil(t); | |
} | |
function printp(tag) { | |
if(!match(text, /^[ ]*$/)){ | |
text = inline(text); | |
if(tag != "") | |
oprint("<" tag ">" text "</" tag ">"); | |
else | |
oprint(text); | |
} | |
text = ""; | |
} | |
BEGIN { | |
blank = 0; | |
code = 0; | |
hr = 0; | |
html = 0; | |
nl = 0; | |
nr = 0; | |
otext = ""; | |
text = ""; | |
par = "p"; | |
} | |
# References | |
!code && /^ *\[[^\]]*\]:[ ]+/ { | |
sub(/^ *\[/, ""); | |
match($0, /\]/); | |
id = substr($0, 1, RSTART - 1); | |
sub(id "\\]:[ ]+", ""); | |
title = ""; | |
if(match($0, /\".*\"$/)) | |
title = "\" title=\"" substr($0, RSTART + 1, RLENGTH - 2); | |
sub(/[ ]+\".*\"$/, ""); | |
url = eschtml($0); | |
ref[id] = url title; | |
subref(id); | |
next; | |
} | |
# html | |
!html && /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ | |
isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/ { | |
if(code) | |
oprint("</pre></code>"); | |
for(; !text && block[nl] == "blockquote"; nl--) | |
oprint("</blockquote>"); | |
match($0, /^<(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ | |
isindex|menu|noframes|noscript|ol|p|pre|table|ul|!--)/); | |
htag = substr($0, 2, RLENGTH - 1); | |
if(!match($0, "(<\\/" htag ">)|((^<hr ?\\/?)|(--)>$)")) | |
html = 1; | |
if(html && match($0, /^<hr/)) | |
hr = 1; | |
oprint($0); | |
next; | |
} | |
html && (/(^<\/(address|blockquote|center|dir|div|dl|fieldset|form|h[1-6r]|\ | |
isindex|menu|noframes|noscript|ol|p|pre|table|ul).*)|(--)>$/ || | |
(hr && />$/)) { | |
html = 0; | |
hr = 0; | |
oprint($0); | |
next; | |
} | |
html { | |
oprint($0); | |
next; | |
} | |
# List and quote blocks | |
# Remove indentation | |
{ | |
for(nnl = 0; nnl < nl; nnl++) | |
if((match(block[nnl + 1], /[ou]l/) && !sub(/^( | )/, "")) || \ | |
(block[nnl + 1] == "blockquote" && !sub(/^> ?/, ""))) | |
break; | |
} | |
nnl < nl && !blank && text && ! /^ ? ? ?([*+-]|([0-9]+\.)+)( +| )/ { nnl = nl; } | |
# Quote blocks | |
{ | |
while(sub(/^> /, "")) | |
nblock[++nnl] = "blockquote"; | |
} | |
# Horizontal rules | |
{ hr = 0; } | |
(blank || (!text && !code)) && /^ ? ? ?([-*_][ ]*)([-*_][ ]*)([-*_][ ]*)+$/ { | |
if(code){ | |
oprint("</pre></code>"); | |
code = 0; | |
} | |
blank = 0; | |
nnl = 0; | |
hr = 1; | |
} | |
# List items | |
block[nl] ~ /[ou]l/ && /^$/ { | |
blank = 1; | |
next; | |
} | |
{ newli = 0; } | |
!hr && (nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?[*+-]( +| )/ { | |
sub(/^ ? ? ?[*+-]( +| )/, ""); | |
nnl++; | |
nblock[nnl] = "ul"; | |
newli = 1; | |
} | |
(nnl != nl || !text || block[nl] ~ /[ou]l/) && /^ ? ? ?([0-9]+\.)+( +| )/ { | |
sub(/^ ? ? ?([0-9]+\.)+( +| )/, ""); | |
nnl++; | |
nblock[nnl] = "ol"; | |
newli = 1; | |
} | |
newli { | |
if(blank && nnl == nl && !par) | |
par = "p"; | |
blank = 0; | |
printp(par); | |
if(nnl == nl && block[nl] == nblock[nl]) | |
oprint("</li><li>"); | |
} | |
blank && ! /^$/ { | |
if(match(block[nnl], /[ou]l/) && !par) | |
par = "p"; | |
printp(par); | |
par = "p"; | |
blank = 0; | |
} | |
# Close old blocks and open new ones | |
nnl != nl || nblock[nl] != block[nl] { | |
if(code){ | |
oprint("</pre></code>"); | |
code = 0; | |
} | |
printp(par); | |
b = (nnl > nl) ? nblock[nnl] : block[nnl]; | |
par = (match(b, /[ou]l/)) ? "" : "p"; | |
} | |
nnl < nl || (nnl == nl && nblock[nl] != block[nl]) { | |
for(; nl > nnl || (nnl == nl && pblock[nl] != block[nl]); nl--){ | |
if(match(block[nl], /[ou]l/)) | |
oprint("</li>"); | |
oprint("</" block[nl] ">"); | |
} | |
} | |
nnl > nl { | |
for(; nl < nnl; nl++){ | |
block[nl + 1] = nblock[nl + 1]; | |
oprint("<" block[nl + 1] ">"); | |
if(match(block[nl + 1], /[ou]l/)) | |
oprint("<li>"); | |
} | |
} | |
hr { | |
oprint("<hr>"); | |
next; | |
} | |
# Code blocks | |
code && /^$/ { | |
if(blanK) | |
oprint(""); | |
blank = 1; | |
next; | |
} | |
!text && sub(/^( | )/, "") { | |
if(blanK) | |
oprint(""); | |
blank = 0; | |
if(!code) | |
oprint("<code><pre>"); | |
code = 1; | |
$0 = eschtml($0); | |
oprint($0); | |
next; | |
} | |
code { | |
oprint("</pre></code>"); | |
code = 0; | |
} | |
# Setex-style Headers | |
text && /^=+$/ {printp("h1"); next;} | |
text && /^-+$/ {printp("h2"); next;} | |
# Atx-Style headers | |
/^#+/ && (!newli || par=="p" || /^##/) { | |
for(n = 0; n < 6 && sub(/^# */, ""); n++) | |
sub(/#$/, ""); | |
par = "h" n; | |
} | |
# Paragraph | |
/^$/ { | |
printp(par); | |
par = "p"; | |
next; | |
} | |
# Add text | |
{ text = (text ? text " " : "") $0; } | |
END { | |
if(code){ | |
oprint("</pre></code>"); | |
code = 0; | |
} | |
printp(par); | |
for(; nl > 0; nl--){ | |
if(match(block[nl], /[ou]l/)) | |
oprint("</li>"); | |
oprint("</" block[nl] ">"); | |
} | |
gsub(/<<[^\"]*/, "", otext); | |
print(otext); | |
} | |
' | |
# 1}}} | |
_echo(){ | |
printf "\r[x] %s" "$1"; tput el; | |
} | |
_ucfirst(){ | |
cat - | awk 'BEGIN { RS="\n"; FS=""; ORS=" "; OFS=""; } { $1=toupper($1); print $0 }' | |
} | |
_checkrequirements(){ | |
for req in $requirements; do | |
hash "$req" 2>&- | |
if [ $? == 1 ]; then echo "please install '$req'"; exit 1; fi | |
done; | |
} | |
# <file.md> <- converts markdownfile to bare html | |
html(){ | |
page="$1" | |
[[ ! -f "$page" ]] && echo "[x] file '$page' does not exist" && exit 1; | |
pageout="${page/.md/.html}" | |
[[ -f "$pageout" ]] && rm "$pageout" | |
/tmp/md2html "$page" > "$pageout" | |
} | |
# <file.md> <- outputs a complete styles html5 page | |
htmlcss(){ | |
page="$1" | |
[[ ! -f "$page" ]] && echo "[x] file '$page' does not exist" && exit 1; | |
pagename=$(basename "${page/.md/}"); | |
pagetitle=$(echo -n "${pagename//-/ }" | _ucfirst ) | |
pageout="${page/.md/.html}" | |
[[ -f "$pageout" ]] && rm "$pageout" | |
if grep -sqE "$regex_external" "$page"; then | |
_embedshellcmd "$page" "$page.tmp" | |
html_content=$(/tmp/md2html "$page.tmp") | |
rm "$page.tmp" | |
else | |
html_content=$(/tmp/md2html "$page") | |
fi | |
printf "$html_head" "$pagetitle" "$NAVIGATION" > "$pageout" | |
echo "$html_css$html_content$html_foot" >> "$pageout" | |
} | |
_embedshellcmd(){ | |
file_input="$1" | |
file_output="$2" | |
path=$(dirname $(readlink -f "$file_input")) | |
oldpath=$(pwd) | |
cd "$path" | |
( IFSBAK="$IFS" | |
IFS='\n' | |
cat -v "$file_input" | while read line; do | |
if echo "$line" | grep -sqE "$regex_external"; then | |
IFS=$IFSBAK | |
txtbefore=$(echo "$line" | sed 's/{!.*//g') | |
txtafter=$(echo "$line" | sed 's/.*}//g') | |
cmd=$(echo "$line" | sed 's/.*{!//g;s/}.*//g') | |
if [[ "${line:4:1}" == "{" ]]; then # prepare literal block | |
${cmd} | sed 's/^/ /g' >> "$file_output" | |
else | |
${cmd} >> "$file_output" | |
fi | |
printf "$txtafter" >> "$file_output" | |
IFS='\n' | |
else | |
echo "$line" >> "$file_output"; | |
fi | |
done ) | |
cd "$oldpath" | |
} | |
_summarize(){ | |
dir="$1" | |
selectedfile="$2" | |
options=$( | |
ls $dir/*.md | grep -v "index.md" | while read page; do | |
#date=$( stat -c %y "$page" | sed 's/ .*//g' ) | |
pagename=$(basename "${page/.md/}"); | |
pagetitle=$(echo -n "${pagename//-/ }" | _ucfirst ) | |
title=" $pagetitle"; | |
[[ "$page" == "$selectedfile" ]] && selected="selected='selected' " || selected=" " | |
printf "\t$html_navigation_option\n" "$selected" "$pagename.html" "$title" | |
done | |
) | |
if [[ -f "$dir/index.md" ]]; then | |
[[ "$dir/index.md" == "$selectedfile" ]] && selected="selected='selected' " || selected=" " | |
options="$(printf "\t$html_navigation_option\n" "$selected" "index.html" "/ Home") $options" | |
fi | |
printf "$html_navigation" "$options" | |
} | |
php2md(){ | |
inputdir="$1" | |
outputfile="$2" | |
mode="$3" | |
result="" | |
for file in $inputdir/*.php; do | |
printf "[x] processing '%s'\n" "$file" | |
content=$(cat "$file" | grep "@RESTdoc") | |
content=$(echo "$content" | sed 's|.*@RESTdoc_name |\n### |g;s|###.*$|&1 ###\n\n|g;') | |
content=$(echo "$content" | sed 's|.*@RESTdoc_param| * `parameter`:|g') | |
content=$(echo "$content" | sed 's|.*@RESTdoc_test| * `example`: |g') | |
content=$(echo "$content" | sed 's|.*@RESTdoc_desc ||g') | |
result=$(printf "%s\n%s" "$result" "$content") | |
done | |
printf "REST documentation\n" > /tmp/RESTdoc.md | |
printf "==================\n \n \n" >> /tmp/RESTdoc.md | |
echo "$result" | sed 's|`example`.*|&1\n|g' >> /tmp/RESTdoc.md | |
$mode "/tmp/RESTdoc.md" | |
mv /tmp/RESTdoc.html "$outputfile" | |
return 0 | |
} | |
_usage(){ | |
echo "$USAGE" | |
} | |
_checkrequirements | |
echo "$md2html" > /tmp/md2html && chmod 755 /tmp/md2html | |
[[ -n "$3" ]] && php2md "$1" "$2" "$3" || _usage | |
[[ -f /tmp/md2html ]] && rm /tmp/md2html | |
# vim: ts=4 nowrap fdm=marker | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment