1
0
mirror of https://github.com/restoreddev/phpapprentice.git synced 2025-08-01 12:30:57 +02:00

Created initial site setup with hugo

This commit is contained in:
Andrew Davis
2019-07-12 19:21:18 -05:00
parent 77a0d2616b
commit e09557cf2c
80 changed files with 732 additions and 10488 deletions

7
.gitignore vendored
View File

@@ -1,8 +1,5 @@
.DS_Store
/vendor
/public
/node_modules
/docs
/.build
/.idea
/resources

View File

@@ -1,34 +0,0 @@
language: php
php:
- '7.1'
branches:
only:
- master
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
before_install:
- nvm install 8
install:
- composer update --prefer-dist --no-interaction --prefer-stable --no-suggest
- npm update
script:
- npm run prod
- php apprentice build
- vendor/bin/phpunit
deploy:
provider: pages
skip-cleanup: true
local-dir: .build
target-branch: gh-pages
github-token: $GITHUB_TOKEN
on:
branch: master

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env php
<?php
require __DIR__ . '/vendor/autoload.php';
load_config(__DIR__ . '/config.php');
$app = new Apprentice\App;
$app->main();

View File

@@ -1 +0,0 @@
phpapprentice.com

View File

@@ -1,3 +0,0 @@
User-agent: *
Disallow:
Sitemap: https://phpapprentice.com/sitemap.xml

View File

@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<!-- created with Free Online Sitemap Generator www.xml-sitemaps.com -->
<url>
<loc>https://phpapprentice.com/</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<loc>https://phpapprentice.com/installing-php.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/basics.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/variables.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/arithmetic.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/strings.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/comparisons.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/boolean-logic.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/conditionals.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/loops.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/arrays.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/functions.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/classes.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/classes-inheritance.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/classes-visibility.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/classes-constructor.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/static.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/interfaces.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/abstract.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/exceptions.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
<url>
<loc>https://phpapprentice.com/credits.html</loc>
<lastmod>2018-12-27T01:20:29+00:00</lastmod>
<priority>0.80</priority>
</url>
</urlset>

153
assets/prism.css Normal file
View File

