Start new HTML export logic
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
97d3ef6cae
commit
54d07754ac
86
app/assets/export/html/css/simple-sidebar.css
Normal file
86
app/assets/export/html/css/simple-sidebar.css
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*!
|
||||||
|
* Start Bootstrap - Simple Sidebar (https://startbootstrap.com/templates/simple-sidebar)
|
||||||
|
* Copyright 2013-2020 Start Bootstrap
|
||||||
|
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-simple-sidebar/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar-wrapper {
|
||||||
|
min-height: 100vh;
|
||||||
|
margin-left: -15rem;
|
||||||
|
-webkit-transition: margin .25s ease-out;
|
||||||
|
-moz-transition: margin .25s ease-out;
|
||||||
|
-o-transition: margin .25s ease-out;
|
||||||
|
transition: margin .25s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar-wrapper .sidebar-heading {
|
||||||
|
padding: 0.875rem 1.25rem;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar-wrapper .list-group {
|
||||||
|
width: 15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-content-wrapper {
|
||||||
|
min-width: 100vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper.toggled #sidebar-wrapper {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
#sidebar-wrapper {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page-content-wrapper {
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper.toggled #sidebar-wrapper {
|
||||||
|
margin-left: -15rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-ref {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-ref {
|
||||||
|
border: 1px solid darkgray;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-ref .file {
|
||||||
|
display: flex;
|
||||||
|
border: 1px solid lightgray;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-ref .file .file-name {
|
||||||
|
margin-right: 15px;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-ref .file .dl-link {
|
||||||
|
border: 2px solid #007bff;
|
||||||
|
padding: 0 7px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
90
app/assets/export/html/index.html
Normal file
90
app/assets/export/html/index.html
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="">
|
||||||
|
|
||||||
|
<title>{{ PAGE_TITLE }} | {{ GROUP_TITLE }}</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="css/simple-sidebar.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="d-flex" id="wrapper">
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<div class="bg-light border-right" id="sidebar-wrapper">
|
||||||
|
<div class="sidebar-heading">{{ GROUP_TITLE }}</div>
|
||||||
|
<div class="list-group list-group-flush" id="sidebar-container"></div>
|
||||||
|
</div>
|
||||||
|
<!-- /#sidebar-wrapper -->
|
||||||
|
|
||||||
|
<!-- Page Content -->
|
||||||
|
<div id="page-content-wrapper">
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light border-bottom">
|
||||||
|
<button class="btn btn-primary" id="menu-toggle">Menu</button>
|
||||||
|
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav ml-auto mt-2 mt-lg-0">
|
||||||
|
<!-- <li class="nav-item active">-->
|
||||||
|
<!-- <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>-->
|
||||||
|
<!-- </li>-->
|
||||||
|
<!-- <li class="nav-item">-->
|
||||||
|
<!-- <a class="nav-link" href="#">Link</a>-->
|
||||||
|
<!-- </li>-->
|
||||||
|
<!-- <li class="nav-item dropdown">-->
|
||||||
|
<!-- <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">-->
|
||||||
|
<!-- Dropdown-->
|
||||||
|
<!-- </a>-->
|
||||||
|
<!-- <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">-->
|
||||||
|
<!-- <a class="dropdown-item" href="#">Action</a>-->
|
||||||
|
<!-- <a class="dropdown-item" href="#">Another action</a>-->
|
||||||
|
<!-- <div class="dropdown-divider"></div>-->
|
||||||
|
<!-- <a class="dropdown-item" href="#">Something else here</a>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </li>-->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container-fluid" style="margin-bottom: 50px;">
|
||||||
|
<h1 class="mt-4">{{ PAGE_TITLE }}</h1>
|
||||||
|
{{ PAGE_CONTENT }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /#page-content-wrapper -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /#wrapper -->
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript -->
|
||||||
|
<script src="vendor/jquery/jquery.min.js"></script>
|
||||||
|
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="vendor/monaco/index.js" type="module"></script>
|
||||||
|
|
||||||
|
<!-- Menu Toggle Script -->
|
||||||
|
<script>
|
||||||
|
$("#menu-toggle").click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$("#wrapper").toggleClass("toggled");
|
||||||
|
});
|
||||||
|
|
||||||
|
const manifest = {{ MANIFEST }};
|
||||||
|
|
||||||
|
manifest.sidebar.forEach(item => {
|
||||||
|
const elem = $('<a href="' + item.link + '" class="list-group-item list-group-item-action bg-light"' + (item.level ? ' style="padding-left: ' + (20 * (item.level + 1)) + 'px;"' : '') + '>' + item.title + '</a>')
|
||||||
|
$('#sidebar-container').append(elem)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
34
app/assets/export/html/manifest.json
Normal file
34
app/assets/export/html/manifest.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"sidebar": [
|
||||||
|
{
|
||||||
|
"title": "Dashboard",
|
||||||
|
"level": 0,
|
||||||
|
"link": "page-Dashboard.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Shortcuts",
|
||||||
|
"level": 1,
|
||||||
|
"link": "page-Shortcuts.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Overview",
|
||||||
|
"level": 0,
|
||||||
|
"link": "page-Overview.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Events",
|
||||||
|
"level": 1,
|
||||||
|
"link": "page-Events.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Profile",
|
||||||
|
"level": 1,
|
||||||
|
"link": "page-Profile.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Status",
|
||||||
|
"level": 2,
|
||||||
|
"link": "page-Status.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
3904
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.css
vendored
Normal file
3904
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.min.css
vendored
Normal file
7
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.min.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-grid.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
325
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.css
vendored
Normal file
325
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.css
vendored
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2020 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2020 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.15;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #212529;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
[tabindex="-1"]:focus:not(:focus-visible) {
|
||||||
|
outline: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title],
|
||||||
|
abbr[data-original-title] {
|
||||||
|
text-decoration: underline;
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted;
|
||||||
|
cursor: help;
|
||||||
|
border-bottom: 0;
|
||||||
|
-webkit-text-decoration-skip-ink: none;
|
||||||
|
text-decoration-skip-ink: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-style: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,
|
||||||
|
ul,
|
||||||
|
dl {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol,
|
||||||
|
ul ul,
|
||||||
|
ol ul,
|
||||||
|
ul ol {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
position: relative;
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #007bff;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #0056b3;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]) {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:not([href]):hover {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre,
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
overflow: auto;
|
||||||
|
-ms-overflow-style: scrollbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
vertical-align: middle;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
padding-bottom: 0.75rem;
|
||||||
|
color: #6c757d;
|
||||||
|
text-align: left;
|
||||||
|
caption-side: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus {
|
||||||
|
outline: 1px dotted;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select,
|
||||||
|
optgroup,
|
||||||
|
textarea {
|
||||||
|
margin: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[role="button"] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
word-wrap: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled),
|
||||||
|
[type="button"]:not(:disabled),
|
||||||
|
[type="reset"]:not(:disabled),
|
||||||
|
[type="submit"]:not(:disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="radio"],
|
||||||
|
input[type="checkbox"] {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
outline-offset: -2px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
font: inherit;
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
output {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.min.css
vendored
Normal file
8
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.min.css
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2020 The Bootstrap Authors
|
||||||
|
* Copyright 2011-2020 Twitter, Inc.
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||||
|
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||||
|
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||||
|
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.min.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap-reboot.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10278
app/assets/export/html/vendor/bootstrap/css/bootstrap.css
vendored
Normal file
10278
app/assets/export/html/vendor/bootstrap/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
app/assets/export/html/vendor/bootstrap/css/bootstrap.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
app/assets/export/html/vendor/bootstrap/css/bootstrap.min.css
vendored
Normal file
7
app/assets/export/html/vendor/bootstrap/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/bootstrap/css/bootstrap.min.css.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/css/bootstrap.min.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7033
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
7033
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.js.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
7
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.min.js.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.bundle.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
4420
app/assets/export/html/vendor/bootstrap/js/bootstrap.js
vendored
Normal file
4420
app/assets/export/html/vendor/bootstrap/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.js.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
app/assets/export/html/vendor/bootstrap/js/bootstrap.min.js
vendored
Normal file
7
app/assets/export/html/vendor/bootstrap/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.min.js.map
vendored
Normal file
1
app/assets/export/html/vendor/bootstrap/js/bootstrap.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10872
app/assets/export/html/vendor/jquery/jquery.js
vendored
Normal file
10872
app/assets/export/html/vendor/jquery/jquery.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
app/assets/export/html/vendor/jquery/jquery.min.js
vendored
Normal file
2
app/assets/export/html/vendor/jquery/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/jquery/jquery.min.map
vendored
Normal file
1
app/assets/export/html/vendor/jquery/jquery.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8777
app/assets/export/html/vendor/jquery/jquery.slim.js
vendored
Normal file
8777
app/assets/export/html/vendor/jquery/jquery.slim.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
app/assets/export/html/vendor/jquery/jquery.slim.min.js
vendored
Normal file
2
app/assets/export/html/vendor/jquery/jquery.slim.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
app/assets/export/html/vendor/jquery/jquery.slim.min.map
vendored
Normal file
1
app/assets/export/html/vendor/jquery/jquery.slim.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
76475
app/assets/export/html/vendor/monaco/index.js
vendored
Normal file
76475
app/assets/export/html/vendor/monaco/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
158
app/controllers/api/v1/Export.controller.js
Normal file
158
app/controllers/api/v1/Export.controller.js
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
const { Controller } = require('libflitter')
|
||||||
|
const ncp = require('ncp').ncp
|
||||||
|
const fs = require('fs').promises
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
class ExportController extends Controller {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'models', 'utility']
|
||||||
|
}
|
||||||
|
|
||||||
|
async get_export_list(req, res, next) {
|
||||||
|
const Export = this.models.get('api:Export')
|
||||||
|
const exports = await Export.find({
|
||||||
|
user_id: req.user.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.api(exports)
|
||||||
|
}
|
||||||
|
|
||||||
|
async export_subtree(req, res, next) {
|
||||||
|
const format = req.form.format
|
||||||
|
const page = req.form.page
|
||||||
|
|
||||||
|
if ( format === 'html' ) {
|
||||||
|
const generated_export = await this.export_subtree_as_html(page, req.user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async export_subtree_as_html(page, user) {
|
||||||
|
const flat_tree = []
|
||||||
|
|
||||||
|
const add_to_tree = async (page, level = 0) => {
|
||||||
|
if ( await page.is_accessible_by(user, 'view') ) {
|
||||||
|
flat_tree.push({
|
||||||
|
level,
|
||||||
|
page,
|
||||||
|
file_name: `${page.Name.replace(/\s/g, '-')}-${page.UUID}.html`,
|
||||||
|
})
|
||||||
|
|
||||||
|
const children = await page.childPages
|
||||||
|
for ( const child of children ) {
|
||||||
|
await add_to_tree(child, level + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await add_to_tree(page)
|
||||||
|
|
||||||
|
const manifest = {
|
||||||
|
sidebar: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const item of flat_tree ) {
|
||||||
|
manifest.sidebar.push({
|
||||||
|
title: item.page.Name,
|
||||||
|
level: item.level,
|
||||||
|
link: item.file_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the template over
|
||||||
|
const work_dir = await this.scratch_dir()
|
||||||
|
await this.copy_template(this.utility.path('app', 'assets', 'export', 'html'), work_dir)
|
||||||
|
|
||||||
|
const html_template = await fs.readFile(path.resolve(work_dir, 'index.html'), 'utf-8')
|
||||||
|
|
||||||
|
for ( const item of flat_tree ) {
|
||||||
|
let item_template = html_template
|
||||||
|
|
||||||
|
item_template = item_template.replace(/{{\s?MANIFEST\s?}}/g, JSON.stringify(manifest))
|
||||||
|
item_template = item_template.replace(/{{\s?GROUP_TITLE\s?}}/g, page.Name)
|
||||||
|
item_template = item_template.replace(/{{\s?PAGE_TITLE\s?}}/g, item.page.Name)
|
||||||
|
item_template = item_template.replace(/{{\s?PAGE_CONTENT\s?}}/g, await this.page_as_html(item.page, work_dir))
|
||||||
|
|
||||||
|
await fs.writeFile(path.resolve(work_dir, item.file_name), item_template)
|
||||||
|
}
|
||||||
|
|
||||||
|
return work_dir
|
||||||
|
}
|
||||||
|
|
||||||
|
async copy_template(from, to) {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
ncp(from, to, err => {
|
||||||
|
if ( err ) rej(err)
|
||||||
|
else res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async scratch_dir() {
|
||||||
|
const tmp = require('tmp')
|
||||||
|
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
tmp.dir((err, path) => {
|
||||||
|
if ( err ) rej(err)
|
||||||
|
else res(path)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async page_as_html(page, work_dir) {
|
||||||
|
const Codium = this.models.get('api:Codium')
|
||||||
|
const FileGroup = this.models.get('api:FileGroup')
|
||||||
|
const File = this.models.get('upload::File')
|
||||||
|
|
||||||
|
let html = ''
|
||||||
|
|
||||||
|
const nodes = await page.nodes
|
||||||
|
for ( const node of nodes ) {
|
||||||
|
// ATM, there are 4 node types: norm, database_ref, files_ref, and code_ref
|
||||||
|
|
||||||
|
if ( node.Value.Mode === 'norm' ) {
|
||||||
|
html += node.Value.Value
|
||||||
|
} else if ( node.Type === 'code_ref' ) {
|
||||||
|
const code = await Codium.findOne({ UUID: node.Value.Value })
|
||||||
|
if ( code ) {
|
||||||
|
const snip_file = `code-snippet-${code.UUID}.txt`
|
||||||
|
await fs.writeFile(path.resolve(work_dir, snip_file), code.code)
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="code-ref">
|
||||||
|
<wc-monaco-editor id="${code.UUID}" language="${code.Language}" src="${snip_file}"></wc-monaco-editor>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
} else if ( node.Type === 'file_ref' ) {
|
||||||
|
const file_group = await FileGroup.findOne({ UUID: node.Value.Value })
|
||||||
|
if ( file_group ) {
|
||||||
|
const file_htmls = []
|
||||||
|
|
||||||
|
for ( const file_id of file_group.FileIds ) {
|
||||||
|
const file = await File.findById(file_id)
|
||||||
|
if ( file ) {
|
||||||
|
const store_path = file.provider().filepath(file.store_id)
|
||||||
|
await this.copy_template(store_path, path.resolve(work_dir, `file-${file.upload_name}`))
|
||||||
|
|
||||||
|
file_htmls.push(`
|
||||||
|
<div class="file">
|
||||||
|
<div class="file-name">${file.original_name}</div>
|
||||||
|
<a href="file-${file.upload_name}" class="dl-link" target="_blank">▼</a>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="file-ref">
|
||||||
|
${file_htmls.join('\n')}
|
||||||
|
</div>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = ExportController
|
17
app/models/api/Export.model.js
Normal file
17
app/models/api/Export.model.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
|
||||||
|
class ExportModel extends Model {
|
||||||
|
static get schema() {
|
||||||
|
return {
|
||||||
|
user_id: String,
|
||||||
|
create_date: { type: Date, default: () => new Date },
|
||||||
|
format: String, // 'html' | 'pdf' | 'markdown' | 'json'
|
||||||
|
subtree: { type: Boolean, default: true },
|
||||||
|
file_id: String,
|
||||||
|
PageId: String,
|
||||||
|
Active: { type: Boolean, default: true },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = ExportModel
|
52
app/routing/routers/api/v1/export.routes.js
Normal file
52
app/routing/routers/api/v1/export.routes.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* API v1 Routes
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Description here
|
||||||
|
*/
|
||||||
|
const index = {
|
||||||
|
|
||||||
|
prefix: '/api/v1/exports',
|
||||||
|
|
||||||
|
middleware: [
|
||||||
|
'auth:UserOnly',
|
||||||
|
],
|
||||||
|
|
||||||
|
get: {
|
||||||
|
'/': ['controller::api:v1:Export.get_export_list'],
|
||||||
|
// '/page/:PageId/info': [
|
||||||
|
// ['middleware::api:RequiredFields', { form: 'sharing.page' }],
|
||||||
|
// ['middleware::api:PageRoute', {level: 'manage'}],
|
||||||
|
// 'controller::api:v1:Sharing.page_info',
|
||||||
|
// ],
|
||||||
|
// '/page/:PageId/link/:level': [
|
||||||
|
// ['middleware::api:RequiredFields', { form: 'sharing.page_link'}],
|
||||||
|
// ['middleware::api:PageRoute', {level: 'manage'}],
|
||||||
|
// 'controller::api:v1:Sharing.get_link',
|
||||||
|
// ],
|
||||||
|
},
|
||||||
|
|
||||||
|
post: {
|
||||||
|
'/subtree': [
|
||||||
|
['middleware::api:RequiredFields', { form: 'exports.subtree' }],
|
||||||
|
['middleware::api:PageRoute', {level: 'view'}],
|
||||||
|
'controller::api:v1:Export.export_subtree',
|
||||||
|
],
|
||||||
|
// // Share a page with the specified user.
|
||||||
|
// '/page/:PageId/share': [
|
||||||
|
// ['middleware::api:RequiredFields', { form: 'sharing.page_level' }],
|
||||||
|
// ['middleware::api:PageRoute', {level: 'manage'}],
|
||||||
|
// 'middleware::api:UserRoute',
|
||||||
|
// 'controller::api:v1:Sharing.share_page',
|
||||||
|
// ],
|
||||||
|
//
|
||||||
|
// // Unshare a page with the specified user.
|
||||||
|
// '/page/:PageId/revoke': [
|
||||||
|
// ['middleware::api:RequiredFields', { form: 'sharing.page_user' }],
|
||||||
|
// ['middleware::api:PageRoute', {level: 'manage'}],
|
||||||
|
// 'middleware::api:UserRoute',
|
||||||
|
// 'controller::api:v1:Sharing.revoke_page',
|
||||||
|
// ],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = index
|
15
config/api/forms/exports.config.js
Normal file
15
config/api/forms/exports.config.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module.exports = exports = {
|
||||||
|
subtree: {
|
||||||
|
fields: {
|
||||||
|
PageId: {
|
||||||
|
required: true,
|
||||||
|
coerce: String,
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
required: true,
|
||||||
|
coerce: String,
|
||||||
|
in_set: ['html', 'pdf', 'markdown', 'json'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,8 @@
|
|||||||
"flitter-orm": "^0.4.0",
|
"flitter-orm": "^0.4.0",
|
||||||
"flitter-upload": "^0.8.1",
|
"flitter-upload": "^0.8.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"libflitter": "^0.54.1"
|
"libflitter": "^0.54.1",
|
||||||
|
"ncp": "^2.0.0",
|
||||||
|
"tmp": "^0.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4121,6 +4121,13 @@ through@~2.3.8:
|
|||||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||||
|
|
||||||
|
tmp@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
|
||||||
|
integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
|
||||||
|
dependencies:
|
||||||
|
rimraf "^3.0.0"
|
||||||
|
|
||||||
to-fast-properties@^1.0.0, to-fast-properties@^1.0.3:
|
to-fast-properties@^1.0.0, to-fast-properties@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
|
||||||
|
Loading…
Reference in New Issue
Block a user