amos-ionic-logging
Version:
Components for Ionic logging
1,017 lines (865 loc) • 37.3 kB
HTML
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>ionic-logging-service</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="../images/favicon.ico">
<link rel="stylesheet" href="../styles/style.css">
</head>
<body>
<div class="navbar navbar-default navbar-fixed-top visible-xs">
<a href="../" class="navbar-brand">ionic-logging-service</a>
<button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button>
</div>
<div class="xs-menu menu" id="mobile-menu">
<div id="book-search-input" role="search"><input type="text" placeholder="Type to search"></div> <compodoc-menu></compodoc-menu>
</div>
<div class="container-fluid main">
<div class="row main">
<div class="hidden-xs menu">
<compodoc-menu mode="normal"></compodoc-menu>
</div>
<!-- START CONTENT -->
<div class="content injectable">
<div class="content-data">
<ol class="breadcrumb">
<li>Injectables</li>
<li>LoggingService</li>
</ol>
<ul class="nav nav-tabs" role="tablist">
<li class="active">
<a href="#info" role="tab" id="info-tab" data-toggle="tab" data-link="info">Info</a>
</li>
<li >
<a href="#source" role="tab" id="source-tab" data-toggle="tab" data-link="source">Source</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade active in" id="c-info">
<p class="comment">
<h3>File</h3>
</p>
<p class="comment">
<code>src/lib/logging.service.ts</code>
</p>
<p class="comment">
<h3>Description</h3>
</p>
<p class="comment">
<p>Service for logging functionality.</p>
<p>By default, the following settings are used:</p>
<ul>
<li>logger: root with level WARN</li>
<li>appender: BrowserConsoleAppender with threshold DEBUG and MemoryAppender with threshold ALL</li>
</ul>
<p>Via <a href="#configure">configure</a>, it is possible to amend these settings.</p>
</p>
<section>
<h3 id="index">Index</h3>
<table class="table table-sm table-bordered index-table">
<tbody>
<tr>
<td class="col-md-4">
<h6><b>Properties</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<span class="modifier">Public</span>
<a href="#ajaxAppenderFailed">ajaxAppenderFailed</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#logMessagesChanged">logMessagesChanged</a>
</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<h6><b>Methods</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<span class="modifier">Public</span>
<a href="#configure">configure</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getLogger">getLogger</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getLogMessages">getLogMessages</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getLogMessagesFromLocalStorage">getLogMessagesFromLocalStorage</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getRootLogger">getRootLogger</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#removeLogMessages">removeLogMessages</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#removeLogMessagesFromLocalStorage">removeLogMessagesFromLocalStorage</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 id="constructor">Constructor</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<code>constructor()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="44" class="link-to-prism">src/lib/logging.service.ts:44</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Creates a new instance of the service.</p>
</div>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 id="methods">
Methods
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="configure"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
configure
</b>
<a href="#configure"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>configure(configuration?: <a href="../injectables/LoggingService.html">LoggingServiceConfiguration</a>)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="83"
class="link-to-prism">src/lib/logging.service.ts:83</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Configures the logging depending on the given configuration.</p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>configuration</td>
<td>
<code><a href="../injectables/LoggingService.html" target="_self" >LoggingServiceConfiguration</a></code>
</td>
<td>
Yes
</td>
<td>
<p>configuration data.</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" target="_blank" >void</a></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getLogger"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
getLogger
</b>
<a href="#getLogger"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getLogger(loggerName: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank">string</a>)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="158"
class="link-to-prism">src/lib/logging.service.ts:158</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Gets a logger with the specified name, creating it if a logger with that name does not already exist.</p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>loggerName</td>
<td>
<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank" >string</a></code>
</td>
<td>
No
</td>
<td>
<p>name of the logger</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../classes/Logger.html" target="_self" >Logger</a></code>
</div>
<div class="io-description">
<p>logger</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getLogMessages"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
getLogMessages
</b>
<a href="#getLogMessages"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getLogMessages()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="170"
class="link-to-prism">src/lib/logging.service.ts:170</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Gets the last log messages.</p>
<p>The log messages are retrieved from the internal <a href="../memoryappender.html">MemoryAppender</a>.
That means you will get only the most current messages. The number of the messages is limited
by its maxMessages value.</p>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../interfaces/LogMessage.html" target="_self" >LogMessage[]</a></code>
</div>
<div class="io-description">
<p>log messages</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getLogMessagesFromLocalStorage"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
getLogMessagesFromLocalStorage
</b>
<a href="#getLogMessagesFromLocalStorage"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getLogMessagesFromLocalStorage(localStorageKey: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank">string</a>)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="179"
class="link-to-prism">src/lib/logging.service.ts:179</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Loads the log messages written by the LocalStorageAppender with the given key.</p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>localStorageKey</td>
<td>
<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank" >string</a></code>
</td>
<td>
No
</td>
<td>
<p>key for the local storage</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../interfaces/LogMessage.html" target="_self" >LogMessage[]</a></code>
</div>
<div class="io-description">
<p>log messages</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getRootLogger"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
getRootLogger
</b>
<a href="#getRootLogger"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getRootLogger()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="149"
class="link-to-prism">src/lib/logging.service.ts:149</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Gets the root logger from which all other loggers derive.</p>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../classes/Logger.html" target="_self" >Logger</a></code>
</div>
<div class="io-description">
<p>root logger</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="removeLogMessages"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
removeLogMessages
</b>
<a href="#removeLogMessages"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>removeLogMessages()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="186"
class="link-to-prism">src/lib/logging.service.ts:186</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Remove all log messages.</p>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" target="_blank" >void</a></code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="removeLogMessagesFromLocalStorage"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
removeLogMessagesFromLocalStorage
</b>
<a href="#removeLogMessagesFromLocalStorage"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>removeLogMessagesFromLocalStorage(localStorageKey: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank">string</a>)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="195"
class="link-to-prism">src/lib/logging.service.ts:195</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Removes the log messages written by the LocalStorageAppender with the given key.</p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>localStorageKey</td>
<td>
<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string" target="_blank" >string</a></code>
</td>
<td>
No
</td>
<td>
<p>key for the local storage</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" target="_blank" >void</a></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 id="inputs">
Properties
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="ajaxAppenderFailed"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
ajaxAppenderFailed</b>
<a href="#ajaxAppenderFailed"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Type : </i> <code>EventEmitter<string></code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="40" class="link-to-prism">src/lib/logging.service.ts:40</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Event triggered when ajax appender could not send log messages to the server.</p>
</div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>message</td>
<td>
<code><p>error message</p>
</code>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="logMessagesChanged"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
logMessagesChanged</b>
<a href="#logMessagesChanged"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Type : </i> <code>EventEmitter<void></code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="34" class="link-to-prism">src/lib/logging.service.ts:34</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Event triggered when the log messages got (potentially) change.
This can happen when:</p>
<ul>
<li>new message was added</li>
<li>all message where removed from memory</li>
<li>all massages where removed for one spcific LocalStorageAppender</li>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</section>
</div>
<div class="tab-pane fade tab-source-code" id="c-source">
<pre class="line-numbers compodoc-sourcecode"><code class="language-typescript">import { EventEmitter, Injectable, Optional } from "@angular/core";
import * as log4javascript from "log4javascript";
import { AjaxAppender } from "./ajax-appender.model";
import { LocalStorageAppender } from "./local-storage-appender.model";
import { LogLevelConverter } from "./log-level.converter";
import { LogMessage } from "./log-message.model";
import { Logger } from "./logger.model";
import { LoggingServiceConfiguration } from "./logging-service.configuration";
import { MemoryAppender } from "./memory-appender.model";
/**
* Service for logging functionality.
*
* By default, the following settings are used:
* - logger: root with level WARN
* - appender: BrowserConsoleAppender with threshold DEBUG and MemoryAppender with threshold ALL
*
* Via [configure](#configure), it is possible to amend these settings.
*/
@Injectable({
providedIn: "root"
})
export class LoggingService {
/**
* Event triggered when the log messages got (potentially) change.
* This can happen when:
* - new message was added
* - all message where removed from memory
* - all massages where removed for one spcific LocalStorageAppender
*/
public logMessagesChanged: EventEmitter<void>;
/**
* Event triggered when ajax appender could not send log messages to the server.
* @param message error message
*/
public ajaxAppenderFailed: EventEmitter<string>;
// tslint:disable-next-line:completed-docs
private memoryAppender: MemoryAppender;
private browserConsoleAppender: log4javascript.BrowserConsoleAppender;
/**
* Creates a new instance of the service.
*/
constructor() {
// prevent log4javascript to show alerts on case of errors
log4javascript.logLog.setQuietMode(true);
// create event emitter
this.logMessagesChanged = new EventEmitter<void>();
this.ajaxAppenderFailed = new EventEmitter<string>();
// configure appender
const logger = log4javascript.getRootLogger();
logger.setLevel(log4javascript.Level.WARN);
// browser console appender for debugger
this.browserConsoleAppender = new log4javascript.BrowserConsoleAppender();
this.browserConsoleAppender.setLayout(new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %c %m"));
this.browserConsoleAppender.setThreshold(log4javascript.Level.ALL);
logger.addAppender(this.browserConsoleAppender);
// in-memory appender for display on log messages page
this.memoryAppender = new MemoryAppender();
this.memoryAppender.setLayout(new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %c %m"));
this.memoryAppender.setOnLogMessagesChangedCallback((message) => {
this.logMessagesChanged.emit();
});
logger.addAppender(this.memoryAppender);
this.configure();
}
/**
* Configures the logging depending on the given configuration.
* @param configuration configuration data.
*/
public configure(configuration?: LoggingServiceConfiguration): void {
if (typeof configuration === "undefined") {
configuration = {};
}
// set log levels
if (typeof configuration.logLevels !== "undefined") {
for (const level of configuration.logLevels) {
let logger: log4javascript.Logger;
if (level.loggerName === "root") {
logger = log4javascript.getRootLogger();
} else {
logger = log4javascript.getLogger(level.loggerName);
}
try {
logger.setLevel(LogLevelConverter.levelToLog4Javascript(LogLevelConverter.levelFromString(level.logLevel)));
} catch (e) {
throw new Error(`invalid log level ${level.logLevel}`);
}
}
}
// configure AjaxAppender
if (typeof configuration.ajaxAppender !== "undefined") {
const ajaxAppender = new AjaxAppender(configuration.ajaxAppender);
ajaxAppender.appenderFailed.subscribe((message: string) => {
this.ajaxAppenderFailed.emit(message);
});
log4javascript.getRootLogger().addAppender(ajaxAppender);
}
// configure LocalStorageAppender
if (typeof configuration.localStorageAppender !== "undefined") {
const localStorageAppender = new LocalStorageAppender(configuration.localStorageAppender);
log4javascript.getRootLogger().addAppender(localStorageAppender);
// ensure that an eventual memoryAppender is behind the localStorageAppender
const appenders = new Logger().getInternalLogger().getEffectiveAppenders();
const memoryAppender = appenders.find((a) => a.toString() === "Ionic.Logging.MemoryAppender") as MemoryAppender;
if (memoryAppender) {
log4javascript.getRootLogger().removeAppender(memoryAppender);
log4javascript.getRootLogger().addAppender(memoryAppender);
}
}
// configure MemoryAppender
if (configuration.memoryAppender) {
this.memoryAppender.configure(configuration.memoryAppender);
}
// configure BrowserConsoleAppender
if (configuration.browserConsoleAppender) {
if (configuration.browserConsoleAppender.threshold) {
const convertedThreshold = LogLevelConverter.levelToLog4Javascript(
LogLevelConverter.levelFromString(configuration.browserConsoleAppender.threshold));
this.browserConsoleAppender.setThreshold(convertedThreshold);
}
}
}
/**
* Gets the root logger from which all other loggers derive.
* @return root logger
*/
public getRootLogger(): Logger {
return new Logger();
}
/**
* Gets a logger with the specified name, creating it if a logger with that name does not already exist.
* @param loggerName name of the logger
* @return logger
*/
public getLogger(loggerName: string): Logger {
return new Logger(loggerName);
}
/**
* Gets the last log messages.
*
* The log messages are retrieved from the internal [MemoryAppender](../memoryappender.html).
* That means you will get only the most current messages. The number of the messages is limited
* by its maxMessages value.
* @return log messages
*/
public getLogMessages(): LogMessage[] {
return this.memoryAppender.getLogMessages();
}
/**
* Loads the log messages written by the LocalStorageAppender with the given key.
* @param localStorageKey key for the local storage
* @returns log messages
*/
public getLogMessagesFromLocalStorage(localStorageKey: string): LogMessage[] {
return LocalStorageAppender.loadLogMessages(localStorageKey);
}
/**
* Remove all log messages.
*/
public removeLogMessages(): void {
this.memoryAppender.removeLogMessages();
this.logMessagesChanged.emit();
}
/**
* Removes the log messages written by the LocalStorageAppender with the given key.
* @param localStorageKey key for the local storage
*/
public removeLogMessagesFromLocalStorage(localStorageKey: string): void {
LocalStorageAppender.removeLogMessages(localStorageKey);
this.logMessagesChanged.emit();
}
}
</code></pre>
</div>
</div>
</div><div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> result-matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
<!-- END CONTENT -->
</div>
</div>
<script>
var COMPODOC_CURRENT_PAGE_DEPTH = 1;
var COMPODOC_CURRENT_PAGE_CONTEXT = 'injectable';
var COMPODOC_CURRENT_PAGE_URL = 'LoggingService.html';
var MAX_SEARCH_RESULTS = 15;
</script>
<script src="../js/libs/custom-elements.min.js"></script>
<script src="../js/libs/lit-html.js"></script>
<!-- Required to polyfill modern browsers as code is ES5 for IE... -->
<script src="../js/libs/custom-elements-es5-adapter.js" charset="utf-8" defer></script>
<script src="../js/menu-wc.js" defer></script>
<script src="../js/libs/bootstrap-native.js"></script>
<script src="../js/libs/es6-shim.min.js"></script>
<script src="../js/libs/EventDispatcher.js"></script>
<script src="../js/libs/promise.min.js"></script>
<script src="../js/libs/zepto.min.js"></script>
<script src="../js/compodoc.js"></script>
<script src="../js/tabs.js"></script>
<script src="../js/menu.js"></script>
<script src="../js/libs/clipboard.min.js"></script>
<script src="../js/libs/prism.js"></script>
<script src="../js/sourceCode.js"></script>
<script src="../js/search/search.js"></script>
<script src="../js/search/lunr.min.js"></script>
<script src="../js/search/search-lunr.js"></script>
<script src="../js/search/search_index.js"></script>
<script src="../js/lazy-load-graphs.js"></script>
</body>
</html>