742 lines
22 KiB
HTML
Executable file
742 lines
22 KiB
HTML
Executable file
<!doctype html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
|
|
<title>Drupal VM, Meet Symfony Console</title>
|
|
|
|
<meta name="description" content="Drupal VM, Meet Symfony Console">
|
|
<meta name="author" content="Oliver Davies">
|
|
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
|
|
<link rel="stylesheet" href="css/reveal.css">
|
|
<link rel="stylesheet" href="css/theme/simple.css" id="theme">
|
|
<link rel="stylesheet" href="lib/css/tomorrow-night-bright.css">
|
|
<link rel="stylesheet" href="assets/css/custom.css">
|
|
|
|
<!-- Printing and PDF exports -->
|
|
<script>
|
|
var link = document.createElement( 'link' );
|
|
link.rel = 'stylesheet';
|
|
link.type = 'text/css';
|
|
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
|
|
document.getElementsByTagName( 'head' )[0].appendChild( link );
|
|
</script>
|
|
|
|
<!--[if lt IE 9]>
|
|
<script src="lib/js/html5shiv.js"></script>
|
|
<![endif]-->
|
|
</head>
|
|
|
|
<body>
|
|
<div class="reveal">
|
|
<div class="slides">
|
|
|
|
<section>
|
|
<h1 class="big">Drupal VM, Meet Symfony Console</h1>
|
|
|
|
<p>
|
|
<img class="no-border" src="assets/images/drupalcamp-bristol.png" >
|
|
</p>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Oliver Davies (opdavies)</h2>
|
|
|
|
<div class="col--6-5">
|
|
<ul class="bullets medium">
|
|
<li>Senior Drupal Developer for Appnovation</li>
|
|
<li>Symfony hobbyist</li>
|
|
<li>Drupal VM user, Drupal VM Generator maintainer</li>
|
|
<li>Drupal Bristol organiser, PHPSW co-organiser, DrupalCamp committee member</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="col--6-1">
|
|
<img src="assets/images/me_thumb.jpg" class="no-border">
|
|
<img src="assets/images/appno.jpg" class="no-border">
|
|
<!-- <img src="assets/images/drupal-bristol.jpg" class="no-border"> -->
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Prerequisites</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Object-orientated PHP</li>
|
|
<li>Composer</li>
|
|
<li>Autoloading, PSR-4</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>About Drupal VM</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Virtual machine for Drupal development</li>
|
|
<li>Developed and maintained by Jeff Geerling</li>
|
|
<li>Vagrant, Ansible</li>
|
|
<li>Configured via YAML files</li>
|
|
<li>Customisable</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Using Drupal VM (< 3.0)</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Download the project</li>
|
|
<li>Copy example.config.yml to config.yml</li>
|
|
<li>Edit values</li>
|
|
<li>Start the VM</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Using Drupal VM (>= 3.0)</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Download the project</li>
|
|
<li>default.config.yml contains default values</li>
|
|
<li>Make config.yml if needed and override values</li>
|
|
<li>Start the VM</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>About the Drupal VM Generator</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Symfony application</li>
|
|
<li>Twig</li>
|
|
<li>Generates minimal, use-case specific configuration files</li>
|
|
<li>http://bit.ly/announcing-drupal-vm-generator</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Using Drupal VM (>= 3.0)</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Download the project</li>
|
|
<li>default.config.yml contains default values</li>
|
|
<li><strong>Make config.yml if needed and override values</strong></li>
|
|
<li>Start the VM</li>
|
|
</ul>
|
|
|
|
<aside class="notes">
|
|
<ul class="bullets">
|
|
<li>Time consuming - 297 lines</li>
|
|
<li>Too much cruft</li>
|
|
</ul>
|
|
</aside>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Drupal VM Generator Example 1</h2>
|
|
<img src="assets/images/drupal-vm-generator-example.gif" alt="">
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Drupal VM Generator Example 2</h2>
|
|
<pre><code class="php text-medium">
|
|
drupalvm config:generate \
|
|
--machine-name="drupalbristol" \
|
|
--hostname="drupalbristol.l" \
|
|
--ip-address="192.168.88.88" \
|
|
--cpus="1" --memory="512" \
|
|
--webserver="nginx" --drupal-version="8" \
|
|
--database-name="drupal" --database-user="drupal" \
|
|
--database-password="drupal" --build-makefile=false \
|
|
...
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>CLI Examples</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Drush</li>
|
|
<li>Symfony/Drupal Console</li>
|
|
<li>Terminus (Pantheon)/Platform.sh</li>
|
|
<li>Artisan (Laravel)</li>
|
|
<li>Composer</li>
|
|
<li>Sculpin</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>CLI Examples</h2>
|
|
|
|
<ul class="bullets">
|
|
<li><s>Drush</s></li>
|
|
<li>Symfony/Drupal Console</li>
|
|
<li>Terminus (Pantheon)/Platform.sh</li>
|
|
<li>Artisan (Laravel)</li>
|
|
<li>Composer</li>
|
|
<li>Sculpin</li>
|
|
</ul>
|
|
|
|
<aside class="notes">
|
|
<ul class="bullets">
|
|
<li>All of these except Drush are based on Symfony Console</li>
|
|
</ul>
|
|
</aside>
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h1 class="white big">Symfony Console</h1>
|
|
</section>
|
|
|
|
<section>
|
|
<h3 class="title">The Console component eases the creation of beautiful and testable command line interfaces.</h3>
|
|
|
|
<p>The Console component allows you to create command-line commands. Your console commands can be used for any recurring task, such as cronjobs, imports, or other batch jobs.</p>
|
|
|
|
<br>
|
|
<div class="text-small">
|
|
<p>
|
|
<a href="http://symfony.com/doc/current/components/console/introduction.html">http://symfony.com/doc/current/components/console/introduction.html</a>
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Installation</h2>
|
|
|
|
<pre><code class="bash text-big" data-trim>
|
|
$ composer require symfony/console
|
|
|
|
$ composer install
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Installation (cont)</h2>
|
|
|
|
<pre><code class="json text-big" data-trim>
|
|
# composer.json
|
|
|
|
"require": {
|
|
"symfony/console": "^3.1"
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Installation (cont)</h2>
|
|
<pre><code class="php text-big">
|
|
# app.php
|
|
|
|
require __DIR__ . '/vendor/autoload.php';
|
|
|
|
// Do stuff.
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Building a Console Application</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Steps</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Download the Console component</li>
|
|
<li>Add an "entry point"</li>
|
|
<li>Configure and run an <code>Application</code> class</li>
|
|
<li>Add new Commands</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">bin/drupalcamp</h2>
|
|
|
|
<pre><code class="php text-big">
|
|
#!/usr/bin/env php
|
|
|
|
require __DIR__ . '/drupalcamp.php';
|
|
</code></pre>
|
|
|
|
<aside class="notes">
|
|
<ul class="bullets">
|
|
<li>No .php file extension</li>
|
|
<li>Formatting issues</li>
|
|
<li>Convenience</li>
|
|
</ul>
|
|
</aside>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">bin/drupalcamp.php</h2>
|
|
|
|
<pre><code class="php text-medium">
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use Symfony\Component\Console\Application;
|
|
|
|
$application = new Application();
|
|
$application->run();
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<img src="assets/images/console-application-1.png" alt="" style="max-width: 100%">
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">bin/drupalcamp.php (cont)</h2>
|
|
|
|
<pre><code class="php text-medium">
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
use Symfony\Component\Console\Application;
|
|
|
|
$application = new Application();
|
|
$application->run('DrupalCamps', '1.0');
|
|
</code></pre>
|
|
|
|
<aside class="notes">
|
|
<ul>
|
|
<li>No .php extension</li>
|
|
</ul>
|
|
</aside>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<img src="assets/images/console-application-2.png" alt="">
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Adding Commands</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Adding Commands</h2>
|
|
<ul class="bullets">
|
|
<li>Add command classes in <code>src/</code></li>
|
|
<li>Autoload via Composer</li>
|
|
<li>Add to <code>Application</code></li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Autoloading via Composer</h2>
|
|
|
|
<pre><code class="php text-big" data-trim>
|
|
# composer.json
|
|
|
|
"autoload": {
|
|
"psr-4": {
|
|
"": "src/"
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">Autoloading via Composer</h2>
|
|
|
|
<pre><code class="php text-big" data-trim>
|
|
# composer.json
|
|
|
|
"autoload": {
|
|
"psr-4": {
|
|
"DrupalCamps\\": "src/"
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php</h2>
|
|
|
|
<pre><code class="php text-medium" data-trim>
|
|
use Symfony\Component\Console\Command\Command;
|
|
|
|
class GoCommand extends Command
|
|
{
|
|
public function configure()
|
|
{
|
|
$this->setName('go')
|
|
->setDescription('Go to a DrupalCamp.');
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php (cont)</h2>
|
|
|
|
<pre><code class="php text-normal">
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
...
|
|
|
|
public function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
// Execute the command.
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">bin/drupalcamp.php</h2>
|
|
|
|
<pre><code class="php text-big">
|
|
$application = new Application();
|
|
|
|
$application->add(new GoCommand());
|
|
|
|
$application->run();
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">bin/drupalcamp.php</h2>
|
|
|
|
<pre><code class="php text-big">
|
|
$application = new Application();
|
|
|
|
$application->addCommands(
|
|
[
|
|
new GoCommand(),
|
|
]
|
|
);
|
|
|
|
$application->run();
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background='#000' data-background-transition="none">
|
|
<img src="assets/images/go-command-1.png" alt="">
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Arguments and Options</h2>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php</h2>
|
|
|
|
<pre><code class="php text-normal" data-trim>
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
|
|
...
|
|
|
|
public function configure()
|
|
{
|
|
$this->setName('go')
|
|
->setDescription('Go to a DrupalCamp')
|
|
->addArgument('name', InputArgument::OPTIONAL, 'Which DrupalCamp?')
|
|
->addOption('past', null, InputOption::VALUE_NONE);
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php (cont)</h2>
|
|
|
|
<pre><code class="php text-normal" data-trim>
|
|
public function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$text = $input->getArgument('name');
|
|
$past = $input->getOption('past');
|
|
|
|
...
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<img src="assets/images/command-arguments.png" alt="">
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Input and Output</h2>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">InputInterface</h2>
|
|
<ul class="bullets">
|
|
<pre><code class="php text-big" data-trim>
|
|
$input->getArgument('foo');
|
|
|
|
$input->getOption('bar');
|
|
</code></pre>
|
|
<aside class="notes">
|
|
Gets values inputted by the user.
|
|
</aside>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">OutputInterface</h2>
|
|
<pre><code class="php text-big" data-trim>
|
|
$output->write($text);
|
|
|
|
$output->writeln($text);
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">OutputInterface</h2>
|
|
<pre><code class="php text-big" data-trim>
|
|
$output->write("<info>$text</info>");
|
|
|
|
$output->write("<error>$text</error>");
|
|
|
|
$output->write("<debug>$text</debug>");
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>SymfonyStyle</h2>
|
|
|
|
<div class="col--6-3">
|
|
<ul class="bullets">
|
|
<li>title</li>
|
|
<li>section</li>
|
|
<li>text</li>
|
|
<li>comment</li>
|
|
<li>note</li>
|
|
<li>caution</li>
|
|
<li>table</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="col--6-3">
|
|
<ul class="bullets">
|
|
<li>ask</li>
|
|
<li>askHidden</li>
|
|
<li>confirm</li>
|
|
<li>choice</li>
|
|
<li>success</li>
|
|
<li>error</li>
|
|
<li>warning</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">SymfonyStyle</h2>
|
|
|
|
<pre><code class="php text-normal">
|
|
public function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$io->table(
|
|
['Title', 'Speaker'],
|
|
[
|
|
['Drupal VM, Meet Symfony Console', 'Oliver Davies'],
|
|
['Drupal 8 and the Symfony EventDispatcher', 'Eric Smith'],
|
|
['Building with APIs', 'Nigel Dunn'],
|
|
]
|
|
);
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<img src="assets/images/talks-command.png" alt="">
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Interaction</h2>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php</h2>
|
|
<pre><code class="php text-normal">
|
|
public function interact(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
if (!$input->getArgument('name')) {
|
|
$input->setArgument('name', $io->ask('Which DrupalCamp?'));
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/GoCommand.php</h2>
|
|
<pre><code class="php text-normal">
|
|
public function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$io->success($input->getArgument('name'));
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Dependency Injection</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Dependency Injection</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>Instantiate dependencies in single place or DI container</li>
|
|
<li>Add as arguments when adding commands</li>
|
|
<li>Add as arguments to the constructor and assign to properties</li>
|
|
</ul>
|
|
|
|
<h3 class="note">
|
|
Make sure to call the __construct() method within the parent class.
|
|
</h3>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/Console/Application.php</h2>
|
|
|
|
<pre><code class="php text-medium" data-trim>
|
|
use GuzzleHttp\Client;
|
|
|
|
...
|
|
|
|
$client = new Client();
|
|
|
|
$application->add(new NewCommand($client));
|
|
</code></pre>
|
|
|
|
<aside class="notes">
|
|
<ul class="bullets">
|
|
<li>Example from the Drupal VM Generator</li>
|
|
<li>Downloads an archive of Drupal VM from GitHub</li>
|
|
<li></li>
|
|
</ul>
|
|
</aside>
|
|
</section>
|
|
|
|
<section data-background="#000" data-background-transition="none">
|
|
<h2 class="white">src/Command/NewCommand.php</h2>
|
|
|
|
<pre><code class="php text-normal" data-trim>
|
|
use GuzzleHttp\ClientInterface;
|
|
use Symfony\Component\Console\Command;
|
|
|
|
final class NewCommand extends Command
|
|
{
|
|
private $client;
|
|
|
|
public function __construct(ClientInterface $client)
|
|
{
|
|
parent::__construct();
|
|
|
|
$this->client = $client;
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Distributing Your Application</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>.phar files</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>PHP archive file</li>
|
|
<li>Packages your application into one file</li>
|
|
<li><code>box build</code></li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section data-background='#000' data-background-transition="none">
|
|
<h2 class="white">Generating phar files</h2>
|
|
<pre><code class="json text-small">
|
|
# composer.json
|
|
|
|
"scripts": {
|
|
"build": [
|
|
"box build",
|
|
"shasum drupalvm.phar |
|
|
awk '{print $1}' > drupalvm.phar.version"
|
|
]
|
|
}
|
|
</code></pre>
|
|
|
|
<pre><code class="bash text-small">
|
|
$ composer run-script build
|
|
</code></pre>
|
|
</section>
|
|
<section>
|
|
<h2>Roadmap</h2>
|
|
|
|
<ul class="bullets medium">
|
|
<li>Keep up to date with Drupal VM stable releases</li>
|
|
<li>New commands - updating existing files, adding vhosts</li>
|
|
<li>Improve user defaults and settings</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Resources</h2>
|
|
|
|
<ul class="bullets medium">
|
|
<li>https://github.com/opdavies/drupal-vm-generator</li>
|
|
<li>https://www.drupalvmgenerator.com</li>
|
|
<!-- <li>http://docs.drupalvmgenerator.com</li> -->
|
|
<li>http://bit.ly/announcing-drupal-vm-generator</li>
|
|
<li>http://symfony.com/doc/current/components</li>
|
|
<li>http://symfony.com/doc/current/cookbook/console</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section data-background="#0076C2" data-background-transition="none">
|
|
<h2 class="white">Questions?</h2>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Feedback</h2>
|
|
|
|
<ul class="bullets">
|
|
<li>@opdavies</li>
|
|
<li>https://www.oliverdavies.uk</li>
|
|
</ul>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script src="lib/js/head.min.js"></script>
|
|
<script src="js/reveal.js"></script>
|
|
|
|
<script>
|
|
|
|
// More info https://github.com/hakimel/reveal.js#configuration
|
|
Reveal.initialize({
|
|
controls: false,
|
|
progress: true,
|
|
history: true,
|
|
center: true,
|
|
|
|
transition: 'none', // none/fade/slide/convex/concave/zoom
|
|
|
|
// More info https://github.com/hakimel/reveal.js#dependencies
|
|
dependencies: [
|
|
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
|
|
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
|
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
|
|
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
|
|
{ src: 'plugin/zoom-js/zoom.js', async: true },
|
|
{ src: 'plugin/notes/notes.js', async: true }
|
|
]
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|