@@ -0,0 +1,153 @@
/* PrismJS 1.16.0
https://prismjs.com/download.html#themes=prism-solarizedlight&languages=markup+css+clike+javascript+markup-templating+http+php */
/*
Solarized Color Schemes originally by Ethan Schoonover
http://ethanschoonover.com/solarized
Ported for PrismJS by Hector Matos
Website: https://krakendev.io
Twitter Handle: https://twitter.com/allonsykraken)
*/
/*
SOLARIZED HEX
--------- -------
base03 #002b36
base02 #073642
base01 #586e75
base00 #657b83
base0 #839496
base1 #93a1a1
base2 #eee8d5
base3 #fdf6e3
yellow #b58900
orange #cb4b16
red #dc322f
magenta #d33682
violet #6c71c4
blue #268bd2
cyan #2aa198
green #859900
*/
code[class*="language-"],
pre[class*="language-"] {
color: #657b83; /* base00 */
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
background: #073642; /* base02 */
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
background: #073642; /* base02 */
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background-color: #fdf6e3; /* base3 */
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #93a1a1; /* base1 */
}
.token.punctuation {
color: #586e75; /* base01 */
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #268bd2; /* blue */
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.url,
.token.inserted {
color: #2aa198; /* cyan */
}
.token.entity {
color: #657b83; /* base00 */
background: #eee8d5; /* base2 */
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #859900; /* green */
}
.token.function,
.token.class-name {
color: #b58900; /* yellow */
}
.token.regex,
.token.important,
.token.variable {
color: #cb4b16; /* orange */
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

10
assets/prism.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
@import "prismjs/themes/prism-solarizedlight.css";
@import "assets/prism.css";
$primary-color: #2AA198;
$primary-color-dark: #1D6E68;

View File

@@ -1,8 +1,4 @@
import Prism from 'prismjs';
var onLoad = function () {
Prism.highlightAll();
var menuButton = document.querySelector('.menu-button');
// stop execution if menu button does not exist on page

View File

@@ -1,25 +0,0 @@
{
"name": "restoreddev/phpapprentice",
"description": "A site for learning PHP",
"require": {
"php": "^7.1.3",
"symfony/console": "^4.1",
"erusev/parsedown": "^1.7"
},
"require-dev": {
"phpunit/phpunit": "^7.3"
},
"autoload": {
"psr-4": {
"Apprentice\\": "src/"
},
"files": [
"src/util/functions.php"
]
},
"autoload-dev": {
"psr-4": {
"Test\\": "test/"
}
}
}

1599
composer.lock generated

File diff suppressed because it is too large Load Diff

4
config.toml Normal file
View File

@@ -0,0 +1,4 @@
baseURL = "https://phpapprentice.com/"
languageCode = "en-us"
title = "PHP Apprentice"
uglyurls = true

View File

@@ -1,3 +1,10 @@
+++
title = "Basics"
description = "Getting Started"
tags = ["php", "basics"]
slug = "basics"
next = "variables.html"
+++
If you want to follow along by writing code, start by downloading a code editor. I recommend
[Visual Studio Code](https://code.visualstudio.com/) or [Sublime Text](https://www.sublimetext.com/).
Next, create a new file in your editor called `basics.php` and save it anywhere on your computer, like a folder

7
layouts/404.html Normal file
View File

@@ -0,0 +1,7 @@
<div class="container center">
<a href="/" class="logo-404"><?= icon('elephant') ?></a>
<p class="message-404">Whoops! The page could not be found.</p>
<div class="toc-404">
<?php partial('table_of_contents') ?>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ if .Title }}{{ .Title }}{{ else }}{{ .Site.Title }}{{ end }}</title>
<meta name="description" content="{{ if .Description }}{{ .Description }}{{ else }}An online book for learning PHP{{ end }}" />
<meta name="viewport" content="width=device-width, initial-scale=1">
{{ $css := resources.Get "site.css" }}
{{ $style := $css | resources.PostCSS }}
<link rel="stylesheet" type="text/css" href="{{ $style.Permalink }}">
<link rel="icon" href="/favicon-32.png">
{{ $prism := resources.Get "prism.js" }}
{{ $site := resources.Get "site.js"}}
{{ $js := slice $prism $site | resources.Concat "bundle.js" }}
<script src="{{ $js.Permalink }}"></script>
</head>
<body>
{{ block "main" . }}{{ end }}
</body>
</html>

View File

@@ -0,0 +1,34 @@
{{ define "main" }}
<div class="container small center">
<div>
<div class="home-title-wrapper">
<div class="home-logo">{{ readFile "static/elephant.svg" | safeHTML }}</div>
<h1 class="home-title">PHP Apprentice</h1>
<h3 class="home-subtitle">An online book for learning PHP</h3>
</div>
<p>
PHP Apprentice is an online, open source book about the PHP programming language. PHP is one of the most popular platforms for building websites and web services. It is a great language that is easy to learn and allows you to build powerful and complex web applications very quickly.
</p>
<p>
The goal of PHP Apprentice is to be an easy to understand resource for learning how to write good code in PHP. There are a lot of PHP tutorials on the internet that use outdated practices or insecure code. I want this book to show how to write PHP code with quality.
</p>
<p>
The contents of PHP Apprentice are for beginners and experienced PHP developers. The book currently has content for learning the basics of the language. In the future, more pages will be added for more advanced topics like building websites, database integration and security.
</p>
<p>
PHP Apprentice is currently a work in progress. If you would like to give feedback or request a certain discussion topic, check out the <a href="https://github.com/restoreddev/phpapprentice" target="_blank">GitHub repository</a>.
</p>
<div class="home-buttons">
<a href="/basics.html" class="button">
<div class="icon">{{ readFile "static/book-reference.svg" | safeHTML }}</div>
Open First Chapter
</a>
{{ partial "menu_button.html" . }}
</div>
<hr />
<p>Created and managed by <a href="https://twitter.com/restoreddev" target="_blank">Andrew Davis @restoreddev</a>
</div>
</div>
{{ partial "menu_modal.html" . }}
{{ end }}

View File

@@ -0,0 +1,26 @@
{{ define "main" }}
<div class="container small center">
{{ partial "menu_button.html" . }}
<h1>{{ .Title }}</h1>
<h3 class="subtitle">{{ .Description }}</h3>
{{ .Content }}
<div class="clearfix"></div>
<div class="navigate-links">
{{ if .Params.previous }}
<a href="/{{ .Params.previous }}" title="Previous" id="prev-link">
<div class="icon">{{ readFile "static/cheveron-outline-left.svg" | safeHTML }}</div>
Previous
</a>
{{ end }}
{{ if .Params.next }}
<a href="/{{ .Params.next }}" title="Next" id="next-link">
Next
<div class="icon">{{ readFile "static/cheveron-outline-right.svg" | safeHTML }}</div>
</a>
{{ end }}
</div>
</div>
{{ partial "menu_modal.html" . }}
{{ end }}

View File

@@ -0,0 +1,6 @@
<div class="menu">
<button class="menu-button" title="Open Menu">
<div class="icon">{{ readFile "static/show-sidebar.svg" | safeHTML }}</div>
Table of Contents
</button>
</div>

View File

@@ -0,0 +1,8 @@
<div class="modal closed">
<div class="modal-content">
<button class="modal-button right" title="Close">
<div class="icon">{{ readFile "static/close-outline.svg" | safeHTML }}</div>
</button>
{{ partial "table_of_contents.html" . }}
</div>
</div>

View File

@@ -0,0 +1,38 @@
<div class="table-of-contents">
<h4>Table of Contents</h4>
<ul class="list-plain">
<li><a href="/">Preface</a></li>
<li><a href="/installing-php.html">Installing PHP</a></li>
</ul>
<h5 class="section-title">Basics</h5>
<ol>
<li><a href="/basics.html">Basics</a></li>
<li><a href="/variables.html">Variables</a></li>
<li><a href="/arithmetic.html">Arithmetic</a></li>
<li><a href="/strings.html">Strings</a></li>
<li><a href="/comparisons.html">Comparisons</a></li>
<li><a href="/boolean-logic.html">Boolean Logic</a></li>
<li><a href="/conditionals.html">Conditionals</a></li>
<li><a href="/loops.html">Loops</a></li>
<li><a href="/arrays.html">Arrays</a></li>
<li><a href="/functions.html">Functions</a></li>
<li><a href="/classes.html">Classes</a></li>
<li><a href="/classes-inheritance.html">Classes: Inheritance</a></li>
<li><a href="/classes-visibility.html">Classes: Visibility</a></li>
<li><a href="/classes-constructor.html">Classes: Constructor</a></li>
<li><a href="/static.html">Static</a></li>
<li><a href="/interfaces.html">Interfaces</a></li>
<li><a href="/abstract.html">Abstract Classes</a></li>
<li><a href="/exceptions.html">Exceptions</a></li>
</ol>
<h5 class="section-title">Web</h5>
<ol>
<li><a href="/web/http.html">HTTP</a></li>
<li><a href="/web/http-post.html">HTTP POST</a></li>
<li><a href="/web/http-server.html">PHP HTTP Server</a></li>
</ol>
<a href="/credits.html">Credits</a>
</div>

8504
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,7 @@
"version": "1.0.0",
"description": "A website for learning PHP",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "./node_modules/.bin/encore dev",
"watch": "./node_modules/.bin/encore dev --watch",
"prod": "./node_modules/.bin/encore production"
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
@@ -19,14 +16,10 @@
},
"homepage": "https://github.com/restoreddev/phpapprentice#readme",
"devDependencies": {
"@symfony/webpack-encore": "^0.22.4",
"autoprefixer": "^8.6.5",
"postcss-import": "^11.1.0",
"postcss-loader": "^3.0.0",
"postcss-simple-vars": "^4.1.0"
"autoprefixer": "^9.6.1",
"postcss-cli": "^6.1.3",
"postcss-import": "^12.0.1",
"postcss-simple-vars": "^5.0.2"
},
"dependencies": {
"babel-plugin-prismjs": "^1.0.2",
"prismjs": "^1.15.0"
}
"dependencies": {}
}

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./test</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -1,22 +0,0 @@
<?php
namespace Apprentice;
use Apprentice\Command;
use Symfony\Component\Console\Application;
class App
{
/**
* Runs cli application
*
* @return void
*/
public function main(): void
{
$cli = new Application;
$cli->add(new Command\BuildCommand);
$cli->add(new Command\ServerCommand);
$cli->run();
}
}

