@@ -616,7 +616,8 @@ def get_pymodule_path(modulename, *joins): | |||
:param modulename: Python module name. | |||
:param *joins: Join additional path elements using `os.path.join`.""" | |||
joins = [scrub(part) for part in joins] | |||
if not "public" in joins: | |||
joins = [scrub(part) for part in joins] | |||
return os.path.join(os.path.dirname(get_module(scrub(modulename)).__file__), *joins) | |||
def get_module_list(app_name): | |||
@@ -350,11 +350,11 @@ def build_website(context): | |||
finally: | |||
frappe.destroy() | |||
@click.command('build-dev-docs') | |||
@click.command('make-docs') | |||
@pass_context | |||
@click.argument('app') | |||
@click.argument('docs_version') | |||
def make_dev_docs(context, app, docs_version): | |||
def make_docs(context, app, docs_version): | |||
"Setup docs in target folder of target app" | |||
from frappe.utils.setup_docs import setup_docs | |||
for site in context.sites: | |||
@@ -366,24 +366,60 @@ def make_dev_docs(context, app, docs_version): | |||
finally: | |||
frappe.destroy() | |||
@click.command('make-docs') | |||
@click.command('sync-docs') | |||
@pass_context | |||
@click.argument('app') | |||
def sync_docs(context, app): | |||
"Sync docs from /docs folder into the database (Web Page)" | |||
from frappe.utils.setup_docs import setup_docs | |||
for site in context.sites: | |||
try: | |||
frappe.init(site=site) | |||
frappe.connect() | |||
make = setup_docs(app) | |||
make.sync_docs() | |||
finally: | |||
frappe.destroy() | |||
@click.command('write-docs') | |||
@pass_context | |||
@click.argument('app') | |||
@click.argument('target') | |||
def setup_docs(context, app, target): | |||
@click.option('--local', default=False, is_flag=True, help='Run app locally') | |||
def write_docs(context, app, target, local=False): | |||
"Setup docs in target folder of target app" | |||
from frappe.utils.setup_docs import setup_docs | |||
from frappe.website import statics | |||
for site in context.sites: | |||
try: | |||
frappe.init(site=site) | |||
frappe.connect() | |||
make = setup_docs(app) | |||
make.make_docs(target) | |||
statics.sync_statics(rebuild=True) | |||
make.make_docs(target, local) | |||
finally: | |||
frappe.destroy() | |||
@click.command('build-docs') | |||
@pass_context | |||
@click.argument('app') | |||
@click.argument('docs_version') | |||
@click.argument('target') | |||
@click.option('--local', default=False, is_flag=True, help='Run app locally') | |||
def build_docs(context, app, docs_version, target, local=False): | |||
"Setup docs in target folder of target app" | |||
from frappe.utils.setup_docs import setup_docs | |||
for site in context.sites: | |||
try: | |||
frappe.init(site=site) | |||
frappe.connect() | |||
make = setup_docs(app) | |||
make.build(docs_version) | |||
make.sync_docs() | |||
make.make_docs(target, local) | |||
finally: | |||
frappe.destroy() | |||
@click.command('reset-perms') | |||
@pass_context | |||
def reset_perms(context): | |||
@@ -945,8 +981,10 @@ commands = [ | |||
destroy_all_sessions, | |||
sync_www, | |||
build_website, | |||
make_dev_docs, | |||
setup_docs, | |||
make_docs, | |||
sync_docs, | |||
write_docs, | |||
build_docs, | |||
reset_perms, | |||
execute, | |||
celery, | |||
@@ -29,7 +29,7 @@ to ERPNext. | |||
app_icon = "octicon octicon-circuit-board" | |||
app_version = "6.6.1" | |||
app_color = "orange" | |||
github_link = "https://github.com/frappe/frappe" | |||
source_link = "https://github.com/frappe/frappe" | |||
app_email = "info@frappe.io" | |||
@@ -0,0 +1,156 @@ | |||
html { | |||
min-height: 100%; | |||
} | |||
body { | |||
height: 100%; | |||
/* The html and body elements cannot have any padding or margin. */ | |||
margin: 0px; | |||
padding: 0px !important; | |||
} | |||
html, | |||
body { | |||
overflow-x: hidden; | |||
/* Prevent scroll on narrow devices */ | |||
} | |||
.offcanvas-main-section-overlay { | |||
display: none; | |||
cursor: pointer; | |||
opacity: 0.5; | |||
} | |||
.sidebar-padding { | |||
padding: 12px 14px; | |||
} | |||
.offcanvas .sidebar .sidebar-menu > li > a, | |||
.offcanvas .sidebar .dropdown-menu > li > a { | |||
padding: 12px 14px; | |||
display: block; | |||
whitespace: nowrap; | |||
transition: 0.2s; | |||
text-decoration: none !important; | |||
} | |||
.offcanvas .sidebar .dropdown-menu { | |||
padding: 0px; | |||
font-size: inherit; | |||
} | |||
.offcanvas .sidebar .dropdown-menu > li > a { | |||
padding-left: 28px; | |||
} | |||
.offcanvas .sidebar .divider { | |||
height: 1px; | |||
overflow: hidden; | |||
background-color: #ebeff2; | |||
width: 100%; | |||
margin: 0px; | |||
} | |||
.offcanvas .sidebar .badge { | |||
right: 15px !important; | |||
top: 11px !important; | |||
} | |||
.offcanvas .sidebar .sidebar-menu > li > a:hover, | |||
.offcanvas .sidebar .dropdown-menu > li > a:hover, | |||
.offcanvas .sidebar .sidebar-menu > li > a:focus, | |||
.offcanvas .sidebar .dropdown-menu > li > a:focus, | |||
.offcanvas .sidebar .sidebar-menu > li > a:active, | |||
.offcanvas .sidebar .dropdown-menu > li > a:active { | |||
background-color: #f0f4f7; | |||
} | |||
.breadcrumb { | |||
line-height: 1.5em; | |||
} | |||
.breadcrumb { | |||
background-color: transparent; | |||
padding: 10px 0px; | |||
} | |||
.breadcrumb a, | |||
.breadcrumb a:hover, | |||
.breadcrumb a:focus, | |||
.breadcrumb a:visited { | |||
color: inherit; | |||
} | |||
.navbar { | |||
background-color: transparent; | |||
border: none; | |||
padding: 10px 0px; | |||
border-radius: 0px; | |||
border-bottom: 1px solid #7575ff; | |||
} | |||
.section { | |||
padding: 30px 0px; | |||
} | |||
.docs-footer { | |||
margin-top: 50px; | |||
padding: 30px 0px 60px 0px; | |||
border-top: 1px solid #d1d8dd; | |||
} | |||
.docs-footer a { | |||
color: #8d99a6; | |||
} | |||
.docs-footer li { | |||
display: inline-block; | |||
margin: 0 15px; | |||
} | |||
.jumbotron { | |||
background-color: transparent; | |||
padding: 80px 30px; | |||
text-align: center; | |||
} | |||
.jumbotron h1 { | |||
font-size: 32px; | |||
font-weight: 400; | |||
} | |||
.jumbotron p { | |||
font-color: #8d99a6 !important; | |||
} | |||
.browser-image { | |||
min-height: 300px; | |||
border: 1px solid #d1d8dd; | |||
} | |||
.fake-browser-frame { | |||
position: relative; | |||
margin: 40px auto; | |||
max-width: 600px; | |||
} | |||
.fake-browser-frame::before { | |||
content: ""; | |||
height: 24px; | |||
position: absolute; | |||
top: -24px; | |||
left: 0px; | |||
right: 0px; | |||
border: 1px solid #d1d8dd; | |||
border-bottom: none; | |||
border-top-left-radius: 4px; | |||
border-top-right-radius: 4px; | |||
} | |||
.fake-browser-frame::after { | |||
content: '\f111 \f111 \f111'; | |||
position: absolute; | |||
color: #d1d8dd; | |||
top: -15px; | |||
left: 8px; | |||
/* octicon */ | |||
font: normal normal; | |||
font-size: 8px; | |||
font-family: 'FontAwesome'; | |||
line-height: 1; | |||
display: inline-block; | |||
text-decoration: none; | |||
-webkit-font-smoothing: antialiased; | |||
-moz-osx-font-smoothing: grayscale; | |||
-webkit-user-select: none; | |||
-moz-user-select: none; | |||
-ms-user-select: none; | |||
user-select: none; | |||
} | |||
.fake-iphone-frame { | |||
position: relative; | |||
padding: 40px 8px; | |||
border: 1px solid #d1d8dd; | |||
border-radius: 15px; | |||
} | |||
.fake-ipad-frame { | |||
position: relative; | |||
padding: 8px 40px; | |||
border: 1px solid #d1d8dd; | |||
border-radius: 15px; | |||
} |
@@ -0,0 +1,13 @@ | |||
<?xml version="1.0" standalone="no"?> | |||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |||
<svg width="100%" height="100%" viewBox="0 0 260 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"> | |||
<g> | |||
<g> | |||
<path d="M65.838,51.703L111.685,97.55" style="fill:rgb(255,120,61);fill-rule:nonzero;"/> | |||
<path d="M142.07,214.331C140.972,214.331 139.892,213.904 139.083,213.099L63.699,138.15C62.899,137.355 62.45,136.273 62.45,135.145L62.45,51.703C62.45,49.364 64.346,47.468 66.683,47.468C69.023,47.468 70.919,49.364 70.919,51.703L70.919,133.385L137.833,199.913L137.833,149.073C137.833,146.735 139.729,144.839 142.067,144.839C144.407,144.839 146.303,146.735 146.303,149.073L146.303,210.095C146.303,211.806 145.274,213.349 143.694,214.006C143.17,214.225 142.617,214.331 142.07,214.331Z" style="fill:rgb(141,153,166);fill-rule:nonzero;"/> | |||
<path d="M66.684,93.206L31.109,93.206C29.423,93.206 27.897,92.208 27.225,90.662C26.552,89.115 26.862,87.317 28.01,86.085L53.506,58.723L62.738,48.816C64.333,47.105 67.013,47.009 68.724,48.604C70.435,50.199 70.529,52.878 68.935,54.59L40.844,84.736L66.684,84.736C69.024,84.736 70.92,86.632 70.92,88.972C70.92,91.311 69.023,93.206 66.684,93.206Z" style="fill:rgb(141,153,166);fill-rule:nonzero;"/> | |||
<path d="M111.685,101.784C110.588,101.784 109.492,101.362 108.663,100.516L63.663,54.669C62.024,52.999 62.05,50.317 63.719,48.68C65.389,47.041 68.07,47.067 69.708,48.736L114.708,94.584C116.347,96.253 116.321,98.934 114.652,100.572C113.826,101.381 112.756,101.784 111.685,101.784Z" style="fill:rgb(141,153,166);fill-rule:nonzero;"/> | |||
<path d="M108.015,180.274C106.802,180.274 105.599,179.756 104.761,178.752C103.262,176.956 103.504,174.285 105.299,172.787L231.176,67.796L153.873,67.796L69.229,138.397C67.433,139.895 64.762,139.655 63.263,137.857C61.765,136.062 62.007,133.39 63.803,131.892L149.626,60.309C150.388,59.675 151.347,59.327 152.338,59.327L242.863,59.327C244.645,59.327 246.238,60.444 246.844,62.12C247.451,63.796 246.944,65.673 245.574,66.814L110.726,179.292C109.934,179.953 108.971,180.274 108.015,180.274Z" style="fill:rgb(141,153,166);fill-rule:nonzero;"/> | |||
</g> | |||
</g> | |||
</svg> |
@@ -0,0 +1,122 @@ | |||
@import "variables.less"; | |||
@import "offcanvas.less"; | |||
.breadcrumb { | |||
line-height: 1.5em; | |||
} | |||
.breadcrumb { | |||
background-color: transparent; | |||
padding: 10px 0px; | |||
} | |||
.breadcrumb a, | |||
.breadcrumb a:hover, | |||
.breadcrumb a:focus, | |||
.breadcrumb a:visited { | |||
color: inherit; | |||
} | |||
.navbar { | |||
background-color: transparent; | |||
border: none; | |||
padding: 10px 0px; | |||
border-radius: 0px; | |||
border-bottom: 1px solid @erpnext-blue; | |||
} | |||
.section { | |||
padding: 30px 0px; | |||
} | |||
.docs-footer { | |||
margin-top: 50px; | |||
padding: 30px 0px 60px 0px; | |||
border-top: 1px solid @border-color; | |||
a { | |||
color: @text-muted; | |||
} | |||
li { | |||
display: inline-block; | |||
margin: 0 15px; | |||
} | |||
} | |||
.jumbotron { | |||
background-color: transparent; | |||
padding: 80px 30px; | |||
text-align: center; | |||
h1 { | |||
font-size: 32px; | |||
font-weight: 400; | |||
} | |||
p { | |||
font-color: @text-muted !important; | |||
} | |||
} | |||
// fake frames | |||
.browser-image { | |||
min-height: 300px; | |||
border: 1px solid #d1d8dd; | |||
} | |||
.fake-browser-frame { | |||
position: relative; | |||
margin: 40px auto; | |||
max-width: 600px; | |||
} | |||
.fake-browser-frame::before { | |||
content: ""; | |||
height: 24px; | |||
position: absolute; | |||
top: -24px; | |||
left: 0px; | |||
right: 0px; | |||
border: 1px solid #d1d8dd; | |||
border-bottom: none; | |||
border-top-left-radius: 4px; | |||
border-top-right-radius: 4px; | |||
} | |||
.fake-browser-frame::after { | |||
content: '\f111 \f111 \f111'; | |||
position: absolute; | |||
color: #d1d8dd; | |||
top: -15px; | |||
left: 8px; | |||
/* octicon */ | |||
font: normal normal; | |||
font-size: 8px; | |||
font-family: 'FontAwesome'; | |||
line-height: 1; | |||
display: inline-block; | |||
text-decoration: none; | |||
-webkit-font-smoothing: antialiased; | |||
-moz-osx-font-smoothing: grayscale; | |||
-webkit-user-select: none; | |||
-moz-user-select: none; | |||
-ms-user-select: none; | |||
user-select: none; | |||
} | |||
.fake-iphone-frame { | |||
position: relative; | |||
padding: 40px 8px; | |||
border: 1px solid #d1d8dd; | |||
border-radius: 15px; | |||
} | |||
.fake-ipad-frame { | |||
position: relative; | |||
padding: 8px 40px; | |||
border: 1px solid #d1d8dd; | |||
border-radius: 15px; | |||
} |
@@ -1,4 +1,5 @@ | |||
@brand-primary: #5E64FF; | |||
@erpnext-blue: #7575ff; | |||
@border-color: #d1d8dd; | |||
@light-border-color: #EBEFF2; | |||
@text-color: #36414C; | |||
@@ -1,9 +1,9 @@ | |||
<!-- title: {{ app.title }} API --> | |||
{% from "templates/autodoc/macros.html" import github_link, version %} | |||
{% from "templates/autodoc/macros.html" import source_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, app.name, True) }} | |||
{{ source_link(app, app.name, True) }} | |||
</p> | |||
<h3>Contents</h3> | |||
@@ -6,12 +6,15 @@ | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<title>{{ title }}</title> | |||
<meta name="generator" content="frappe"> | |||
<link type="text/css" rel="stylesheet" href="/assets/css/bootstrap.css"> | |||
<link type="text/css" rel="stylesheet" href="/assets/css/hljs.css"> | |||
<link type="text/css" rel="stylesheet" href="{{ docs_base_url }}/assets/css/bootstrap.css"> | |||
<link type="text/css" rel="stylesheet" href="{{ docs_base_url }}/assets/css/hljs.css"> | |||
<link type="text/css" rel="stylesheet" href="{{ docs_base_url }}/assets/css/font-awesome.css"> | |||
<link type="text/css" rel="stylesheet" href="{{ docs_base_url }}/assets/css/octicons/octicons.css"> | |||
<link type="text/css" rel="stylesheet" href="{{ docs_base_url }}/assets/css/docs.css"> | |||
<script type="text/javascript" src="{{ github }}/assets/js/jquery.min.js"></script> | |||
<script type="text/javascript" src="{{ github }}/assets/js/bootstrap.min.js"></script> | |||
<script type="text/javascript" src="{{ github }}/assets/js/highlight.pack.js"></script> | |||
<script type="text/javascript" src="{{ docs_base_url }}/assets/js/jquery.min.js"></script> | |||
<script type="text/javascript" src="{{ docs_base_url }}/assets/js/bootstrap.min.js"></script> | |||
<script type="text/javascript" src="{{ docs_base_url }}/assets/js/highlight.pack.js"></script> | |||
{% block favicon %} | |||
<link rel="shortcut icon" | |||
@@ -63,25 +66,42 @@ | |||
{% include "templates/includes/navbar/navbar.html" %} | |||
{%- endblock -%} | |||
<div class="hero-and-content"> | |||
{%- block hero -%} | |||
<div data-html-block="hero"> | |||
{{ hero or "" }} | |||
</div> | |||
{%- endblock -%} | |||
{% block content %} | |||
<div class="container" data-html-block="content"> | |||
<div class="container"> | |||
{{ content }} | |||
</div> | |||
{% endblock %} | |||
</div> | |||
<footer class="page-footer"> | |||
<div class="container" data-html-block="footer"> | |||
<footer class="docs-footer"> | |||
<div class="container"> | |||
{%- if footer is defined -%}{{ footer }}{%- endif -%} | |||
<br> | |||
<div class="text-center"> | |||
<b>A Frappe App</b><br> | |||
<a href="https://discuss.erpnext.com" | |||
target="_blank">Discuss this on the forum</a> | |||
<ul class="list-unstyled"> | |||
<li> | |||
<a href="{{ app.source_link }}"> | |||
Source</a> | |||
</li> | |||
<li> | |||
<a href="{{ app.source_link }}/issues"> | |||
Issues</a> | |||
</li> | |||
<li> | |||
<a href="{{ docs_base_url }}/license.html"> | |||
License</a> | |||
</li> | |||
<li> | |||
<a href="https://discuss.erpnext.com"> | |||
Forum</a> | |||
</li> | |||
<li> | |||
<a href="https://apps.frappe.io"> | |||
Frappe Apps</a> | |||
</li> | |||
</ul> | |||
</div> | |||
<div class="built-with-frappe text-center"> | |||
<img src="{{ docs_base_url }}/assets/img/frappe-bird-grey.svg" style="width: 40px; height: 40px; margin-top: 20px;"> | |||
</div> | |||
</div> | |||
</footer> | |||
@@ -0,0 +1,47 @@ | |||
<!-- title: {{ app.title }} Developer Docs --> | |||
<!-- no-breadcrumbs --> | |||
{% from "templates/autodoc/macros.html" import source_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ source_link(app, app.name, True) }} | |||
</p> | |||
<table class="table table-bordered" style="max-width: 500px;"> | |||
<tr> | |||
<td style="width: 40%"> | |||
App Name | |||
</td> | |||
<td> | |||
<code>{{ app.name }}</code> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
Publisher | |||
</td> | |||
<td> | |||
<code>{{ app.publisher }}</code> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
Version | |||
</td> | |||
<td> | |||
<code>{{ app.version }}</code> | |||
</td> | |||
</tr> | |||
</table> | |||
<h3>Contents</h3> | |||
<ul> | |||
<li> | |||
<a href="models">Models (DocTypes)</a> | |||
</li> | |||
<li> | |||
<a href="api">Server-side API</a> | |||
</li> | |||
</ul> | |||
<!-- jinja --><!-- static --> |
@@ -1,53 +1,20 @@ | |||
<!-- title: {{ app.title }} Documentation --> | |||
<!-- no-breadcrumbs --> | |||
{% from "templates/autodoc/macros.html" import github_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, app.name, True) }} | |||
</p> | |||
<div class="jumbotron"> | |||
<h1>{{ app.headline }}</h1> | |||
<p>{{ app.description }}</p> | |||
</div> | |||
<table class="table table-bordered" style="max-width: 500px;"> | |||
<tr> | |||
<td style="width: 40%"> | |||
App Name | |||
</td> | |||
<td> | |||
<code>{{ app.name }}</code> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
Publisher | |||
</td> | |||
<td> | |||
<code>{{ app.publisher }}</code> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td> | |||
Version | |||
</td> | |||
<td> | |||
<code>{{ app.version }}</code> | |||
</td> | |||
</tr> | |||
</table> | |||
<hr> | |||
{{ app.description }} | |||
<hr> | |||
<div class="section" style="padding-top: 0px;"> | |||
<div class="fake-browser-frame"> | |||
<img class="img-responsive browser-image feature-image" | |||
src="img/desktop.png"> | |||
</div> | |||
</div> | |||
<h3>Contents</h3> | |||
<ul> | |||
<li> | |||
<a href="models">Models (DocTypes)</a> | |||
</li> | |||
<li> | |||
<a href="api">Server-side API</a> | |||
</li> | |||
</ul> | |||
<!-- jinja --><!-- static --> | |||
{index} | |||
<!-- jinja --> |
@@ -1,13 +1,13 @@ | |||
<!-- title: {{ doctype }} --> | |||
{% from "templates/autodoc/macros.html" import automodule, version, | |||
github_link, doctype_link %} | |||
source_link, doctype_link %} | |||
{% set doc = frappe.get_doc("DocType", doctype) %} | |||
{% set controller = autodoc.get_controller(doctype) %} | |||
<p> | |||
{{ version(doctype) }} | |||
{{ github_link(app, app.name + "/" + scrub(doc.module) | |||
{{ source_link(app, app.name + "/" + scrub(doc.module) | |||
+ "/doctype/" + scrub(doctype), True) }} | |||
</p> | |||
@@ -0,0 +1,5 @@ | |||
<!-- title: {{ app.title }} License {{ app.license }} --> | |||
<h1>{{ app.license}}</h1> | |||
{{ license_text }} |
@@ -50,15 +50,15 @@ | |||
Version {{ autodoc.get_version(name) }}</a> | |||
{% endmacro %} | |||
{% macro github_link(app, file_path, tree=False) %} | |||
<a class="btn btn-default btn-sm" href="{{ app.github_link }}/{{ "tree" if tree else "blob" }}/v{{ app.version }}/{{ file_path }}" | |||
{% macro source_link(app, file_path, tree=False) %} | |||
<a class="btn btn-default btn-sm" href="{{ app.source_link }}/{{ "tree" if tree else "blob" }}/v{{ app.version }}/{{ file_path }}" | |||
target="_blank" style="margin-left: 10px; margin-bottom: 10px;"><i class="octicon octicon-mark-github"></i> Source</a> | |||
{% endmacro %} | |||
{% macro doctype_link(app, doctype) %} | |||
{% set module = frappe.db.get_value("DocType", doctype, "module") %} | |||
{% if doctype and module %} | |||
<a href="{{ app.github }}/{{ app.docs_version }}/models/{{ | |||
<a href="{{ app.docs_base_url }}/{{ app.docs_version }}/models/{{ | |||
scrub(module) }}/{{ scrub(doctype) }}">{{ doctype }}</a> | |||
{% endif %} | |||
{% endmacro %} |
@@ -1,9 +1,9 @@ | |||
<!-- title: {{ app.title }} Models (DocTypes) --> | |||
{% from "templates/autodoc/macros.html" import github_link, version %} | |||
{% from "templates/autodoc/macros.html" import source_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, app.name, True) }} | |||
{{ source_link(app, app.name, True) }} | |||
</p> | |||
<p>Browse DocTypes by Module</p> | |||
@@ -1,9 +1,9 @@ | |||
<!-- title: Module {{ name }} --> | |||
{% from "templates/autodoc/macros.html" import github_link, version %} | |||
{% from "templates/autodoc/macros.html" import source_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, app.name + "/" + scrub(name), True) }} | |||
{{ source_link(app, app.name + "/" + scrub(name), True) }} | |||
</p> | |||
<h3>DocTypes for {{ name }}</h3> | |||
@@ -1,9 +1,9 @@ | |||
<!-- title: {{ title }} --> | |||
{% from "templates/autodoc/macros.html" import github_link, version %} | |||
{% from "templates/autodoc/macros.html" import source_link, version %} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, title, True) }} | |||
{{ source_link(app, title, True) }} | |||
</p> | |||
<h3>Package Contents</h3> | |||
@@ -1,10 +1,10 @@ | |||
<!-- title: {{ name }} --> | |||
{%- from "templates/autodoc/macros.html" import automodule, github_link, | |||
{%- from "templates/autodoc/macros.html" import automodule, source_link, | |||
version -%} | |||
<p> | |||
{{ version(app.name) }} | |||
{{ github_link(app, name.replace(".", "/") + ".py") }} | |||
{{ source_link(app, name.replace(".", "/") + ".py") }} | |||
</p> | |||
{{ automodule(name) }} |
@@ -9,6 +9,7 @@ Call from command line: | |||
import os, json, frappe, markdown2, shutil | |||
import frappe.website.statics | |||
from frappe.website.context import get_context | |||
from markdown2 import markdown | |||
class setup_docs(object): | |||
def __init__(self, app): | |||
@@ -18,10 +19,28 @@ class setup_docs(object): | |||
self.app = app | |||
self.hooks = frappe.get_hooks(app_name = self.app) | |||
self.app_title = self.hooks.get("app_title")[0] | |||
self.setup_app_context() | |||
def setup_app_context(self): | |||
self.app_context = { | |||
"app": { | |||
"name": self.app, | |||
"title": self.app_title, | |||
"description": markdown2.markdown(self.hooks.get("app_description")[0]), | |||
"version": self.hooks.get("app_version")[0], | |||
"headline": self.hooks.get("app_headline")[0], | |||
"publisher": self.hooks.get("app_publisher")[0], | |||
"source_link": self.hooks.get("source_link")[0], | |||
"docs_base_url": self.hooks.get("docs_base_url")[0], | |||
"license": self.hooks.get("app_license")[0] | |||
} | |||
} | |||
def build(self, docs_version): | |||
"""Build templates for docs models and Python API""" | |||
self.path = frappe.get_app_path(self.app, "docs", docs_version) | |||
self.docs_path = frappe.get_app_path(self.app, "docs") | |||
self.path = os.path.join(self.docs_path, docs_version) | |||
self.app_context["app"]["docs_version"] = docs_version | |||
self.app_title = self.hooks.get("app_title")[0] | |||
self.app_path = frappe.get_app_path(self.app) | |||
@@ -30,22 +49,14 @@ class setup_docs(object): | |||
shutil.rmtree(self.path, ignore_errors = True) | |||
os.makedirs(self.path) | |||
self.app_context = { | |||
"app": { | |||
"name": self.app, | |||
"title": self.app_title, | |||
"description": markdown2.markdown(self.hooks.get("app_description")[0]), | |||
"version": self.hooks.get("app_version")[0], | |||
"publisher": self.hooks.get("app_publisher")[0], | |||
"github_link": self.hooks.get("github_link")[0], | |||
"github": self.hooks.get("github_pages_url")[0], | |||
"docs_version": docs_version | |||
} | |||
} | |||
# make dev home page | |||
with open(os.path.join(self.docs_path, "index.html"), "w") as home: | |||
home.write(frappe.render_template("templates/autodoc/docs_home.html", | |||
self.app_context)) | |||
# make home page | |||
# make dev home page | |||
with open(os.path.join(self.path, "index.html"), "w") as home: | |||
home.write(frappe.render_template("templates/autodoc/docs_home.html", | |||
home.write(frappe.render_template("templates/autodoc/dev_home.html", | |||
self.app_context)) | |||
# make folders | |||
@@ -80,13 +91,34 @@ class setup_docs(object): | |||
elif self.is_py_module(basepath, folders, files): | |||
self.write_modules(basepath, folders, files) | |||
def make_docs(self, target): | |||
self.target = target | |||
self.build_user_docs() | |||
def build_user_docs(self): | |||
"""Build templates for user docs pages, if missing.""" | |||
user_docs_path = os.path.join(self.docs_path, "user") | |||
with open(os.path.join(self.app_path, "..", "license.txt"), "r") as license_file: | |||
self.app_context["license_text"] = markdown(license_file.read()) | |||
html = frappe.render_template("templates/autodoc/license.html", | |||
context = self.app_context) | |||
with open(os.path.join(self.docs_path, "license.html"), "w") as license_file: | |||
license_file.write(html) | |||
self.update_index_txt(self.docs_path) | |||
def sync_docs(self): | |||
"""Sync docs from /docs folder to **Web Page**. | |||
print "Loadings docs..." | |||
Called as `bench --site [sitename] sync-docs [appname]` | |||
""" | |||
sync = frappe.website.statics.sync() | |||
sync.start(path="docs", rebuild=True) | |||
def make_docs(self, target, local = False): | |||
self.target = target | |||
self.local = local | |||
# write in target path | |||
self.write_files() | |||
@@ -187,7 +219,10 @@ class setup_docs(object): | |||
def write_files(self): | |||
"""render templates and write files to target folder""" | |||
frappe.local.flags.home_page = "index" | |||
github_pages_url = self.hooks.get("github_pages_url")[0] | |||
if self.local: | |||
docs_base_url = "" | |||
else: | |||
docs_base_url = self.hooks.get("docs_base_url")[0] | |||
for page in frappe.db.sql("""select parent_website_route, | |||
page_name from `tabWeb Page`""", as_dict=True): | |||
@@ -204,33 +239,35 @@ class setup_docs(object): | |||
"relative_links": True | |||
}) | |||
target_filename = os.path.join(self.target, context.template_path.split('/docs/', 1)[1]) | |||
print "Writing {0}".format(target_filename) | |||
context.update(self.app_context) | |||
context.update({ | |||
"brand_html": self.app_title, | |||
"top_bar_items": [ | |||
{"label": "User", "url":"/", "right": 1}, | |||
{"label": "Developer", "url":"/current", "right": 1}, | |||
{"label": "About", "url":"/user/about", "right": 1} | |||
{"label": "User", "url": docs_base_url + "/", "right": 1}, | |||
{"label": "Developer", "url": docs_base_url + "/current", "right": 1}, | |||
{"label": "About", "url": docs_base_url + "/user/about", "right": 1} | |||
], | |||
"favicon": "/assets/img/favicon.ico", | |||
"only_static": True, | |||
"github_pages_url": github_pages_url, | |||
"docs_base_url": docs_base_url, | |||
}) | |||
html = frappe.get_template("templates/autodoc/base_template.html").render(context) | |||
target_filename = os.path.join(self.target, context.template_path.split('/docs/', 1)[1]) | |||
if not os.path.exists(os.path.dirname(target_filename)): | |||
os.makedirs(os.path.dirname(target_filename)) | |||
with open(target_filename, "w") as htmlfile: | |||
htmlfile.write(html.encode("utf-8")) | |||
print "wrote {0}".format(target_filename) | |||
def copy_assets(self): | |||
"""Copy jquery, bootstrap and other assets to files""" | |||
print "Copying assets..." | |||
assets_path = os.path.join(self.target, "assets") | |||
# copy assets from docs | |||
@@ -249,10 +286,19 @@ class setup_docs(object): | |||
"js/lib/bootstrap.min.js": "js/bootstrap.min.js", | |||
"js/lib/highlight.pack.js": "js/highlight.pack.js", | |||
"css/bootstrap.css": "css/bootstrap.css", | |||
"css/hljs.css": "css/hljs.css" | |||
"css/font-awesome.css": "css/font-awesome.css", | |||
"css/docs.css": "css/docs.css", | |||
"css/hljs.css": "css/hljs.css", | |||
"css/font": "css/font", | |||
"css/octicons": "css/octicons", | |||
"images/frappe-bird-grey.svg": "img/frappe-bird-grey.svg" | |||
} | |||
for source, target in copy_files.iteritems(): | |||
shutil.copy(frappe.get_app_path("frappe", "public", source), | |||
os.path.join(assets_path, target)) | |||
source_path = frappe.get_app_path("frappe", "public", source) | |||
if os.path.isdir(source_path): | |||
if not os.path.exists(os.path.join(assets_path, target)): | |||
shutil.copytree(source_path, os.path.join(assets_path, target)) | |||
else: | |||
shutil.copy(source_path, os.path.join(assets_path, target)) | |||
@@ -26,7 +26,8 @@ def get_context(path, args=None): | |||
if not context: | |||
context = get_route_info(path) | |||
context.update(args) | |||
if args: | |||
context.update(args) | |||
context = build_context(context) | |||
add_data_path(context) | |||
@@ -211,13 +211,20 @@ class WebsiteGenerator(Document): | |||
def get_children_of(self, route): | |||
"""Return list of children of given route, for generating index in Web Page""" | |||
condition = 'parent_website_route = %s' | |||
if route=="index" or not route: | |||
condition = 'ifnull(parent_website_route, "") = %s and name != "index"' | |||
route = "" | |||
children = frappe.db.sql("""select name, page_name, | |||
parent_website_route, {title_field} as title from `tab{doctype}` | |||
where parent_website_route = %s | |||
where {condition} | |||
order by {order_by}""".format( | |||
doctype = self.doctype, | |||
title_field = self.website.page_title_field or "name", | |||
order_by = self.website.order_by or "idx asc" | |||
order_by = self.website.order_by or "idx asc", | |||
condition = condition | |||
), route, as_dict=True) | |||
for c in children: | |||