View File

@@ -1,150 +0,0 @@
<?php
namespace Apprentice;
use Parsedown;
/**
* Handles building pages in public folder
* using configuration based on Page classes
*/
class Build
{
/**
* Builds all pages in config
*
* @return void
*/
public function buildAll(): void
{
$this->createOutputFolder();
$this->cleanOutputFolder();
$this->copyFiles();
$pages = config('pages');
foreach ($pages as $page) {
$this->buildPage($page);
}
}
/**
* Builds single page in config
*
* @param string $name Name of page to build
* @return string Contents of built page
*/
public function runSingleBuild(string $name): string
{
$this->createOutputFolder();
$pages = config('pages');
foreach ($pages as $page) {
if ($page->name == $name) {
break;
}
}
return $this->buildPage($page);
}
/**
* Deletes all html files in public folder
*
* @return void
*/
private function cleanOutputFolder(): void
{
$files = glob(config('output_dir') . '/*.html');
foreach ($files as $file) {
unlink($file);
}
}
private function copyFiles(): void
{
$filesDir = config('files_dir');
if (!file_exists($filesDir)) {
return;
}
$outputDir = config('output_dir');
foreach (glob($filesDir . '/*') as $file) {
$name = basename($file);
copy($file, $outputDir . '/' . $name);
}
}
/**
* Creates output folder if it does not exist
*
* @return void
*/
private function createOutputFolder(): void
{
if (!file_exists(config('output_dir'))) {
mkdir(config('output_dir'));
}
}
/**
* Builds single Page into html and
* outputs to public directory
*
* @param Page $page Page from config to be built
* @return void Contents of built page
*/
private function buildPage(Page $page): string
{
if (!empty($page->chapter)) {
if (!file_exists(config('chapter_dir') . '/' . $page->chapter)) {
throw new \Exception('Code file not found: ' . $page->chapter);
}
$parser = new Parsedown();
$content = file_get_contents(config('chapter_dir') . '/' . $page->chapter);
$page->variables['chapter'] = $parser->text($content);
}
if ($page->template) {
$template = config('templates_dir') . '/' . $page->template;
} else {
$template = config('templates_dir') . '/default.phtml';
}
$output = $this->getOutput($template, $page->variables);
$path = config('output_dir') . '/' . $page->name . '.html';
$dir = pathinfo($path, PATHINFO_DIRNAME);
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($path, $output);
return $output;
}
/**
* Loads template file with scoped
* variables
*
* @param string $path Path to template in templates folder
* @param array $vars Array of variables to be loaded in template
* @return string Output of template
*/
private function getOutput(string $path, array $vars = []): string {
if ($vars) {
extract($vars);
}
ob_start();
require $path;
$output = ob_get_contents();
ob_end_clean();
return $output;
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace Apprentice\Command;
use Apprentice\Build;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class BuildCommand extends Command
{
protected function configure()
{
$this->setName('build')
->setDescription('Builds PHP templates into HTML files.')
->setHelp('Help!');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$build = new Build;
$build->buildAll();
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace Apprentice\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ServerCommand extends Command
{
protected function configure()
{
$this->setName('server')
->setDescription('Runs PHP server that automatically builds files')
->setHelp('Help!');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln('Starting development server on localhost:8080');
system('php -S localhost:8080 -t ' . config('output_dir') . ' src/util/router.php');
}
}

View File

@@ -1,77 +0,0 @@
<?php
namespace Apprentice;
/**
* A class representing a single page in the build process
*/
class Page
{
/**
* Name of page, used in filename
*
* @var string
*/
public $name;
/**
* Name of template to use
* If none is provided, a default will be used
*
* @var string|null
*/
public $template;
/**
* Name of chapter file to load and parse
* Will be skipped if none is provided
*
* @var string|null
*/
public $chapter;
/**
* Map of data to passed to template
*
* @var array
*/
public $variables;
/**
* Creates new page
*
* @param string $name
* @param string|null $template
* @param string|null $chapter
* @param array $variables
*/
public function __construct(
string $name,
?string $chapter = null,
?array $variables = [],
?string $template = null
) {
$this->name = $name;
$this->chapter = $chapter;
$this->variables = $variables;
$this->template = $template;
}
/**
* Static constructor
*
* @param string $name
* @param string|null $template
* @param string|null $code
* @param array $variables
* @return Apprentice\Page
*/
public static function create(
string $name,
?string $chapter = null,
?array $variables = [],
?string $template = null
): Page {
return new static($name, $chapter, $variables, $template);
}
}

View File

@@ -1,111 +0,0 @@
<?php
/**
* Runs a scoped require on a partial
*
* The filename must start with an underscore
* and end with .php or .phtml
*
* @param string $path Name of partial
* @param array $vars Variables to use for the partial
* @return void
*/
function partial(string $path, array $vars = []) {
$dir = config('templates_dir');
if (file_exists($dir. '/' . "_$path.php")) {
$file = $dir. '/' . "_$path.php";
} elseif (file_exists($dir . '/' . "_$path.phtml")) {
$file = $dir. '/' . "_$path.phtml";
} else {
throw new Exception('Partial could not be found: ' . $dir . '/' . "_$path.php");
}
extract($vars);
require $file;
}
/**
* Gets url path to page
*
* @param string $page Name of page
* @return string
*/
function page_path(string $page): string {
return '/' . $page . '.html';
}
/**
* Safely escapes text for display in html
*
* @param string $text
* @return string
*/
function escape(string $text): string {
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8', true);
}
/**
* Loads content of svg icon from assets folder
*
* @param string $name Name of icon without extension
* @return string Contents of file
*/
function icon(string $name): string {
$dir = config('icon_dir');
$path = $dir . '/' . $name . '.svg';
if (file_exists($path)) {
return file_get_contents($path);
}
return '';
}
/**
* Loads config file into a global
*
* @param string $path
* @return void
*/
function load_config(string $path) {
$config = require $path;
if (!is_array($config)) {
throw new \Exception('Config file does not return an array.');
}
$GLOBALS['APPRENTICE_CONFIG'] = $config;
}
/**
* Returns config value
*
* @param string $key
* @return mixed
*/
function config(string $key) {
$config = $GLOBALS['APPRENTICE_CONFIG'] ?? [];
return $config[$key] ?? null;
}
/**
* Returns path to asset based on manifes.json file
*
* @param string $name
* @return string
*/
function asset(string $name): string {
$outputDir = config('output_dir');
if (file_exists($outputDir . '/manifest.json')) {
$text = file_get_contents($outputDir . '/manifest.json');
$paths = json_decode($text, true);
if (isset($paths[$name])) {
return $paths[$name];
}
}
return '/' . $name;
}

View File

@@ -1,32 +0,0 @@
<?php
/**
* Router file used for development server
* to create html files on demand
*/
require __DIR__ . '/../../vendor/autoload.php';
load_config(__DIR__ . '/../../config.php');
$uri = $_SERVER['REQUEST_URI'];
$pathinfo = pathinfo($uri);
if ($pathinfo['dirname'] == '/' && !isset($pathinfo['extension'])) {
$pathinfo['extension'] = 'html';
$pathinfo['filename'] = 'index';
}
if ($pathinfo['extension'] == 'html') {
$name = $pathinfo['filename'];
if ($pathinfo['dirname'] != '/') {
$name = ltrim($pathinfo['dirname'], '/') . '/' . $name;
}
$build = new Apprentice\Build;
$output = $build->runSingleBuild($name);
echo $output;
return true;
}
return false;

View File

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 167 B

View File

Before

Width:  |  Height:  |  Size: 169 B

After

Width:  |  Height:  |  Size: 169 B

View File

Before

Width:  |  Height:  |  Size: 167 B

After

Width:  |  Height:  |  Size: 167 B

View File

Before

Width:  |  Height:  |  Size: 169 B

After

Width:  |  Height:  |  Size: 169 B

View File

Before

Width:  |  Height:  |  Size: 200 B

After

Width:  |  Height:  |  Size: 200 B

View File

Before

Width:  |  Height:  |  Size: 225 B

After

Width:  |  Height:  |  Size: 225 B

View File

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 223 B

View File

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 221 B

View File

Before

Width:  |  Height:  |  Size: 222 B

After

Width:  |  Height:  |  Size: 222 B

View File

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 314 B

View File

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 260 B

View File

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 223 B

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 162 B

After

Width:  |  Height:  |  Size: 162 B

View File

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View File

Before

Width:  |  Height:  |  Size: 217 B

After

Width:  |  Height:  |  Size: 217 B

View File

@@ -1,8 +0,0 @@
<?php
namespace Test;
class BaseTestCase extends \PHPUnit\Framework\TestCase
{
}

View File

@@ -1,62 +0,0 @@
<?php
namespace Test;
use Apprentice\Build;
class BuildTest extends BaseTestCase
{
public function setUp()
{
load_config(__DIR__ . '/static/config.php');
}
public function tearDown()
{
$files = glob('/tmp/apprentice_output/*');
foreach ($files as $file) {
unlink($file);
}
rmdir('/tmp/apprentice_output');
}
public function test_build_single_page()
{
$build = new Build();
$build->runSingleBuild('test');
$html = file_get_contents('/tmp/apprentice_output/test.html');
$expectedHtml = "<div>Test Title</div>\n" .
"<div>Test Subtitle</div>\n" .
"<div>Test Description</div>\n" .
"<div>&lt;p&gt;Test comment&lt;/p&gt;\n" .
"&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;\$test = &#039;test&#039;;&lt;/code&gt;&lt;/pre&gt;</div>\n";
$this->assertFalse(empty($html));
$this->assertEquals($expectedHtml, $html);
}
public function test_build_all()
{
$build = new Build();
$build->buildAll();
$expectedHtml = "<div>Test Title</div>\n" .
"<div>Test Subtitle</div>\n" .
"<div>Test Description</div>\n" .
"<div>&lt;p&gt;Test comment&lt;/p&gt;\n" .
"&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;\$test = &#039;test&#039;;&lt;/code&gt;&lt;/pre&gt;</div>\n";
$expectedHtml2 = "<div>index</div>\n";
$html = file_get_contents('/tmp/apprentice_output/test.html');
$html2 = file_get_contents('/tmp/apprentice_output/index.html');
$this->assertEquals($expectedHtml, $html);
$this->assertEquals($expectedHtml2, $html2);
$this->assertTrue(file_exists('/tmp/apprentice_output/test.txt'));
$this->assertTrue(file_exists('/tmp/apprentice_output/TEST'));
}
}

View File

@@ -1,78 +0,0 @@
<?php
namespace Test;
class FunctionsTest extends BaseTestCase
{
public function setUp()
{
mkdir('/tmp/apprentice_output');
}
public function tearDown()
{
$GLOBALS['PARTIAL_TEST'] = null;
$files = glob('/tmp/apprentice_output/*');
foreach ($files as $file) {
unlink($file);
}
rmdir('/tmp/apprentice_output');
}
public function test_load_config()
{
load_config(__DIR__ . '/static/config.php');
$this->assertEquals(__DIR__ . '/static/../icons', config('icon_dir'));
}
public function test_page_path()
{
$page = page_path('home');
$this->assertEquals('/home.html', $page);
}
public function test_escape()
{
$output = escape("'\"&");
$this->assertEquals("&#039;&quot;&amp;", $output);
}
public function test_icon()
{
load_config(__DIR__ . '/static/config.php');
$icon = icon('test');
$this->assertFalse(empty($icon));
$this->assertEquals("<test></test>\n", $icon);
}
public function test_partial()
{
partial('partial', ['test' => 'test var']);
$this->assertEquals('test var', $GLOBALS['PARTIAL_TEST']);
}
public function test_asset_path_with_manifest()
{
file_put_contents(
'/tmp/apprentice_output/manifest.json',
json_encode(['js/app.js' => '/js/app-1234.js'])
);
$path = asset('js/app.js');
$this->assertEquals('/js/app-1234.js', $path);
}
public function test_asset_path_without_manifest()
{
$path = asset('js/app.js');
$this->assertEquals('/js/app.js', $path);
}
}

View File

@@ -1 +0,0 @@
<test></test>

View File

@@ -1,4 +0,0 @@
Test comment
```php
$test = 'test';
```

View File

@@ -1,19 +0,0 @@
<?php
use Apprentice\Page;
return [
'icon_dir' => __DIR__ . '/../icons',
'chapter_dir' => __DIR__ . '/chapter',
'templates_dir' => __DIR__ . '/templates',
'output_dir' => '/tmp/apprentice_output',
'files_dir' => __DIR__ . '/files',
'pages' => [
Page::create('index', null, [], 'index.phtml'),
Page::create('test', 'test.md', [
'title' => 'Test Title',
'subtitle' => 'Test Subtitle',
'description' => 'Test Description',
]),
],
];

View File

@@ -1,3 +0,0 @@
<?php
$GLOBALS['PARTIAL_TEST'] = $test;

View File

@@ -1,4 +0,0 @@
<div><?= escape($title) ?></div>
<div><?= escape($subtitle) ?></div>
<div><?= escape($description) ?></div>
<div><?= escape($chapter) ?></div>

View File

@@ -1 +0,0 @@
<div>index</div>

View File

@@ -1,18 +0,0 @@
var Encore = require('@symfony/webpack-encore');
Encore
.setOutputPath('.build')
.setPublicPath('/')
.addEntry('js/site', './assets/js/site.js')
.addStyleEntry('css/site', './assets/css/site.css')
.enablePostCssLoader()
.configureBabel(function (babel) {
babel.plugins.push(['prismjs', {
"languages": ["php", "http"],
"css": false,
}]);
})
.enableVersioning();
;
module.exports = Encore.getWebpackConfig();