Merge branch 'master' of github.com:dauxio/daux.io

# Conflicts:
#	daux_libraries/README.md
#	src/css/theme_daux/_components.scss
#	src/css/theme_daux/_fonts.scss
#	src/css/theme_daux/_homepage.scss
#	src/css/theme_daux/_mixins.scss
#	src/css/theme_daux/_print.scss
#	src/css/theme_daux/_structure.scss
#	src/css/theme_daux/_typography.scss
#	src/css/theme_daux/_variables.scss
#	src/css/theme_daux/theme-blue.scss
#	src/css/theme_daux/theme-green.scss
#	src/css/theme_daux/theme-navy.scss
#	src/css/theme_daux/theme-red.scss
#	src/css/theme_daux/theme.scss
#	src/css/theme_daux/vendor/normalize.scss
#	src/css/theme_daux_singlepage/_fonts.scss
#	src/css/theme_daux_singlepage/_print.scss
#	src/css/theme_daux_singlepage/_typography.scss
#	src/css/theme_daux_singlepage/main.scss
#	themes/d3/js/README.md
#	themes/d3/js/daux.js
#	themes/d3/js/highlight.pack.js
#	themes/d3/js/html5shiv-3.7.3.min.js
#	themes/d3/js/jquery-1.11.3.min.js
#	themes/d3/scss/_components.scss
#	themes/d3/scss/_fonts.scss
#	themes/d3/scss/_homepage.scss
#	themes/d3/scss/_mixins.scss
#	themes/d3/scss/_print.scss
#	themes/d3/scss/_structure.scss
#	themes/d3/scss/_typography.scss
#	themes/d3/scss/_variables.scss
#	themes/d3/scss/theme-blue.scss
#	themes/d3/scss/theme-green.scss
#	themes/d3/scss/theme-navy.scss
#	themes/d3/scss/theme-red.scss
#	themes/d3/scss/theme.scss
#	themes/d3/scss/vendor/highlight.scss
#	themes/d3/scss/vendor/normalize.scss
#	themes/daux/config.json
#	themes/daux/css/theme-blue.min.css
#	themes/daux/css/theme-blue.min.css.map
#	themes/daux/css/theme-green.min.css
#	themes/daux/css/theme-green.min.css.map
#	themes/daux/css/theme-navy.min.css
#	themes/daux/css/theme-navy.min.css.map
#	themes/daux/css/theme-red.min.css
#	themes/daux/css/theme-red.min.css.map
#	themes/daux/js/README.md
#	themes/daux/scss/_components.scss
#	themes/daux/scss/_fonts.scss
#	themes/daux/scss/_homepage.scss
#	themes/daux/scss/_mixins.scss
#	themes/daux/scss/_print.scss
#	themes/daux/scss/_structure.scss
#	themes/daux/scss/_typography.scss
#	themes/daux/scss/_variables.scss
#	themes/daux/scss/theme-blue.scss
#	themes/daux/scss/theme-green.scss
#	themes/daux/scss/theme-navy.scss
#	themes/daux/scss/theme-red.scss
#	themes/daux/scss/theme.scss
#	themes/daux/scss/vendor/normalize.scss
#	themes/daux_singlepage/css/main.min.css
#	themes/daux_singlepage/css/main.min.css.map
This commit is contained in:
Daniel Seifert 2019-09-24 10:43:01 +02:00
commit 48e0d0c734
106 changed files with 10608 additions and 3668 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
vendor
node_modules

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

4
.gitignore vendored
View File

@ -5,3 +5,7 @@ node_modules
static
/vendor
/prettier.config.js
/.eslintrc.js
/stylelint.config.js

View File

@ -3,6 +3,7 @@ language: php
php:
- '7.1'
- '7.2'
- '7.3'
- nightly
matrix:
@ -19,9 +20,14 @@ after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
jobs:
include:
- stage: "Deploy Documentation"
php: "7.3"
script: skip
before_deploy:
- composer install
- bin/daux generate
deploy:
provider: pages
local_dir: static

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at stephane.goetz@onigoetz.ch. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@ -1,31 +1,31 @@
FROM php:7-alpine
FROM composer:1.7.2 AS composer
RUN apk info && apk add --no-cache unzip
FROM php:7-stretch
RUN apt-get update && apt-get install -y libicu-dev git unzip
RUN docker-php-ext-configure intl \
&& docker-php-ext-install intl
RUN mkdir /daux && mkdir /build
WORKDIR /daux
COPY --from=composer /usr/bin/composer /usr/bin/composer
# Copy files
COPY composer.json /daux/composer.json
COPY composer.lock /daux/composer.lock
RUN composer install --prefer-dist --no-ansi --no-dev --no-interaction --no-progress --no-scripts --optimize-autoloader
COPY bin/ /daux/bin/
COPY libs/ /daux/libs/
COPY templates/ /daux/templates/
COPY themes/ /daux/themes/
COPY tipuesearch/ /daux/tipuesearch/
COPY daux_libraries/ /daux/daux_libraries/
COPY global.json /daux/global.json
COPY composer.json /daux/composer.json
COPY composer.lock /daux/composer.lock
COPY index.php /daux/index.php
# Composer install
RUN cd /daux && php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php \
&& rm composer-setup.php \
&& php composer.phar install --prefer-dist --no-ansi --no-dev --no-interaction --no-progress --no-scripts --optimize-autoloader \
&& rm composer.phar
RUN ln -s /daux/bin/daux /usr/local/bin/daux
WORKDIR /build

View File

@ -34,17 +34,17 @@
This is a list of sites using Daux.io:
- With a custom theme:
* [Pixolution flow](https://docs.pixolution.org)
* [Crafty](https://swissquote.github.io/crafty)
* [Pixolution flow](https://docs.pixolution.org)
* [Soisy](https://doc.soisy.it/)
* [Vulkan Tutorial](https://vulkan-tutorial.com)
* [TrackJs](http://docs.trackjs.com)
* [3Q](https://docs.3q.video/)
- With the default Theme
* [Daux.io](https://daux.io/)
* [Gltn - An open-source word processor webapp](http://felkerdigitalmedia.com/gltn/docs/)
* [Invade & Annex 3 - An Arma 3 Co-operative Mission](http://ia3.ahoyworld.co.uk/)
* [Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation](http://mun.ee)
* [DoctrineWatcher](https://dsentker.github.io/WatcherDocumentation/)
* [DrupalGap](http://docs.drupalgap.org/8/)
* [ICADMIN: An admin panel powered by CodeIgniter.](http://istocode.com/shared/ic-admin/)
* [Cumulus TV: Android TV app that turns any stream/page into a Live Channel](http://cumulustv.herokuapp.com)
* [Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation](http://mun.ee)
* [Nuntius: A PHP framework for bots](https://roysegall.github.io/nuntius-bot/)
Do you use Daux.io? Send me a pull request or open an [issue](https://github.com/dauxio/daux.io/issues) and I will add you to the list.
@ -71,7 +71,7 @@ If the command isn't found, ensure your `$PATH` contains `~/.composer/vendor/bin
Or if you wish to use Docker, the start of the command will be :
```bash
docker run --rm -it -w /build -v "$PWD":/build daux/daux.io daux
docker run --rm -it -w /build -v "$PWD":/build -u "$(id -u):$(id -g)" daux/daux.io daux
```
## Run on a server
@ -233,15 +233,15 @@ You can then point your browser to http://localhost:8086
## PHP Requirements
Daux.io is compatible with PHP 5.6 and up.
Daux.io is compatible with PHP 7.1.3 and up.
The reason is because some dependencies we have (mainly Symfony and Guzzle) do not support php 5.4 anymore.
The reason is because some dependencies we have (mainly Symfony and Guzzle) do not support PHP 5.6 anymore.
### Extensions
PHP Needs the following extension to work : `php-mbstring` and `php-xml`.
If you encounter an error similar to `utf8_decode() not found` this means that you're missing the `php-xml` package. (We've seen it happen only on PHP 7)
If you encounter an error similar to `utf8_decode() not found` this means that you're missing the `php-xml` package.
## Support

View File

@ -19,14 +19,19 @@
"require": {
"php": ">=7.1.3",
"guzzlehttp/guzzle": "~6.0",
"league/commonmark": "^0.15",
"league/commonmark": "^0.18",
"league/plates": "~3.1",
"myclabs/deep-copy": "^1.5",
"symfony/console": "^4.0",
"symfony/http-foundation": "^4.0",
"symfony/polyfill-intl-icu": "^1.10",
"symfony/process": "^4.0",
"webuni/commonmark-table-extension": "0.6.*",
"webuni/front-matter": "^1.0.0"
"webuni/commonmark-table-extension": "0.9.*",
"webuni/front-matter": "^1.0.0",
"scrivo/highlight.php": "^9.15"
},
"suggest":{
"ext-intl": "Allows to translate the modified at date"
},
"autoload": {
"psr-4": {
@ -37,7 +42,10 @@
"justinwalsh/daux.io": "*"
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"mikey179/vfsStream": "^1.6"
"phpunit/phpunit": "~7.4",
"mikey179/vfsstream": "^1.6"
},
"scripts": {
"test": "phpunit"
}
}

1567
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +1,62 @@
module.exports = {
browsers:
"> 0.25%, Edge >= 15, Safari >= 10, iOS >= 10, Chrome >= 56, Firefox >= 51, IE >= 11, not op_mini all",
presets: [
"@swissquote/crafty-preset-babel",
"@swissquote/crafty-runner-rollup",
"@swissquote/crafty-preset-postcss",
"@swissquote/crafty-runner-gulp"
],
destination_css: "themes",
destination_css: ".",
destination_js: ".",
stylelint_pattern: [
"themes/daux/scss/**/*.scss",
"themes/daux_singlepage/scss/**/*.scss",
"src/css/**/*.scss",
"!*.min.css",
"!**/vendor/**/*.scss"
],
stylelint: {
rules: {
"swissquote/no-type-outside-scope": null
"swissquote/no-type-outside-scope": null,
"plugin/no-unsupported-browser-features": null
}
},
js: {
search: {
runner: "rollup",
source: "src/js/search/index.js",
destination: "daux_libraries/search.min.js"
},
theme_daux: {
runner: "rollup",
source: "src/js/theme_daux/index.js",
destination: "themes/daux/js/daux.min.js"
}
},
css: {
"theme_blue": {
source: "themes/daux/scss/theme-blue.scss",
destination: "daux/css/theme-blue.min.css",
watch: ["themes/daux/scss/**"]
theme_blue: {
source: "src/css/theme_daux/theme-blue.scss",
destination: "themes/daux/css/theme-blue.min.css",
watch: ["src/css/**/*.scss"]
},
"theme_green": {
source: "themes/daux/scss/theme-green.scss",
destination: "daux/css/theme-green.min.css",
watch: ["themes/daux/scss/**"]
theme_green: {
source: "src/css/theme_daux/theme-green.scss",
destination: "themes/daux/css/theme-green.min.css",
watch: ["src/css/**/*.scss"]
},
"theme_navy": {
source: "themes/daux/scss/theme-navy.scss",
destination: "daux/css/theme-navy.min.css",
watch: ["themes/daux/scss/**"]
theme_navy: {
source: "src/css/theme_daux/theme-navy.scss",
destination: "themes/daux/css/theme-navy.min.css",
watch: ["src/css/**/*.scss"]
},
"theme_red": {
source: "themes/daux/scss/theme-red.scss",
destination: "daux/css/theme-red.min.css",
watch: ["themes/daux/scss/**"]
theme_red: {
source: "src/css/theme_daux/theme-red.scss",
destination: "themes/daux/css/theme-red.min.css",
watch: ["src/css/**/*.scss"]
},
"daux_singlepage": {
source: "themes/daux_singlepage/scss/main.scss",
destination: "daux_singlepage/css/main.min.css",
watch: ["themes/daux_singlepage/scss/**"]
daux_singlepage: {
source: "src/css/theme_daux_singlepage/main.scss",
destination: "themes/daux_singlepage/css/main.min.css",
watch: ["src/css/**/*.scss"]
}
}
};

12
daux_libraries/README.md Normal file
View File

@ -0,0 +1,12 @@
# Updating Highlight.js
This build of highlight.js contains all languages. to achieve this, go to : https://highlightjs.org/download/
And run the following snipped in the console:
```
$$("input[type=checkbox]").forEach(function(checkbox) { checkbox.checked=true; })
```
This will tick all boxes instead of doing it by hand.

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,3 @@
/*
Tipue Search 5.0
Copyright (c) 2015 Tipue
Tipue Search is released under the MIT License
http://www.tipue.com/search
*/
body.with-search {
overflow: hidden;
}
@ -35,10 +28,9 @@ body.with-search {
bottom: 0;
background: #000;
opacity: .6;
opacity: 0.6;
}
.homepage .SearchResults,
.homepage .SearchResultsBackdrop {
top: 50px;
@ -59,6 +51,7 @@ body.with-search {
line-height: 1.6;
color: #555;
margin: 7px 0;
clear: both;
}
.SearchResults__warning a {
@ -86,7 +79,7 @@ body.with-search {
cursor: pointer;
padding: 0;
margin: 0;
line-height: .8em;
line-height: 0.8em;
}
.SearchResults__title {
@ -164,7 +157,6 @@ body.with-search {
border: 1px solid #e2e2e2;
}
/* spinner */
@media (min-width: 650px) {

2
daux_libraries/search.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -36,13 +36,19 @@
This is a list of sites using Daux.io:
* [Daux.io](https://dauxio.github.io/)
- With a custom theme:
* [Crafty](https://swissquote.github.io/crafty)
* [Pixolution flow](https://docs.pixolution.org)
* [Soisy](https://doc.soisy.it/)
* [Vulkan Tutorial](https://vulkan-tutorial.com)
* [3Q](https://docs.3q.video/)
- With the default Theme
* [Daux.io](https://daux.io/)
* [DoctrineWatcher](https://dsentker.github.io/WatcherDocumentation/)
* [jDrupal](http://jdrupal.easystreet3.com/8/docs/)
* [DrupalGap](http://docs.drupalgap.org/8/)
* [Invade & Annex 3 - An Arma 3 Co-operative Mission](http://ia3.ahoyworld.co.uk/)
* [Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation](http://mun.ee)
* [ICADMIN: An admin panel powered by CodeIgniter.](http://istocode.com/shared/ic-admin/)
* [Munee: Standalone PHP 5.3 Asset Optimisation & Manipulation](http://mun.ee)
* [Nuntius: A PHP framework for bots](https://roysegall.github.io/nuntius-bot/)
Do you use Daux.io? Send us a pull request or open an [issue](https://github.com/dauxio/daux.io/issues) and I will add you to the list.
@ -63,7 +69,7 @@ daux generate
You can then use the `daux` command line to generate your documentation.
If the command isn't found, ensure your `$PATH` contains `~/.composer/vendor/bin`
If the command isn't found, ensure your `$PATH` contains `~/.composer/vendor/bin` or `~/.config/composer/vendor/bin`.
#### Docker
@ -139,9 +145,9 @@ Now that you got the basics, you can also [see what you can configure](05_Config
## PHP Requirements
Daux.io is compatible with PHP 5.6 and up.
Daux.io is compatible with PHP 7.1.3 and up.
The reason is because some dependencies we have do not support php 5.5 anymore.
The reason is because some dependencies we have (mainly Symfony and Guzzle) do not support PHP 5.6 anymore.
### Extensions

View File

@ -2,9 +2,15 @@ Highlight.js highlights syntax in code examples on blogs, forums and in fact on
You can even use [Github Flavored Markdown](!Features/CommonMark_compliant)
We also use the [scrivo/highlight.php](https://github.com/scrivo/highlight.php) package to highlight on rendering when possible.
Highlight.js is a powerful but heavy library, since we don't know which languages you'll use we included all of them.
The good news is; if you use a fenced code block (` ``` `) with the language defined, the rendering is done on server side and entirely skips loading Highlight.js on the page. While still having the same end-result on your code.
**Python**
```python
@requires_authorization
def somefunc(param1='', param2=0):
r'''A docstring'''
@ -16,7 +22,7 @@ You can even use [Github Flavored Markdown](!Features/CommonMark_compliant)
>>> message = '''interpreter
... prompt'''
```
**Python's profiler output**

View File

@ -60,16 +60,6 @@ You can *optionally* specify the separator used for breadcrumbs.
}
```
## Code Floating
By default your code blocks will be floated to a column on the right side of your content.
To disable this feature, set the `float` property to `false`.
```json
{
"html": { "float": false }
}
```
## Date Modified
By default, daux.io will display the last modified time as reported by the system underneath the title for each document.
To disable this, change the option in your config.json to `false`.
@ -80,17 +70,6 @@ To disable this, change the option in your config.json to `false`.
}
```
If you want to use the last modified time you can set the [format](http://php.net/manual/function.date.php) with the `date_modified_format` option.
```json
{
"html": {
"date_modified": true,
"date_modified_format": "l, F j, Y g:i A"
}
}
```
## GitHub Repo
Add a 'Fork me on GitHub' ribbon.

View File

@ -16,8 +16,6 @@
"breadcrumb_separator": "Chevrons",
"toggle_code": true,
"date_modified": true,
"date_modified_format": "l, F j, Y g:i A",
"float": true,
"inherit_index": true,
"repo": "dauxio/daux.io",

View File

@ -28,12 +28,20 @@
"CodeBlocks_inline": "Inline",
"CodeBlocks_show": "Show Code Blocks",
"Search_placeholder": "Search...",
"Search_one_result": "1 result",
"Search_results": "!count results",
"Search_no_results": "Nothing found",
"Search_common_words_ignored": "Common words are largely ignored",
"Search_too_short": "Search too short",
"Search_one_character_or_more": "Should be one character or more",
"Search_should_be_x_or_more": "Should be !min characters or more",
"Link_previous": "Previous",
"Link_next": "Next",
"Edit_on": "Edit on :name:",
"View_on_github": "View On GitHub",
"View_documentation": "View Documentation",
"Table_of_contents": "Table of Contents"
"Table_of_contents": "Table of Contents",
"Toggle_navigation": "Toggle navigation"
},
"fr": {
"CodeBlocks_title": "Afficher le code",
@ -42,6 +50,13 @@
"CodeBlocks_inline": "A côté",
"CodeBlocks_show": "Afficher le code",
"Search_placeholder": "Rechercher...",
"Search_one_result": "1 résultat",
"Search_results": "!count résultats",
"Search_no_results": "Aucun résultat trouvé",
"Search_common_words_ignored": "Les mots communs sont ignorés",
"Search_too_short": "Critère de recherche trop court",
"Search_one_character_or_more": "Doit être un caractère ou plus",
"Search_should_be_x_or_more": "Doit être !min caractère ou plus",
"Link_previous": "Précédent",
"Link_next": "Suivant",
"Edit_on": "Editer sur :name:",
@ -56,12 +71,40 @@
"CodeBlocks_inline": "Linear",
"CodeBlocks_show": "Code-Blöcke anzeigen",
"Search_placeholder": "Suchen...",
"Search_one_result": "1 Ergebnis",
"Search_results": "!count Ergebnisse",
"Search_no_results": "Nichts gefunden",
"Search_common_words_ignored": "Allgemeine Wörter werden weitgehend ignoriert",
"Search_too_short": "Suche zu kurz",
"Search_one_character_or_more": "Sollte ein Zeichen oder mehr sein",
"Search_should_be_x_or_more": "Sollte !min Zeichen oder mehr sein",
"Link_previous": "Zurück",
"Link_next": "Weiter",
"Edit_on": "Bearbeiten bei :name:",
"View_on_github": "Bei GitHub anzeigen",
"View_documentation": "Dokumentation anzeigen",
"Table_of_contents": "Inhaltsverzeichnis"
},
"it": {
"CodeBlocks_title": "Blocchi di codice",
"CodeBlocks_hide": "No",
"CodeBlocks_below": "Sotto",
"CodeBlocks_inline": "In linea",
"CodeBlocks_show": "Mostra blocchi di codice",
"Search_one_result": "1 risultato",
"Search_results": "!count risultati",
"Search_no_results": "Nessun risultato trovato",
"Search_common_words_ignored": "Le parole comuni vengono per lo più ignorate",
"Search_too_short": "Ricerca troppo breve",
"Search_one_character_or_more": "Dovrebbe essere composto da uno o più caratteri",
"Search_should_be_x_or_more": "Dovrebbe essere composto da almeno !min caratteri",
"Search_placeholder": "Cerca...",
"Link_previous": "Pagina precedente",
"Link_next": "Pagina successiva",
"Edit_on": "Modifica su :name:",
"View_on_github": "Guarda su GitHub",
"View_documentation": "Leggi la documentazione",
"Table_of_contents": "Contenuti"
}
},
@ -77,8 +120,6 @@
"breadcrumb_separator": "Chevrons",
"toggle_code": true,
"date_modified": false,
"date_modified_format": "l, F j, Y g:i A",
"float": false,
"auto_landing": true,
"search": true,
"auto_toc": false,

View File

@ -31,6 +31,5 @@ class Application extends SymfonyApplication
$this->setVersion($version);
$this->setName($app_name);
$this->setDefaultCommand('generate');
}
}

View File

@ -19,7 +19,7 @@ trait RunAction
$padding = $width - $this->getLength($title) - 10;
try {
$response = $closure(function ($content) use (&$padding) {
$response = $closure(function ($content) use (&$padding, $verbose) {
$padding -= $this->getLength($content);
Daux::write($content, $verbose);
});

View File

@ -42,19 +42,11 @@ class Serve extends DauxCommand
putenv('DAUX_CONFIGURATION=' . $daux->getParams()->getConfigurationOverrideFile());
putenv('DAUX_EXTENSION=' . DAUX_EXTENSION);
$base = ProcessUtils::escapeArgument(__DIR__ . '/../../');
$binary = ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));
$base = escapeshellarg(__DIR__ . '/../../');
$binary = escapeshellarg((new PhpExecutableFinder)->find(false));
echo "Daux development server started on http://{$host}:{$port}/\n";
if (defined('HHVM_VERSION')) {
if (version_compare(HHVM_VERSION, '3.8.0') >= 0) {
passthru("{$binary} -m server -v Server.Type=proxygen -v Server.SourceRoot={$base}/ -v Server.IP={$host} -v Server.Port={$port} -v Server.DefaultDocument=server.php -v Server.ErrorDocument404=server.php");
} else {
throw new Exception("HHVM's built-in server requires HHVM >= 3.8.0.");
}
} else {
passthru("{$binary} -S {$host}:{$port} {$base}/index.php");
}
}
}

View File

@ -42,6 +42,7 @@ class ContentType implements \Todaymade\Daux\ContentTypes\ContentType
return $this->doConversion($raw);
}
// TODO :: add daux version to cache key
$cacheKey = $this->config->getCacheKey() . sha1($raw);
$payload = Cache::get($cacheKey);

View File

@ -109,18 +109,38 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
$urlAndHash = explode('#', $url);
$url = $urlAndHash[0];
$foundWithHash = false;
try {
$file = $this->resolveInternalFile($url);
$url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
} catch (LinkNotFoundException $e) {
// For some reason, the filename could contain a # and thus the link needs to resolve to that.
try {
if (strlen($urlAndHash[1] ?? "") > 0) {
$file = $this->resolveInternalFile($url . '#' . $urlAndHash[1]);
$url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
$foundWithHash = true;
}
} catch (LinkNotFoundException $e2) {
// If it's still not found here, we'll only
// report on the first error as the second
// one will tell the same.
}
if (!$foundWithHash) {
if ($this->daux->isStatic()) {
throw $e;
}
$element->setAttribute('class', 'Link--broken');
}
}
if (isset($urlAndHash[1])) {
if (!$foundWithHash && isset($urlAndHash[1])) {
$url .= '#' . $urlAndHash[1];
}

View File

@ -19,7 +19,7 @@ class TableOfContentsParser extends AbstractBlockParser
}
$previousState = $cursor->saveState();
$cursor->advanceToFirstNonSpace();
$cursor->advanceToNextNonSpaceOrNewline();
$fence = $cursor->match('/^\[TOC\]/');
if (is_null($fence)) {
$cursor->restoreState($previousState);

View File

@ -293,6 +293,20 @@ class Daux
return $class;
}
protected function findAlternatives($input, $words) {
$alternatives = [];
foreach ($words as $word) {
$lev = levenshtein($input, $word);
if ($lev <= \strlen($word) / 3) {
$alternatives[] = $word;
}
}
return $alternatives;
}
/**
* @return \Todaymade\Daux\Format\Base\Generator
*/
@ -307,7 +321,19 @@ class Daux
$format = $this->getParams()->getFormat();
if (!array_key_exists($format, $generators)) {
throw new \RuntimeException("The format '$format' doesn't exist, did you forget to set your processor ?");
$message = "The format '$format' doesn't exist, did you forget to set your processor ?";
$alternatives = $this->findAlternatives($format, array_keys($generators));
if (0 == \count($alternatives)) {
$message .= "\n\nAvailable formats are \n " . implode("\n ", array_keys($generators));
} elseif (1 == \count($alternatives)) {
$message .= "\n\nDid you mean this?\n " . implode("\n ", $alternatives);
} else {
$message .= "\n\nDid you mean one of these?\n " . implode("\n ", $alternatives);
}
throw new \RuntimeException($message);
}
$class = $generators[$format];

View File

@ -189,7 +189,7 @@ class DauxHelper
continue;
}
$node = urldecode($node);
$node = DauxHelper::slug(urldecode($node));
// if the node exists in the current request tree,
// change the $tree variable to reference the new
@ -241,18 +241,21 @@ class DauxHelper
*/
public static function slug($title)
{
// Convert to ASCII
foreach (static::charsArray() as $key => $value) {
$title = str_replace($value, $key, $title);
}
// Remove unsupported characters
$title = preg_replace('/[^\x20-\x7E]/u', '', $title);
$separator = '_';
// Convert all dashes into underscores
$title = preg_replace('![' . preg_quote('-') . ']+!u', $separator, $title);
// Remove all characters that are not the separator, letters, numbers, or whitespace.
$title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', $title);
// Remove all characters that are not valid in a URL:
// $-_.+!*'(), separator, letters, numbers, or whitespace.
$title = preg_replace('![^-' . preg_quote($separator) . '\!\'\(\),\.\+\*\$\pL\pN\s]+!u', '', $title);
// Replace all separator characters and whitespace by a single separator
$title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
@ -485,6 +488,11 @@ class DauxHelper
* @return false|null|string
*/
public static function findLocation($path, $basedir, $var, $type) {
// VFS, used only in tests
if (substr($path, 0, 6) == "vfs://") {
return $path;
}
// When running through `daux --serve` we set an environment variable to know where we started from
$env = getenv($var);
if ($env && DauxHelper::is($env, $type)) {

View File

@ -4,6 +4,7 @@ use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\FencedCode;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Xml;
class FencedCodeRenderer extends CodeRenderer
{
@ -58,7 +59,7 @@ class FencedCodeRenderer extends CodeRenderer
return false;
}
$language = $htmlRenderer->escape($infoWords[0], true);
$language = Xml::escape($infoWords[0], true);
if (array_key_exists($language, $this->known_conversions)) {
$language = $this->known_conversions[$language];

View File

@ -104,6 +104,15 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
$context = ['page' => $page, 'params' => $params];
return $this->templateRenderer->render($this->isLanding() ? 'theme::home' : 'theme::content', $context);
$template = "theme::content";
if ($this->isLanding()) {
$template = "theme::home";
}
if (array_key_exists('template', $page['attributes'])) {
$template = "theme::" . $page['attributes']['template'];
}
return $this->templateRenderer->render($template, $context);
}
}

View File

@ -9,6 +9,8 @@ class CommonMarkConverter extends \Todaymade\Daux\ContentTypes\Markdown\CommonMa
{
parent::extendEnvironment($environment, $config);
$environment->addBlockRenderer('FencedCode', new FencedCodeRenderer());
$environment->addDocumentProcessor(new TOC\Processor($config));
$environment->addBlockRenderer('Todaymade\Daux\ContentTypes\Markdown\TableOfContents', new TOC\Renderer($config));
}

View File

@ -0,0 +1,70 @@
<?php namespace Todaymade\Daux\Format\HTML\ContentTypes\Markdown;
use Highlight\Highlighter;
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\FencedCode;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Util\Xml;
class FencedCodeRenderer implements BlockRendererInterface
{
function __construct() {
$this->hl = new Highlighter();
}
/**
* @param AbstractBlock $block
* @param HtmlRendererInterface $htmlRenderer
* @param bool $inTightList
*
* @return HtmlElement|string
*/
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
if (!($block instanceof FencedCode)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$attrs = [];
foreach ($block->getData('attributes', []) as $key => $value) {
$attrs[$key] = Xml::escape($value);
}
$content = $block->getStringContent();
$language = $this->getLanguage($block->getInfoWords());
$highlighted = false;
if ($language) {
$attrs['class'] = isset($attrs['class']) ? $attrs['class'] . ' ' : '';
try {
$highlighted = $this->hl->highlight($language, $content);
$content = $highlighted->value;
$attrs['class'] .= 'hljs ' . $highlighted->language;
} catch (Exception $e) {
$attrs['class'] .= 'language-' . $language;
}
}
if (!$highlighted) {
$content = Xml::escape($content);
}
return new HtmlElement(
'pre',
[],
new HtmlElement('code', $attrs, $content)
);
}
public function getLanguage($infoWords)
{
if (count($infoWords) === 0 || strlen($infoWords[0]) === 0) {
return false;
}
return Xml::escape($infoWords[0], true);
}
}

View File

@ -254,8 +254,6 @@ class Processor implements DocumentProcessorInterface
$method->invoke($subnode, $firstClone);
}
$deepCopy = new DeepCopy();
return $deepCopy->copy($firstClone)->children();
return (new DeepCopy())->copy($firstClone)->children();
}
}

View File

@ -17,6 +17,6 @@ class Renderer implements BlockRendererInterface
$content = $htmlRenderer->renderBlocks($block->children());
return $this->config->templateRenderer
->getEngine($this->config)
->render('partials/table_of_contents', ['content' => $content]);
->render('theme::partials/table_of_contents', ['content' => $content]);
}
}

View File

@ -16,7 +16,7 @@ use Todaymade\Daux\Tree\Raw;
class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
{
use RunAction;
use RunAction, HTMLUtils;
/** @var Daux */
protected $daux;
@ -45,30 +45,6 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
];
}
protected function ensureEmptyDestination($destination)
{
if (is_dir($destination)) {
GeneratorHelper::rmdir($destination);
} else {
mkdir($destination);
}
}
/**
* Copy all files from $local to $destination
*
* @param string $destination
* @param string $local_base
*/
protected function copyThemes($destination, $local_base)
{
mkdir($destination . DIRECTORY_SEPARATOR . 'themes');
GeneratorHelper::copyRecursive(
$local_base,
$destination . DIRECTORY_SEPARATOR . 'themes'
);
}
public function generateAll(InputInterface $input, OutputInterface $output, $width)
{
$destination = $input->getOption('destination');
@ -96,13 +72,14 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
$this->generateRecursive($this->daux->tree, $destination, $params, $output, $width, $params['html']['search']);
if ($params['html']['search']) {
GeneratorHelper::copyRecursive(
$this->daux->local_base . DIRECTORY_SEPARATOR . 'tipuesearch' . DIRECTORY_SEPARATOR,
$destination . DIRECTORY_SEPARATOR . 'tipuesearch'
$this->daux->local_base . DIRECTORY_SEPARATOR . 'daux_libraries' . DIRECTORY_SEPARATOR,
$destination . DIRECTORY_SEPARATOR . 'daux_libraries'
);
if ($params['html']['search']) {
file_put_contents(
$destination . DIRECTORY_SEPARATOR . 'tipuesearch' . DIRECTORY_SEPARATOR . 'tipuesearch_content.json',
$destination . DIRECTORY_SEPARATOR . 'daux_search_index.json',
json_encode(['pages' => $this->indexed_pages])
);

View File

@ -0,0 +1,29 @@
<?php namespace Todaymade\Daux\Format\HTML;
use Todaymade\Daux\GeneratorHelper;
trait HTMLUtils {
public function ensureEmptyDestination($destination)
{
if (is_dir($destination)) {
GeneratorHelper::rmdir($destination);
} else {
mkdir($destination);
}
}
/**
* Copy all files from $local to $destination
*
* @param string $destination
* @param string $local_base
*/
public function copyThemes($destination, $local_base)
{
mkdir($destination . DIRECTORY_SEPARATOR . 'themes');
GeneratorHelper::copyRecursive(
$local_base,
$destination . DIRECTORY_SEPARATOR . 'themes'
);
}
}

View File

@ -1,4 +1,6 @@
<?php namespace Todaymade\Daux\Format\HTML;
<?php
namespace Todaymade\Daux\Format\HTML;
use League\Plates\Engine;
use Symfony\Component\Console\Output\OutputInterface;
@ -84,9 +86,18 @@ class Template
$engine->registerFunction('translate', function ($key) {
$language = $this->params['language'];
if (isset($this->engine->getData('page')['page'])) {
$page = $this->engine->getData('page');
if (!empty($page['page']['language'])) {
$language = $page['page']['language'];
}
}
if (array_key_exists($language, $this->params['strings'])) {
if (array_key_exists($key, $this->params['strings'][$language])) {
return $this->params['strings'][$language][$key];
}
}
if (array_key_exists($key, $this->params['strings']['en'])) {
return $this->params['strings']['en'][$key];
@ -122,9 +133,9 @@ class Template
$icon = '<i class="Nav__arrow">&nbsp;</i>';
if (array_key_exists('href', $entry)) {
$link = '<a href="' . $entry['href'] . '" class="folder">' . $icon . $entry['title'] . '</a>';
$link = '<a href="' . $entry['href'] . '" class="Nav__item__link">' . $icon . $entry['title'] . '</a>';
} else {
$link = '<a href="#" class="aj-nav folder">' . $icon . $entry['title'] . '</a>';
$link = '<a href="#" class="Nav__item__link Nav__item__link--nopage">' . $icon . $entry['title'] . '</a>';
}
$link .= $this->renderNavigation($entry['children']);

View File

@ -22,15 +22,9 @@ class Book
return '<style>' . file_get_contents('themes/daux_singlepage/css/main.min.css') . '</style>';
}
protected function getSectionId(Content $node)
protected function getPageUrl($page)
{
foreach ($this->pages as $id => $page) {
if ($page['page'] == $node) {
return $id;
}
}
throw new RuntimeException('Could not find the content page');
return "file_" . str_replace('/', '_', $page->getUrl());
}
protected function buildNavigation(Directory $tree)
@ -44,7 +38,7 @@ class Book
$nav[] = [
'title' => $node->getTitle(),
'href' => '#section_' . $this->getSectionId($node),
'href' => "#" . $this->getPageUrl($node),
];
} elseif ($node instanceof Directory) {
if (!$node->hasContent()) {
@ -55,7 +49,7 @@ class Book
$nav[] = [
'title' => $node->getTitle(),
'href' => '#section_' . $this->getSectionId($page_index),
'href' => "#" . $this->getPageUrl($page_index),
'children' => $this->buildNavigation($node),
];
}
@ -70,9 +64,9 @@ class Book
foreach ($entries as $entry) {
if (array_key_exists('children', $entry)) {
if (array_key_exists('href', $entry)) {
$link = '<a href="' . $entry['href'] . '" class="folder">' . $entry['title'] . '</a>';
$link = '<a href="' . $entry['href'] . '" class="Nav__item__link--nopage">' . $entry['title'] . '</a>';
} else {
$link = '<a href="#" class="aj-nav folder">' . $entry['title'] . '</a>';
$link = '<a href="#" class="Nav__item__link Nav__item__link--nopage">' . $entry['title'] . '</a>';
}
$link .= $this->renderNavigation($entry['children']);
@ -104,8 +98,8 @@ class Book
protected function generatePages()
{
$content = '';
foreach ($this->pages as $section => $page) {
$content .= '<a id="section_' . $section . '"></a>';
foreach ($this->pages as $page) {
$content .= '<a id="' . $this->getPageUrl($page['page']) . '"></a>';
$content .= '<h1>' . $page['page']->getTitle() . '</h1>';
$content .= '<section class="s-content">' . $page['content'] . '</section>';
$content .= '<div class="PageBreak">&nbsp;</div>';

View File

@ -0,0 +1,13 @@
<?php namespace Todaymade\Daux\Format\HTMLFile\ContentTypes\Markdown;
use League\CommonMark\Environment;
use Todaymade\Daux\Config;
class CommonMarkConverter extends \Todaymade\Daux\Format\HTML\ContentTypes\Markdown\CommonMarkConverter
{
protected function getLinkRenderer(Environment $environment)
{
var_dump(LinkRenderer::class);
return new LinkRenderer($environment->getConfig('daux'));
}
}

View File

@ -0,0 +1,12 @@
<?php namespace Todaymade\Daux\Format\HTMLFile\ContentTypes\Markdown;
use Todaymade\Daux\Config;
class ContentType extends \Todaymade\Daux\ContentTypes\Markdown\ContentType
{
public function __construct(Config $config)
{
$this->config = $config;
$this->converter = new CommonMarkConverter(['daux' => $config]);
}
}

View File

@ -0,0 +1,74 @@
<?php namespace Todaymade\Daux\Format\HTMLFile\ContentTypes\Markdown;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Link;
use Todaymade\Daux\Config;
use Todaymade\Daux\DauxHelper;
use Todaymade\Daux\Exception\LinkNotFoundException;
use Todaymade\Daux\Tree\Entry;
class LinkRenderer extends \Todaymade\Daux\ContentTypes\Markdown\LinkRenderer
{
/**
* @param AbstractInline|Link $inline
* @param ElementRendererInterface $htmlRenderer
* @return HtmlElement
* @throws LinkNotFoundException
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
// This can't be in the method type as
// the method is an abstract and should
// have the same interface
if (!$inline instanceof Link) {
throw new \RuntimeException(
'Wrong type passed to ' . __CLASS__ . '::' . __METHOD__ .
" the expected type was 'League\\CommonMark\\Inline\\Element\\Link' but '" .
get_class($inline) . "' was provided"
);
}
$element = parent::render($inline, $htmlRenderer);
$url = $inline->getUrl();
// empty urls and anchors should
// not go through the url resolver
if (!$this->isValidUrl($url)) {
return $element;
}
// Absolute urls, shouldn't either
if ($this->isExternalUrl($url)) {
$element->setAttribute('class', 'Link--external');
return $element;
}
// if there's a hash component in the url, we can directly use it as all pages are in the same file
$urlAndHash = explode('#', $url);
if (isset($urlAndHash[1])) {
$element->setAttribute('href', '#' . $urlAndHash[1]);
return $element;
}
try {
$file = $this->resolveInternalFile($url);
$url = $file->getUrl();
} catch (LinkNotFoundException $e) {
if ($this->daux->isStatic()) {
throw $e;
}
$element->setAttribute('class', 'Link--broken');
}
$url = str_replace('/', '_', $url);
$element->setAttribute('href', "#file_$url");
return $element;
}
}

View File

@ -5,11 +5,12 @@ use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Console\RunAction;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Format\HTML\Template;
use Todaymade\Daux\Format\HTML\ContentTypes\Markdown\ContentType;
use Todaymade\Daux\Format\HTML\HTMLUtils;
use Todaymade\Daux\Format\HTMLFile\ContentTypes\Markdown\ContentType;
class Generator implements \Todaymade\Daux\Format\Base\Generator
{
use RunAction;
use RunAction, HTMLUtils;
/** @var Daux */
protected $daux;
@ -36,52 +37,31 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
];
}
protected function initPDF()
{
// create new PDF document
$pdf = new Book(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$params = $this->daux->getParams();
// set document information
$pdf->SetCreator(PDF_CREATOR);
// set default header data
$pdf->SetHeaderData('', 0, $params['title'], $params['tagline']);
// set header and footer fonts
$pdf->setHeaderFont([PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN]);
$pdf->setFooterFont([PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA]);
// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set margins
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
// set auto page breaks
$pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// set font
$pdf->SetFont('helvetica', '', 10);
return $pdf;
}
/**
* {@inheritdoc}
*/
public function generateAll(InputInterface $input, OutputInterface $output, $width)
{
$params = $this->daux->getParams();
$destination = $input->getOption('destination');
$data = ['author' => $params['author'], 'title' => $params['title'], 'subject' => $params['tagline']];
$params = $this->daux->getParams();
if (is_null($destination)) {
$destination = $this->daux->local_base . DIRECTORY_SEPARATOR . 'static';
}
$this->runAction(
'Cleaning destination folder ...',
$width,
function() use ($destination, $params) {
$this->ensureEmptyDestination($destination);
}
);
$data = [
'author' => $params['author'],
'title' => $params['title'],
'subject' => $params['tagline']
];
$book = new Book($this->daux->tree, $data);

22
libs/FormatDate.php Normal file
View File

@ -0,0 +1,22 @@
<?php namespace Todaymade\Daux;
use IntlDateFormatter;
class FormatDate
{
public static function format($params, $date) {
$locale = $params['language'];
$datetype = IntlDateFormatter::LONG;
$timetype = IntlDateFormatter::SHORT;
$timezone = null;
if (!extension_loaded("intl")) {
$locale = 'en';
$timezone = 'GMT';
}
$formatter = new IntlDateFormatter($locale, $datetype, $timetype, $timezone);
return $formatter->format($date);
}
}

View File

@ -1,11 +1,12 @@
<?php namespace Todaymade\Daux\Server;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface as FileMimeTypeGuesserInterface;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
/**
* Guesses the mime type using the file's extension
*/
class ExtensionMimeTypeGuesser implements MimeTypeGuesserInterface
class ExtensionMimeTypeGuesser implements FileMimeTypeGuesserInterface, MimeTypeGuesserInterface
{
/**
* {@inheritdoc}
@ -22,4 +23,20 @@ class ExtensionMimeTypeGuesser implements MimeTypeGuesserInterface
return "application/javascript";
}
}
/**
* {@inheritdoc}
*/
public function isGuesserSupported(): bool
{
return true;
}
/**
* {@inheritdoc}
*/
public function guessMimeType(string $path): ?string
{
return $this->guess($path);
}
}

View File

@ -4,7 +4,7 @@ use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser;
use Symfony\Component\Mime\MimeTypes;
use Todaymade\Daux\Daux;
use Todaymade\Daux\DauxHelper;
use Todaymade\Daux\Exception;
@ -97,7 +97,8 @@ class Server
*/
public function createResponse(Page $page) {
MimeTypeGuesser::getInstance()->register(new ExtensionMimeTypeGuesser);
$mimeTypes = MimeTypes::getDefault();
$mimeTypes->registerGuesser(new ExtensionMimeTypeGuesser());
if ($page instanceof RawPage) {
return new BinaryFileResponse($page->getFile());
@ -142,7 +143,7 @@ class Server
{
$this->params = $this->getParams();
$request = substr($this->request->getRequestUri(), 1);
$request = substr($this->request->getRequestUri(), strlen($this->request->getBaseUrl()) + 1);
if (substr($request, 0, 7) == 'themes/') {
return $this->serveTheme(substr($request, 6));

View File

@ -75,7 +75,7 @@ class Builder
}
if ($file->isDir()) {
$title = static::removeSortingInformations($file->getFilename());
$title = DauxHelper::slug(static::removeSortingInformations($file->getFilename()));
$new = new Directory($node, $title, $file);
$new->setName(static::getName($file->getPathName()));
$new->setTitle(str_replace('_', ' ', static::removeSortingInformations($new->getName())));
@ -115,6 +115,7 @@ class Builder
}
$uri = static::removeSortingInformations($name);
$uri = DauxHelper::slug($uri);
if ($config->isStatic()) {
$uri .= '.html';
}

View File

@ -3,12 +3,17 @@
"version": "0.3.0",
"private": true,
"devDependencies": {
"@swissquote/crafty": "^1.0.1",
"@swissquote/crafty-preset-postcss": "^1.0.1",
"@swissquote/crafty-runner-gulp": "^1.0.1"
"@swissquote/crafty": "^1.8.0",
"@swissquote/crafty-preset-babel": "^1.8.0",
"@swissquote/crafty-preset-postcss": "^1.8.0",
"@swissquote/crafty-runner-gulp": "^1.8.0",
"@swissquote/crafty-runner-rollup": "^1.8.0",
"flexsearch": "^0.6.30",
"preact": "^10.0.0-rc.3"
},
"scripts": {
"build": "crafty run",
"watch": "crafty watch"
"watch": "crafty watch",
"lint:css": "crafty cssLint --fix --preset recommended themes/daux_singlepage/scss/*.scss themes/daux/scss/*.scss"
}
}

View File

@ -8,7 +8,6 @@
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
>
<testsuites>
<testsuite name="Daux Test Suite">

View File

@ -0,0 +1,483 @@
/* ============================================================================
Base tags
============================================================================ */
a {
text-decoration: none;
color: var(--link-color);
&.Link--external:after {
content: " "
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=);
}
&.Link--broken {
color: red;
}
}
p {
margin: 0 0 1em;
}
hr {
clear: both;
margin: 1em 0;
border: 0;
border-top: 1px solid #ddd;
}
/* ============================================================================
Components
============================================================================ */
.Button {
display: inline-block;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214
border: 1px solid transparent;
white-space: nowrap;
border-radius: 4px;
margin-bottom: 0;
&--small {
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
&--default {
color: #333;
background-color: #fff;
border-color: #ccc;
&.Button--active {
color: #333;
background-color: #e6e6e6;
border-color: #adadad;
}
}
}
.Brand {
display: block;
background-color: var(--brand-background);
padding: 0.75em 0.6em;
font-size: var(--type-size-4);
text-shadow: none;
font-family: var(--font-family-heading);
font-weight: 700;
color: var(--brand-color);
}
.Navbar {
height: 50px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.25);
background-color: var(--homepage-navbar-background);
margin-bottom: 0;
.Brand {
float: left;
line-height: 20px;
height: 50px;
}
}
.CodeToggler {
padding: 0 20px;
&__text {
font-size: 12px;
line-height: 1.5;
padding: 6px 10px 6px 0;
display: inline-block;
vertical-align: middle;
}
}
/* stylelint-disable-next-line selector-class-pattern */
.no-js .CodeToggler {
display: none;
}
// Sidebar navigation
.Nav {
margin: 0;
padding: 0;
&__arrow {
display: inline-block;
position: relative;
width: 16px;
margin-left: -16px;
&:before {
position: absolute;
display: block;
content: "";
margin: -0.25em 0 0 -0.4em;
left: 50%;
top: 50%;
width: 0.5em;
height: 0.5em;
border-right: 0.15em solid var(--sidebar-link-arrow-color);
border-top: 0.15em solid var(--sidebar-link-arrow-color);
transform: rotate(45deg);
transition-duration: 0.3s;
}
}
&__item {
display: block;
a {
display: block;
margin: 0;
padding: 6px 15px 6px 20px;
font-family: var(--font-family-heading);
font-weight: 400;
color: var(--sidebar-link-color);
text-shadow: none;
}
a:hover {
color: var(--sidebar-link-color);
text-shadow: none;
background-color: var(--sidebar-link-hover-background);
}
}
}
.Nav .Nav {
margin-left: 15px;
/* stylelint-disable-next-line selector-class-pattern */
html:not(.no-js) & {
height: 0;
transition: height 400ms ease-in-out;
overflow: hidden;
}
.Nav__item a {
margin: 0;
margin-left: -15px;
padding: 3px 30px;
font-family: var(--font-family-text);
color: var(--sidebar-link-secondary-color);
opacity: 0.7;
&:hover {
opacity: 1;
}
}
.Nav__item--active a {
color: var(--sidebar-link-color);
}
}
.Nav__item {
&--open,
&--active {
> a {
background-color: var(--sidebar-link-active-background);
}
}
&--open {
> a > .Nav__arrow:before {
margin-left: -0.25em;
transform: rotate(135deg);
}
}
}
.Page__header {
margin: 0 0 10px;
padding: 0;
border-bottom: 1px solid #eee;
@include clearfix();
h1 {
margin: 0;
padding: 0;
line-height: 57px;
}
&--separator {
height: 0.6em;
}
a {
text-decoration: none;
}
.ModifiedDate {
float: left;
font-size: 10px;
color: gray;
}
.EditOn {
float: right;
font-size: 10px;
color: gray;
}
}
.Links {
padding: 0 20px;
a {
font-family: var(--font-family-heading);
font-weight: 400;
color: var(--sidebar-link-color);
line-height: 2em;
}
}
.Twitter {
padding: 0 20px;
font: normal normal normal 11px/18px "Helvetica Neue", Arial, sans-serif;
&__button {
text-decoration: none;
display: inline-block;
vertical-align: top;
zoom: 1;
position: relative;
height: 20px;
box-sizing: border-box;
padding: 1px 8px 1px 6px;
background-color: #1b95e0;
color: #fff;
border-radius: 3px;
font-weight: 500;
cursor: pointer;
.Twitter__button__label {
display: inline-block;
vertical-align: top;
zoom: 1;
margin-left: 3px;
white-space: nowrap;
}
svg {
position: relative;
top: 2px;
display: inline-block;
width: 14px;
height: 14px;
}
}
}
.PoweredBy {
padding: 0 20px 1rem 20px;
font-size: var(--type-size-6);
}
.Search {
position: relative;
&__field {
display: block;
width: 100%;
height: 34px;
padding: 6px 30px 6px 20px;
color: var(--search-field-color);
border-width: 0 0 1px;
border-bottom: 1px solid var(--search-field-border-color);
background: var(--search-field-background);
transition: border-color ease-in-out 0.15s;
&:focus {
border-color: var(--search-field-hover-border-color);
outline: 0;
}
}
&__icon {
position: absolute;
right: 9px;
top: 9px;
width: 16px;
height: 16px;
}
}
.Navbar .Search {
float: right;
margin: 8px 20px;
&__field {
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
border-width: 0;
border-radius: 4px;
padding-left: 10px;
}
}
.TableOfContentsContainer {
float: right;
min-width: 300px;
max-width: 25%;
padding-left: 1em;
&__title {
margin-bottom: 0 !important;
}
&__content {
border: 1px solid #efefef;
border-width: 4px 2px 2px 6px;
}
&__content > .TableOfContents > li + li {
border-top: 1px solid #ddd;
}
}
ul.TableOfContents {
font-size: 1rem;
padding-left: 0;
margin: 0;
list-style-type: none;
p {
margin-bottom: 0;
}
a {
text-decoration: none;
display: block;
padding: 0.2em 0 0.2em 0.75em;
}
.TableOfContents {
padding-left: 0.75em;
}
}
.Pager {
padding-left: 0;
margin: 1em 0;
list-style: none;
text-align: center;
clear: both;
@include clearfix();
li {
display: inline;
> a {
display: inline-block;
padding: 5px 14px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 15px;
}
> a:hover,
> a:focus {
text-decoration: none;
background-color: #eee;
}
}
&--next > a {
float: right;
}
&--prev > a {
float: left;
}
}
.Checkbox {
position: relative;
display: block;
padding-left: 30px;
cursor: pointer;
input {
position: absolute;
z-index: -1;
opacity: 0;
}
}
.Checkbox__indicator {
position: absolute;
top: 50%;
left: 0;
width: 20px;
height: 20px;
margin-top: -10px;
background: var(--checkbox-background);
/* Check mark */
&:after {
position: absolute;
display: none;
content: "";
}
/* Hover and focus states */
.Checkbox:hover input ~ &,
.Checkbox input:focus ~ & {
background: var(--checkbox-hover-background);
}
/* Checked state */
.Checkbox input:checked ~ & {
background: var(--checkbox-checked-background);
/* Show check mark */
&:after {
display: block;
}
}
/* Hover state whilst checked */
.Checkbox:hover input:not([disabled]):checked ~ &,
.Checkbox input:checked:focus ~ & {
background: var(--checkbox-checked-hover-background);
}
/* Disabled state */
.Checkbox input:disabled ~ & {
pointer-events: none;
opacity: 0.6;
background: var(--checkbox-disabled-background);
}
/* Checkbox tick */
.Checkbox &:after {
top: 4px;
left: 8px;
width: 5px;
height: 10px;
transform: rotate(45deg);
border: solid var(--checkbox-tick-color);
border-width: 0 2px 2px 0;
}
/* Disabled tick colour */
.Checkbox input:disabled ~ &:after {
border-color: var(--checkbox-disabled-tick-color);
}
}
.Hidden {
display: none;
}

View File

@ -0,0 +1,56 @@
:root {
--font-family-text: -apple-system, ".SFNSText-Regular", "San Francisco",
"Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", Arial,
sans-serif;
--font-family-monospace: Monaco, Menlo, Consolas, "Lucida Console",
"Courier New", monospace;
--font-family-heading: "Roboto Slab", var(--font-family-text);
}
/*! Generated by Font Squirrel (https://www.fontsquirrel.com) */
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 300;
font-display: fallback;
src: url("../fonts/robotoslab-light.eot");
src: url("../fonts/robotoslab-light.eot?#iefix") format("embedded-opentype"),
url("../fonts/robotoslab-light.woff2") format("woff2"),
url("../fonts/robotoslab-light.woff") format("woff"),
url("../fonts/robotoslab-light.ttf") format("truetype"),
url("../fonts/robotoslab-light.svg#roboto_slablight") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url("../fonts/robotoslab-regular.eot");
src: url("../fonts/robotoslab-regular.eot?#iefix")
format("embedded-opentype"),
url("../fonts/robotoslab-regular.woff2") format("woff2"),
url("../fonts/robotoslab-regular.woff") format("woff"),
url("../fonts/robotoslab-regular.ttf") format("truetype"),
url("../fonts/robotoslab-regular.svg#roboto_slabregular") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url("../fonts/robotoslab-bold.eot");
src: url("../fonts/robotoslab-bold.eot?#iefix") format("embedded-opentype"),
url("../fonts/robotoslab-bold.woff2") format("woff2"),
url("../fonts/robotoslab-bold.woff") format("woff"),
url("../fonts/robotoslab-bold.ttf") format("truetype"),
url("../fonts/robotoslab-bold.svg#roboto_slabbold") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}

View File

@ -0,0 +1,226 @@
/* ============================================================================
Homepage
============================================================================ */
.Container {
margin-right: auto;
margin-left: auto;
&--inner {
width: 80%;
margin: 0 auto;
}
}
@media (min-width: 1200px) {
.Container {
width: 1170px;
}
}
@media (min-width: 992px) {
.Container {
width: 970px;
}
}
@media (min-width: 769px) {
.Container {
width: 750px;
}
}
.Homepage {
padding-top: 60px !important;
background-color: var(--homepage-hero-background);
border-radius: 0;
border: none;
color: var(--homepage-hero-color);
overflow: hidden;
padding-bottom: 0;
margin-bottom: 0;
@include kill-box-shadow;
}
.HomepageTitle {
h2 {
width: 80%;
font-size: 30px;
margin: 20px auto;
text-align: center;
}
}
.HomepageImage {
img {
display: block;
max-width: 80%;
margin: 0 auto;
height: auto;
}
}
.HomepageButtons {
padding: 20px 0;
background-color: var(--hero-button-block-background);
text-align: center;
@include clearfix;
.Button--hero {
padding: 20px 30px;
border-radius: 0;
text-shadow: none;
opacity: 0.8;
margin: 0 10px;
text-transform: uppercase;
border: 5px solid var(--hero-button-border-color);
font-family: var(--font-family-heading);
font-weight: 700;
@include kill-background-image;
@include kill-box-shadow;
@media (max-width: 768px) {
display: block;
margin-bottom: 10px;
}
&:hover {
opacity: 1;
}
&.Button--secondary {
background-color: var(--hero-button-secondary-background);
color: var(--hero-button-secondary-color);
}
&.Button--primary {
background-color: var(--hero-buttom-primary-background);
color: var(--hero-button-primary-color);
}
}
}
.HomepageContent {
background-color: white;
padding: 40px 0;
ul,
ol {
li {
list-style: none;
margin-bottom: 0.5em;
position: relative;
}
li:before {
position: absolute;
top: 50%;
left: -1.5em;
content: "";
width: 0;
height: 0;
border: 0.5em solid transparent;
border-left: 0.5em solid var(--homepage-bullet-color);
float: left;
display: block;
margin-top: -0.5em;
}
}
.HeroText {
font-family: var(--font-family-heading);
font-weight: 300;
font-size: 16px;
margin-bottom: 20px;
line-height: 1.4;
}
@media (min-width: 769px) {
padding: 40px 20px;
.HeroText {
font-size: 21px;
}
.Row {
margin: 0 -15px;
}
.Row__third,
.Row__half,
.Row__quarter {
float: left;
position: relative;
min-height: 1px;
padding-left: 15px;
padding-right: 15px;
}
.Row__third {
width: 33.333333%;
}
.Row__half {
width: 50%;
}
.Row__quarter {
width: 25%;
}
}
}
.HomepageFooter {
background-color: var(--homepage-footer-background);
color: var(--homepage-footer-color);
border: none;
@include kill-box-shadow;
@include clearfix;
@media (max-width: 768px) {
padding: 0 20px;
text-align: center;
.HomepageFooter__links {
padding-left: 0;
list-style-type: none;
}
}
@media (min-width: 769px) {
.HomepageFooter__links {
float: left;
}
.HomepageFooter__twitter {
float: right;
}
}
&__links {
margin: 40px 0;
li a {
line-height: 32px;
font-size: 16px;
font-family: var(--font-family-heading);
font-weight: 700;
}
li a:hover {
text-decoration: underline;
}
}
&__twitter {
margin: 40px 0;
}
.Twitter__button {
margin-bottom: 20px;
}
}

View File

@ -0,0 +1,36 @@
/* ============================================================================
Mixins
============================================================================ */
@mixin kill-background-image {
background-image: none;
filter: none;
}
@mixin kill-box-shadow {
box-shadow: none;
}
// Clearfix
//
// For modern browsers
// 1. The space content is one way to avoid an Opera bug when the
// contenteditable attribute is included anywhere else in the document.
// Otherwise it causes space to appear at the top and bottom of elements
// that are clearfixed.
// 2. The use of `table` rather than `block` is only necessary if using
// `:before` to contain the top-margins of child elements.
//
// Source: http://nicolasgallagher.com/micro-clearfix-hack/
@mixin clearfix {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}

View File

@ -0,0 +1,86 @@
* {
text-shadow: none !important;
color: #000 !important; // Black prints faster: h5bp.com/s
background: transparent !important;
box-shadow: none !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid;
page-break-before: auto;
}
pre,
blockquote {
border: 1px solid #999;
font-style: italic;
page-break-inside: avoid;
}
img {
page-break-inside: avoid;
border: 0; /* Some browsers like to show a border around images. Switch it off */
}
a,
a:visited {
text-decoration: underline;
}
abbr[title]:after {
content: " (" attr(title) ")";
}
q {
quotes: none;
&:before {
content: "";
}
&:after {
content: " (" attr(cite) ")";
}
}
.PageBreak {
display: block;
page-break-before: always;
}
.NoPrint {
display: none;
}
/* Hide the navigation */
aside {
display: none;
}
.Pager {
display: none;
}
.Columns__right {
width: 100% !important;
}
.s-content a:after {
content: " (" attr(href) ")";
font-size: 80%;
word-wrap: break-word; /* break long urls that donìt fit the page width */
}
/* Anchors don't need that */
.s-content a[href^="#"]:after {
content: "";
}
h1 a[href]:after {
font-size: 50%;
}

View File

@ -0,0 +1,150 @@
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
/* ============================================================================
Docs Body & Page Structure
============================================================================ */
html {
font-size: 14px;
@media (--viewport-large) {
font-size: 16px;
}
}
html,
body {
height: 100%;
background-color: #fff;
color: var(--text);
}
.Columns {
&__left {
background-color: var(--sidebar-background);
}
&__right {
&__content {
padding: 10px;
background-color: #fff;
}
}
}
@media (max-width: 768px) {
// mobile friendly sub-nav
/* stylelint-disable-next-line selector-class-pattern */
html:not(.no-js) .Collapsible__content {
height: 0;
overflow: hidden;
transition: height 400ms ease-in-out;
}
}
.Collapsible__trigger {
margin: 12px;
padding: 7px 10px;
background-color: transparent;
border: none;
float: right;
@include kill-background-image;
@include kill-box-shadow;
&__bar {
display: block;
width: 18px;
height: 2px;
margin-top: 2px;
margin-bottom: 3px;
background-color: var(--sidebar-collapsible--hamburger-color);
}
&:hover {
background-color: var(
--sidebar-collapsible--hamburger-hover-background
);
@include kill-box-shadow;
.Collapsible__trigger__bar {
background-color: var(--sidebar-collapsible--hamburger-hover-color);
}
}
}
@media screen and (min-width: 769px) {
body {
//Needed only for floating code blocks
background-color: var(--content-floating-blocks-background);
}
.Navbar {
position: fixed;
z-index: 1030;
width: 100%;
}
.Collapsible {
&__trigger {
display: none !important;
}
&__content {
display: block !important;
}
}
.Columns {
height: 100%;
&:after,
&:before {
content: " ";
display: table;
}
&:after {
clear: both;
}
&__left,
&__right {
position: relative;
min-height: 1px;
float: left;
overflow: auto;
height: 100%;
}
&__left {
width: 25%;
border-right: 1px solid var(--sidebar-border);
overflow-x: hidden;
}
&__right {
width: 75%;
&__content {
padding: 0 20px 20px;
min-height: 100%;
}
}
}
}
.Page {
// 860 == screen-width of 1200 - sidebar - margin
max-width: 860px;
}

View File

@ -0,0 +1,254 @@
/* ============================================================================
Base CSS
============================================================================ */
body {
line-height: 1.5;
font-family: var(--font-family-text);
font-feature-settings: "kern" 1;
font-kerning: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-family-heading);
font-weight: 300;
}
.s-content {
h1,
h2,
h3,
h4,
h5,
h6 {
cursor: text;
line-height: 1.4em;
margin: 2em 0 0.5em;
tt,
code {
font-size: inherit;
}
i {
font-size: 0.7em;
}
p {
margin-top: 0;
}
}
h1 {
margin-top: 0;
font-size: var(--type-size-3);
}
h2 {
font-size: var(--type-size-4);
}
h3 {
font-size: var(--type-size-5);
}
h4 {
font-size: var(--type-size-6);
}
h5 {
font-size: var(--type-size-6);
}
h6 {
font-size: var(--type-size-6);
}
a {
text-decoration: underline;
}
small {
font-size: var(--type-size-6);
}
p {
margin-bottom: 1.3em;
}
ul,
ol {
padding-left: 2em;
}
ul p {
margin: 0;
}
ul ul {
margin: 0;
}
dl {
padding: 0;
dt {
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dt:first-child {
padding: 0;
}
dd {
margin: 0 0 15px;
padding: 0 15px;
}
}
blockquote {
margin: 0.75em 2em;
padding: 0.5em 1em;
font-style: italic;
border-left: 0.25em solid var(--blockquote-border-color);
cite {
font-style: italic;
}
cite:before {
content: "\2014";
padding-right: 0.5em;
}
}
table {
width: 100%;
padding: 0;
margin-bottom: 1em;
border-collapse: collapse;
font-size: var(--type-size-6);
+ table {
margin-top: 1em;
}
tr {
border-top: 1px solid #eee;
background-color: white;
margin: 0;
padding: 0;
}
tr:nth-child(2n) {
background-color: var(--lightest-gray);
}
th {
font-weight: bold;
border: 1px solid var(--light-gray);
background: var(--lighter-gray);
margin: 0;
padding: 0.5em;
}
td {
border: 1px solid var(--lighter-gray);
margin: 0;
padding: 0.5em;
}
}
ul,
ol,
blockquote,
dl dt,
dl dd,
table th,
table td {
> :first-child {
margin-top: 0;
}
> :last-child {
margin-bottom: 0;
}
}
img {
max-width: 100%;
display: block;
margin: 0 auto;
}
code {
font-family: var(--font-family-monospace);
padding-top: 0.1rem;
padding-bottom: 0.1rem;
background: var(--code-tag-background-color);
border: 1px solid var(--light-gray);
border-radius: var(--code-tag-border-radius);
box-shadow: var(--code-tag-box-shadow);
&:before,
&:after {
letter-spacing: -0.2em;
content: "\00a0"; /* non-breaking space*/
}
}
pre {
background: #f5f2f0;
color: #333;
line-height: 1.5em;
overflow: auto;
border: none;
border-radius: 0;
padding: 0.75em 20px;
margin: 0 -20px 20px -20px;
code {
margin: 0;
padding: 0;
white-space: pre;
box-shadow: none;
}
code:before,
code:after {
display: none;
}
code,
tt {
background-color: transparent;
border: none;
}
}
u,
ins {
text-decoration: none;
border-bottom: 1px solid var(--text);
a {
color: inherit;
}
}
del a {
color: inherit;
}
}

View File

@ -0,0 +1,89 @@
:root {
// Gray Scale
--gray: #7a8288;
--dark-gray: color(var(--gray) blend(#000 40%));
//--darker-gray: color(var(--gray) blend(#000 60%));
--light-gray: color(var(--gray) blend(#fff 50%));
--lighter-gray: color(var(--gray) blend(#fff 70%));
--lightest-gray: color(var(--gray) blend(#fff 90%));
// Type Scale
--type-size-1: 2.441rem; // ~39.056px
--type-size-2: 1.953rem; // ~31.248px
--type-size-3: 1.563rem; // ~25.008px
--type-size-4: 1.25rem; // ~20px
--type-size-5: 1rem; // ~16px
--type-size-6: 0.75rem; // ~12px
--dark: #3f4657;
--light: #82becd;
--text: #222;
--link-color: var(--light);
--brand-color: var(--light);
--brand-background: var(--dark);
// Sidebar
--sidebar-border: #e7e7e9;
--sidebar-background: #f7f7f7;
// Sidebar links
--sidebar-link-color: var(--dark);
--sidebar-link-active-background: #c5c5cb;
--sidebar-link-hover-background: var(--sidebar-link-active-background);
--sidebar-link-arrow-color: var(--dark);
--sidebar-link-secondary-color: var(--text);
// Sidebar Checkbox
--checkbox-background: #e6e6e6;
--checkbox-hover-background: #ccc;
--checkbox-checked-background: var(--dark);
--checkbox-checked-hover-background: var(--light);
--checkbox-tick-color: #fff;
--checkbox-disabled-background: #e6e6e6;
--checkbox-disabled-tick-color: #7b7b7b;
// Sidebar search field
--search-field-color: #555;
--search-field-border-color: #ccc;
--search-field-background: #fff;
--search-field-hover-border-color: var(--light);
// Sidebar hamburger
--sidebar-collapsible--hamburger-color: var(--light);
--sidebar-collapsible--hamburger-hover-color: var(--dark);
--sidebar-collapsible--hamburger-hover-background: var(--light);
// Homepage
--homepage-navbar-background: var(--dark);
--homepage-hero-background: var(--light);
--homepage-hero-color: var(--dark);
--homepage-bullet-color: var(--light);
--homepage-footer-color: var(--light);
--homepage-footer-background: var(--dark);
// Homepage Hero Buttons
--hero-button-block-background: var(--sidebar-link-active-background);
--hero-button-border-color: var(--dark);
--hero-button-primary-color: var(--sidebar-background);
--hero-buttom-primary-background: var(--dark);
--hero-button-secondary-color: var(--dark);
--hero-button-secondary-background: var(--sidebar-link-active-background);
--content-floating-blocks-background: var(--light);
--code-tag-color: var(--dark);
--code-tag-background-color: #fafafa;
--code-tag-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.125);
--code-tag-border-radius: 4px;
--blockquote-border-color: var(--dark);
}
/*
* Breakpoints
* ===================================================================== */
@custom-media --viewport-small (width < 850px);
@custom-media --viewport-large (width >= 850px);

View File

@ -0,0 +1,9 @@
@import "theme.scss";
//Daux.io Blue
:root {
--sidebar-background: #f7f7f7;
--sidebar-link-active-background: #c5c5cb;
--dark: #3f4657;
--light: #82becd;
}

View File

@ -0,0 +1,9 @@
@import "theme.scss";
//Daux.io Green
:root {
--sidebar-background: #f5f5f6;
--sidebar-link-active-background: #a0d55d;
--dark: #000;
--light: #8acc37;
}

View File

@ -0,0 +1,9 @@
@import "theme.scss";
//Daux.io Navy
:root {
--sidebar-background: #f5f5f6;
--sidebar-link-active-background: #c5c5cb;
--dark: #13132a;
--light: #7795b4;
}

View File

@ -0,0 +1,9 @@
@import "theme.scss";
// Daux.io Red
:root {
--sidebar-background: #f7f7f7;
--sidebar-link-active-background: #eee;
--dark: #c64641;
--light: #ecb5a1;
}

View File

@ -0,0 +1,22 @@
/*!
* DAUX.IO
* https://dauxio.github.io/
* MIT License
*/
// Daux Style
@import "vendor/normalize.scss";
@import "_fonts.scss";
@import "_variables.scss";
@import "_mixins.scss";
// Layout
@import "_structure.scss";
// Content presentation
@import "_typography.scss";
@import "_components.scss";
@import "_homepage.scss";
@import "vendor/highlight.scss";
@import "_print.scss" print;

View File

@ -0,0 +1,79 @@
/**
* GitHub Gist Theme
* Author : Anthony Attard - https://github.com/AnthonyAttard
* Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro
*/
.hljs {
display: block;
//background: white;
//padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #d73a49;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #6f42c1;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
.hljs-number {
color: #005cc5;
}
.hljs-string {
color: #032f62;
}

419
src/css/theme_daux/vendor/normalize.scss vendored Normal file
View File

@ -0,0 +1,419 @@
/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Change the default font family in all browsers (opinionated).
* 2. Prevent adjustments of font size after orientation changes in IE and iOS.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
* 2. Add the correct display in IE.
*/
article,
aside,
details, /* 1 */
figcaption,
figure,
footer,
header,
main, /* 2 */
menu,
nav,
section,
summary { /* 1 */
display: block;
}
/**
* Add the correct display in IE 9-.
*/
audio,
canvas,
progress,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Add the correct display in IE 10-.
* 1. Add the correct display in IE.
*/
template, /* 1 */
[hidden] {
display: none;
}
/* Links
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* Remove the outline on focused links when they are also active or hovered
* in all browsers (opinionated).
*/
a:active,
a:hover {
outline-width: 0;
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the bottom border in Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/* Forms
========================================================================== */
/**
* 1. Change font properties to `inherit` in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
select,
textarea {
font: inherit; /* 1 */
margin: 0; /* 2 */
}
/**
* Restore the font weight unset by the previous rule.
*/
optgroup {
font-weight: bold;
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Change the border, margin, and padding in all browsers (opinionated).
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on OS X.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Correct the text style of placeholders in Chrome, Edge, and Safari.
*/
::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}

View File

@ -0,0 +1,56 @@
:root {
--font-family-text: -apple-system, ".SFNSText-Regular", "San Francisco",
"Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", Arial,
sans-serif;
--font-family-monospace: Monaco, Menlo, Consolas, "Lucida Console",
"Courier New", monospace;
--font-family-heading: "Roboto Slab", var(--font-family-text);
}
/*! Generated by Font Squirrel (https://www.fontsquirrel.com) */
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 300;
font-display: fallback;
src: url("../fonts/robotoslab-light.eot");
src: url("../fonts/robotoslab-light.eot?#iefix") format("embedded-opentype"),
url("../fonts/robotoslab-light.woff2") format("woff2"),
url("../fonts/robotoslab-light.woff") format("woff"),
url("../fonts/robotoslab-light.ttf") format("truetype"),
url("../fonts/robotoslab-light.svg#roboto_slablight") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 400;
font-display: fallback;
src: url("../fonts/robotoslab-regular.eot");
src: url("../fonts/robotoslab-regular.eot?#iefix")
format("embedded-opentype"),
url("../fonts/robotoslab-regular.woff2") format("woff2"),
url("../fonts/robotoslab-regular.woff") format("woff"),
url("../fonts/robotoslab-regular.ttf") format("truetype"),
url("../fonts/robotoslab-regular.svg#roboto_slabregular") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}
@font-face {
font-family: "Roboto Slab";
font-style: normal;
font-weight: 700;
font-display: fallback;
src: url("../fonts/robotoslab-bold.eot");
src: url("../fonts/robotoslab-bold.eot?#iefix") format("embedded-opentype"),
url("../fonts/robotoslab-bold.woff2") format("woff2"),
url("../fonts/robotoslab-bold.woff") format("woff"),
url("../fonts/robotoslab-bold.ttf") format("truetype"),
url("../fonts/robotoslab-bold.svg#roboto_slabbold") format("svg");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
}

View File

@ -0,0 +1,67 @@
* {
text-shadow: none !important;
color: #000 !important; // Black prints faster: h5bp.com/s
background: transparent !important;
box-shadow: none !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid;
page-break-before: auto;
}
pre,
blockquote {
border: 1px solid #999;
font-style: italic;
page-break-inside: avoid;
}
img {
page-break-inside: avoid;
border: 0; /* Some browsers like to show a border around images. Switch it off */
}
a,
a:visited {
text-decoration: underline;
}
abbr[title]:after {
content: " (" attr(title) ")";
}
q {
quotes: none;
&:before {
content: "";
}
&:after {
content: " (" attr(cite) ")";
}
}
.PageBreak {
display: block;
page-break-before: always;
}
.NoPrint {
display: none;
}
/* Hide the navigation */
aside {
display: none;
}
a[href]:after {
content: " (" attr(href) ")";
}

View File

@ -0,0 +1,221 @@
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-family-heading);
font-weight: 300;
}
.s-content {
padding: 15px 25px 25px;
background-color: white;
body {
font-size: 15px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 300;
-webkit-font-smoothing: antialiased;
cursor: text;
line-height: 1.4em;
margin-top: 0.3em;
margin-bottom: 0.3em;
tt,
code {
font-size: inherit;
}
i {
font-size: 0.7em;
}
p {
margin-top: 0;
}
}
h1 {
// 40px
font-size: 2.6666666667em;
color: black;
}
h2 {
// 30px
font-size: 2em;
border-bottom: 1px solid #eee;
color: black;
}
h3 {
// 26px
font-size: 1.7333333333em;
}
h4 {
// 22px
font-size: 1.4666666667em;
}
h5 {
// 18px
font-size: 1.2em;
}
h6 {
// 16px
font-size: 1.0666666667em;
color: #555;
}
a {
text-decoration: underline;
}
p {
// 15px
line-height: 1.8em;
margin-bottom: 20px;
}
ul,
ol {
padding-left: 30px;
}
ul p {
margin: 0;
}
ul ul {
margin: 0;
}
dl {
padding: 0;
dt {
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dt:first-child {
padding: 0;
}
dd {
margin: 0 0 15px;
padding: 0 15px;
}
}
blockquote {
font-size: 1.2em;
border-left: 4px solid #ddd;
padding: 7px 15px;
color: #666;
p {
font-size: inherit;
}
}
table {
width: 100%;
padding: 0;
border-collapse: collapse;
tr {
border-top: 1px solid #eee;
background-color: white;
margin: 0;
padding: 0;
}
tr:nth-child(2n) {
background-color: #f8f8f8;
}
th {
font-weight: bold;
border: 1px solid #eee;
background: #eee;
margin: 0;
padding: 6px 13px;
}
td {
border: 1px solid #eee;
margin: 0;
padding: 6px 13px;
}
}
ul,
ol,
blockquote,
dl dt,
dl dd,
table th,
table td {
> :first-child {
margin-top: 0;
}
> :last-child {
margin-bottom: 0;
}
}
img {
max-width: 100%;
display: block;
margin: 0 auto;
}
code {
font-family: var(--font-family-monospace);
}
code,
tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
pre {
background: #f5f2f0;
color: #333;
line-height: 1.5em;
overflow: auto;
padding: 20px;
margin: 0 -20px 20px -20px;
code {
margin: 0;
padding: 0;
white-space: pre;
}
code,
tt {
background-color: transparent;
border: none;
}
}
}

View File

@ -0,0 +1,62 @@
// Core variables and mixins
@import "vendor/highlight.scss";
@import "_fonts.scss";
@import "_typography.scss";
* {
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
html,
body {
height: 100%;
}
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: var(--font-family-text);
}
a {
color: #337ab7;
text-decoration: none;
}
a:focus,
a:hover {
color: #23527c;
text-decoration: underline;
}
p {
margin: 0 0 1em;
}
hr {
clear: both;
margin: 1em 0;
border: 0;
border-top: 1px solid #ddd;
}
img {
max-width: 100% !important;
}
.PageBreak {
display: none;
}
@media screen {
body {
margin: 1em;
}
}
@media print {
@import "_print.scss";
}

View File

@ -0,0 +1,79 @@
/**
* GitHub Gist Theme
* Author : Anthony Attard - https://github.com/AnthonyAttard
* Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro
*/
.hljs {
display: block;
//background: white;
//padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #d73a49;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #6f42c1;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
.hljs-number {
color: #005cc5;
}
.hljs-string {
color: #032f62;
}

View File

@ -0,0 +1,64 @@
import * as preact from "preact";
import { textLinkPrevious, textLinkNext } from "./translation";
/** @jsx preact.h */
export default function Pagination({ counter, start, settings, onPageSelect }) {
const pages = Math.ceil(counter / settings.show);
const page = start / settings.show;
let displayedPages;
if (page <= 2) {
// Display max three pages
displayedPages = Math.min(pages, 3);
} else {
// Display two more pages, but don't overflow
displayedPages = Math.min(pages, page + 2);
}
const items = [];
for (let f = 0; f < displayedPages; f++) {
if (f === page) {
items.push(<li className="current">{f + 1}</li>);
} else {
items.push(
<li>
<a
className="SearchResults__footer__link"
onClick={() => onPageSelect(f * settings.show)}
>
{f + 1}
</a>
</li>
);
}
}
return (
<div className="SearchResults__footer">
<ul className="SearchResults__footer__links Pager">
{start > 0 && (
<li className="Pager--prev">
<a
className="SearchResults__footer__link"
onClick={() => onPageSelect(start - settings.show)}
>
{textLinkPrevious}
</a>
</li>
)}
{items}
{page + 1 !== pages && (
<li className="Pager--next">
<a
className="SearchResults__footer__link"
onClick={() => onPageSelect(start + settings.show)}
>
{textLinkNext}
</a>
</li>
)}
</ul>
</div>
);
}

50
src/js/search/Result.js Normal file
View File

@ -0,0 +1,50 @@
import * as preact from "preact";
/** @jsx preact.h */
// TODO :: restore highlight
/*function highlightText(search, text) {
if (settings.highlightTerms) {
var pattern = new RegExp(
`(${search})`,
settings.highlightEveryTerm ? "gi" : "i"
);
text = text.replace(
pattern,
'<span class="SearchResults__highlight">$1</span>'
);
}
return text;
}*/
export default function Result({ settings, item }) {
let text;
if (item.text) {
text = item.text
.split(" ")
.slice(0, settings.descriptiveWords)
.join(" ");
if (
item.text.length < text.length &&
text.charAt(text.length - 1) !== "."
) {
text += " ...";
}
}
return (
<div className="SearchResult">
<div className="SearchResults__title">
<a href={settings.base_url + item.url}>{item.title}</a>
</div>
{settings.showURL && (
<div className="SearchResults__url">
<a href={settings.base_url + item.url}>
{item.url.toLowerCase().replace(/https?:\/\//g, "")}
</a>
</div>
)}
{text && <div className="SearchResults__text">{text}</div>}
</div>
);
}

145
src/js/search/Search.js Normal file
View File

@ -0,0 +1,145 @@
import * as preact from "preact";
import Pagination from "./Pagination";
import Result from "./Result";
import {
textSearchNoResults,
textSearchOneCharacterOrMore,
textSearchOneResult,
textSearchResults,
textSearchShouldBeXOrMore,
textSearchTooShort
} from "./translation";
/** @jsx preact.h */
export default class Search extends preact.Component {
constructor(props) {
super(props);
this.state = {
search: this.props.settings.field.value || "",
start: 0
};
}
// "click", ".SearchResults__close"
handleClose = () => {
this.props.onClose();
};
scrollTop = () => {
if (this.resultRef) {
this.resultRef.scrollTop = 0;
}
};
handlePaginate = start => {
this.setState({ start }, this.scrollTop);
};
handleChange = event => {
this.setState({ search: event.target.value, start: 0 }, this.scrollTop);
this.props.settings.field.value = event.target.value;
};
getResults() {
const { settings } = this.props;
const { start } = this.state;
const warnings = [];
let counter = 0;
let results = [];
if (this.state.search.length < settings.minimumLength) {
warnings.push(textSearchTooShort);
warnings.push(
settings.minimumLength === 1
? textSearchOneCharacterOrMore
: textSearchShouldBeXOrMore.replace(
"!min",
settings.minimumLength
)
);
return { warnings, counter, results, start };
}
const found = this.props.onSearch(this.state.search);
counter = found.length;
if (counter === 0) {
warnings.push(textSearchNoResults);
return { warnings, counter, results, start };
}
if (settings.showTitleCount) {
this.props.onTitleChange(`(${counter})`);
}
results = found.filter(
(item, itemNumber) =>
itemNumber >= start && itemNumber < settings.show + start
);
return { warnings, counter, results, start };
}
render() {
const { settings } = this.props;
const { warnings, counter, results, start } = this.getResults();
return (
<div>
<div className="SearchResultsBackdrop" />
<div
className="SearchResults"
ref={el => (this.resultRef = el)}
>
<input
className="Search__field"
placeholder="Search..."
autoComplete="on"
autoSave="text_search"
type="search"
value={this.state.search}
onInput={this.handleChange}
/>
<button
className="SearchResults__close"
onClick={this.handleClose}
>
&times;
</button>
<div className="SearchResults__count">
{counter === 1
? textSearchOneResult
: textSearchResults.replace("!count", counter)}
</div>
{warnings.map(warning => (
<div key={warning} className="SearchResults__warning">
{warning}
</div>
))}
{results.map(result => (
<Result
key={result.title}
item={result}
settings={settings}
/>
))}
{counter > settings.show && (
<Pagination
counter={counter}
start={start}
settings={settings}
onPageSelect={this.handlePaginate}
/>
)}
</div>
</div>
);
}
}

144
src/js/search/index.js Normal file
View File

@ -0,0 +1,144 @@
import * as preact from "preact";
import FlexSearch from "flexsearch";
import Search from "./Search";
/** @jsx preact.h */
const originalTitle = document.title;
function getURLP(name) {
const elements = new RegExp(`[?|&]${name}=([^&;]+?)(&|#|;|$)`).exec(
window.location.search
);
return (
decodeURIComponent(
((elements && elements[1]) || "").replace(/\+/g, "%20")
) || null
);
}
class SearchEngine {
constructor(options) {
this.settings = {
field: document.getElementById("search_input"),
show: 10,
showURL: true,
showTitleCount: true,
minimumLength: 3,
descriptiveWords: 25,
highlightTerms: true,
highlightEveryTerm: false,
contentLocation: "daux_search_index.json",
...options
};
this.searchIndex = {
pages: []
};
}
loadData() {
if (!this.loadingPromise) {
this.loadingPromise = fetch(
this.settings.base_url + this.settings.contentLocation
)
.then(data => data.json())
.then(json => {
this.searchIndex = new FlexSearch({
doc: {
id: "url",
field: ["title", "text", "tags"]
}
});
let pages = json.pages;
// Only keep the pages related to the current language
if (window.searchLanguage) {
const pagePrefix = `${window.searchLanguage}/`;
pages = pages.filter(
item => item.url.indexOf(pagePrefix) === 0
);
}
this.searchIndex.add(pages);
});
}
return this.loadingPromise;
}
run() {
if (getURLP("q")) {
this.settings.field.value = getURLP("q");
this.loadData().then(() => {
this.displaySearch();
});
}
this.settings.field.addEventListener("keyup", event => {
// Start loading index once the user types text in the field, not before
this.loadData();
if (parseInt(event.keyCode, 10) === 13) {
this.loadData().then(() => {
this.displaySearch();
});
}
});
}
keyUpHandler = e => {
if (e.which === 27) {
//escape
this.handleClose();
}
};
handleClose = () => {
document.title = originalTitle;
document.removeEventListener("keyup", this.keyUpHandler);
document.body.classList.remove("with-search");
preact.render(null, this.resultContainer);
this.resultContainer = null;
};
displaySearch() {
if (!this.resultContainer) {
this.resultContainer = document.createElement("div");
document.body.appendChild(this.resultContainer);
}
document.addEventListener("keyup", this.keyUpHandler);
preact.render(
<Search
onSearch={term => this.searchIndex.search(term)}
onClose={this.handleClose}
onTitleChange={title => {
document.title = `${title} ${originalTitle}`;
}}
settings={this.settings}
/>,
this.resultContainer
);
document.body.classList.add("with-search");
document.body.scrollTop = 0;
}
}
// Main containers
function search(options) {
const instance = new SearchEngine(options);
instance.run();
}
// Declare globally
window.search = search;

View File

@ -0,0 +1,32 @@
/* eslint-disable camelcase */
const {
Link_previous,
Link_next,
Search_no_results,
Search_one_character_or_more,
Search_one_result,
Search_results,
Search_should_be_x_or_more,
Search_too_short
} = window.searchTranslation;
const textLinkPrevious = Link_previous;
const textLinkNext = Link_next;
const textSearchNoResults = Search_no_results;
const textSearchOneCharacterOrMore = Search_one_character_or_more;
const textSearchOneResult = Search_one_result;
const textSearchResults = Search_results;
const textSearchShouldBeXOrMore = Search_should_be_x_or_more;
const textSearchTooShort = Search_too_short;
/* eslint-enable camelcase */
export {
textLinkPrevious,
textLinkNext,
textSearchNoResults,
textSearchOneCharacterOrMore,
textSearchOneResult,
textSearchResults,
textSearchShouldBeXOrMore,
textSearchTooShort
};

View File

@ -0,0 +1,55 @@
const codeBlocks = document.querySelectorAll(".s-content pre");
const toggleCodeSection = document.querySelector(".CodeToggler");
const LOCAL_STORAGE_KEY = "daux_code_blocks_hidden";
function setCodeBlockStyle(hidden) {
for (let a = 0; a < codeBlocks.length; a++) {
codeBlocks[a].classList.toggle("Hidden", hidden);
}
try {
localStorage.setItem(LOCAL_STORAGE_KEY, hidden);
} catch (e) {
// local storage operations can fail with the file:// protocol
}
}
function enableToggler() {
const toggleCodeBlockBtnSet = toggleCodeSection.querySelector(
".CodeToggler__button--main"
); // available when floating is disabled
toggleCodeBlockBtnSet.addEventListener(
"change",
ev => {
setCodeBlockStyle(!ev.target.checked);
},
false
);
let hidden = false;
try {
hidden = localStorage.getItem(LOCAL_STORAGE_KEY);
if (hidden === "false") {
hidden = false;
} else if (hidden === "true") {
hidden = true;
}
if (hidden) {
setCodeBlockStyle(!!hidden);
toggleCodeBlockBtnSet.checked = !hidden;
}
} catch (e) {
// local storage operations can fail with the file:// protocol
}
}
if (toggleCodeSection) {
if (codeBlocks.length) {
enableToggler();
} else {
toggleCodeSection.classList.add("Hidden");
}
}

View File

@ -0,0 +1,18 @@
const trigger = document.querySelector(".Collapsible__trigger");
if (trigger) {
const content = document.querySelector(".Collapsible__content");
trigger.addEventListener("click", ev => {
if (content.classList.contains("Collapsible__content--open")) {
content.style.height = 0;
content.classList.remove("Collapsible__content--open");
trigger.setAttribute("aria-expanded", "false");
} else {
trigger.setAttribute("aria-expanded", "true");
content.style.transitionDuration = "150ms";
content.style.height = `${content.scrollHeight}px`;
content.classList.add("Collapsible__content--open");
}
});
}

View File

@ -0,0 +1,12 @@
const codeBlocks = document.querySelectorAll("pre > code:not(.hljs)");
if (codeBlocks.length) {
const head = document.getElementsByTagName("head")[0],
script = document.createElement("script");
script.type = "text/javascript";
script.async = true;
script.src = `${window.base_url}daux_libraries/highlight.pack.js`;
script.onload = function(src) {
[].forEach.call(codeBlocks, window.hljs.highlightBlock);
};
head.appendChild(script);
}

View File

@ -0,0 +1,6 @@
/** global localStorage, hljs */
import "./code_toggle.js";
import "./hamburger.js";
import "./highlight.js";
import "./menu.js";

79
src/js/theme_daux/menu.js Normal file
View File

@ -0,0 +1,79 @@
/**
* After the transition finishes set the height to auto so child
* menus can expand properly.
* @param {Element} item
*/
function resetHeightAfterAnimation(item) {
const setHeightToAuto = ev => {
if (ev.target.style.height !== "0px") {
ev.target.style.height = "auto";
}
ev.target.removeEventListener("transitionend", setHeightToAuto);
};
item.addEventListener("transitionend", setHeightToAuto);
}
function findNavItem(start) {
let elem = start;
while ((elem = elem.parentNode) && elem.nodeType !== 9) {
if (elem.nodeType === 1 && elem.classList.contains("Nav__item")) {
return elem;
}
}
throw new Error("Could not find a NavItem...");
}
function toggleSubMenu(ev) {
const isEvent = ev.preventDefault !== undefined;
if (isEvent) {
ev.preventDefault();
}
const parent = findNavItem(ev.target);
const subNav = parent.querySelector("ul.Nav");
if (isEvent && parent.classList.contains("Nav__item--open")) {
// Temporarily set the height so the transition can work.
subNav.style.height = `${subNav.scrollHeight}px`;
subNav.style.transitionDuration = "150ms";
subNav.style.height = "0px";
parent.classList.remove("Nav__item--open");
} else {
if (isEvent) {
subNav.style.transitionDuration = "150ms";
resetHeightAfterAnimation(subNav);
subNav.style.height = `${subNav.scrollHeight}px`;
parent.classList.add("Nav__item--open");
} else {
// When running at page load the transitions don't need to fire and
// the classList doesn't need to be altered.
subNav.style.height = "auto";
}
}
}
const navItems = document.querySelectorAll(
".Nav__item.has-children i.Nav__arrow"
);
// Go in reverse here because on page load the child nav items need to be
// opened first before their parents so the height on the parents can be
// calculated properly.
for (let i = navItems.length - 1, target; i >= 0; i--) {
target = navItems[i];
target.addEventListener("click", toggleSubMenu);
if (target.parentNode.parentNode.classList.contains("Nav__item--open")) {
toggleSubMenu({ target });
}
}
// Some navigations just have sub-pages without having a page by themselves
const ajNav = document.querySelectorAll(".Nav__item__link--nopage");
for (const navItem of ajNav) {
navItem.addEventListener("click", toggleSubMenu);
}

View File

@ -5,8 +5,7 @@
<h1><?= $page['breadcrumbs'] ? $this->get_breadcrumb_title($page, $base_page) : $page['title'] ?></h1>
<?php if ($params['html']['date_modified']) { ?>
<span class="ModifiedDate">
<?php $date_format = isset($params['html']['date_modified_format']) ? $params['html']['date_modified_format'] : 'l, F j, Y g:i A'; ?>
<?= date($date_format, $page['modified_time']); ?>
<?= Todaymade\Daux\FormatDate::format($params, $page['modified_time']) ?>
</span>
<?php } ?>
<?php

View File

@ -60,11 +60,9 @@
<?php if (!empty($params['html']['twitter'])) { ?>
<div class="HomepageFooter__twitter">
<?php foreach ($params['html']['twitter'] as $handle) { ?>
<div class="Twitter">
<iframe allowtransparency="true" frameborder="0" scrolling="no" style="width:162px; height:20px;" src="https://platform.twitter.com/widgets/follow_button.html?screen_name=<?= $handle; ?>&amp;show_count=false"></iframe>
<?php $this->insert('theme::partials/twitter_buttons', ['params' => $params]); ?>
</div>
<?php } ?>
</div>
<?php } ?>
</div>

View File

@ -26,6 +26,12 @@
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- JS -->
<script>
window.base_url = "<?php echo $base_url?>";
document.documentElement.classList.remove('no-js');
</script>
<!-- Font -->
<?php foreach ($params['theme']['fonts'] as $font) {
echo "<link href='$font' rel='stylesheet' type='text/css'>";
@ -37,15 +43,11 @@
} ?>
<?php if ($params['html']['search']) { ?>
<!-- Tipue Search -->
<link href="<?= $base_url; ?>tipuesearch/tipuesearch.css" rel="stylesheet">
<!-- Search -->
<link href="<?= $base_url; ?>daux_libraries/search.css" rel="stylesheet">
<?php } ?>
<!--[if lt IE 9]>
<script src="<?= $base_url; ?>themes/daux/js/html5shiv-3.7.3.min.js"></script>
<![endif]-->
</head>
<body class="<?= $params['html']['float'] ? 'with-float' : ''; ?> <?= $this->section('classes'); ?>">
<body class="<?= $this->section('classes'); ?>">
<?= $this->section('content'); ?>
<?php
@ -62,19 +64,7 @@
echo '<script src="' . $js . '"></script>';
} ?>
<?php if ($params['html']['search']) { ?>
<!-- Tipue Search -->
<script type="text/javascript" src="<?php echo $base_url; ?>tipuesearch/tipuesearch.js"></script>
<script>
window.onunload = function(){}; // force $(document).ready to be called on back/forward navigation in firefox
$(function() {
tipuesearch({
'base_url': '<?php echo $base_url?>'
});
});
</script>
<?php } ?>
<?php $this->insert('theme::partials/search_script', ['page' => $page, 'base_url' => $base_url]); ?>
</body>
</html>

View File

@ -1,7 +1,7 @@
<?php $this->layout('theme::layout/00_layout') ?>
<div class="Columns content">
<aside class="Columns__left Collapsible">
<button type="button" class="Button Collapsible__trigger">
<button type="button" class="Button Collapsible__trigger" aria-controls="sidebar_content" aria-expanded="false" aria-label="<?= $this->translate("Toggle_navigation") ?>">
<span class="Collapsible__trigger__bar"></span>
<span class="Collapsible__trigger__bar"></span>
<span class="Collapsible__trigger__bar"></span>
@ -9,7 +9,7 @@
<?php $this->insert('theme::partials/navbar_content', ['params' => $params]); ?>
<div class="Collapsible__content">
<div class="Collapsible__content" id="sidebar_content">
<!-- Navigation -->
<?php
$rendertree = $tree;
@ -37,30 +37,17 @@
<?php if ($params['html']['toggle_code']) { ?>
<div class="CodeToggler">
<hr/>
<?php if ($params['html']['float']) { ?>
<span class="CodeToggler__text"><?=$this->translate("CodeBlocks_title") ?></span>
<div class="ButtonGroup" role="group">
<button class="Button Button--default Button--small CodeToggler__button CodeToggler__button--hide"><?=$this->translate("CodeBlocks_hide") ?></button>
<button class="Button Button--default Button--small CodeToggler__button CodeToggler__button--below"><?=$this->translate("CodeBlocks_below") ?></button>
<button class="Button Button--default Button--small CodeToggler__button CodeToggler__button--float"><?=$this->translate("CodeBlocks_inline") ?></button>
</div>
<?php } else { ?>
<label class="Checkbox"><?=$this->translate("CodeBlocks_show") ?>
<input type="checkbox" class="CodeToggler__button--main" checked="checked"/>
<div class="Checkbox__indicator"></div>
</label>
<?php } ?>
</div>
<?php } ?>
<?php if (!empty($params['html']['twitter'])) { ?>
<div class="Twitter">
<hr/>
<?php foreach ($params['html']['twitter'] as $handle) { ?>
<iframe allowtransparency="true" frameborder="0" scrolling="no" style="width:162px; height:20px;" src="https://platform.twitter.com/widgets/follow_button.html?screen_name=<?= $handle; ?>&amp;show_count=false"></iframe>
<br />
<br />
<?php } ?>
<?php $this->insert('theme::partials/twitter_buttons', ['params' => $params]); ?>
</div>
<?php } ?>
@ -72,7 +59,7 @@
<?php } ?>
</div>
</aside>
<div class="Columns__right <?= $params['html']['float'] ? 'Columns__right--float' : 'Columns__right--full'; ?>">
<div class="Columns__right">
<div class="Columns__right__content">
<div class="doc_content">
<?= $this->section('content'); ?>

View File

@ -5,7 +5,7 @@
<svg class="Search__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 451 451">
<path d="M447.05 428l-109.6-109.6c29.4-33.8 47.2-77.9 47.2-126.1C384.65 86.2 298.35 0 192.35 0 86.25 0 .05 86.3.05 192.3s86.3 192.3 192.3 192.3c48.2 0 92.3-17.8 126.1-47.2L428.05 447c2.6 2.6 6.1 4 9.5 4s6.9-1.3 9.5-4c5.2-5.2 5.2-13.8 0-19zM26.95 192.3c0-91.2 74.2-165.3 165.3-165.3 91.2 0 165.3 74.2 165.3 165.3s-74.1 165.4-165.3 165.4c-91.1 0-165.3-74.2-165.3-165.4z"/>
</svg>
<input type="search" id="tipue_search_input" class="Search__field" placeholder="<?=$this->translate("Search_placeholder") ?>" autocomplete="on"
<input type="search" id="search_input" class="Search__field" placeholder="<?=$this->translate("Search_placeholder") ?>" autocomplete="on"
results=25 autosave=text_search>
</div>
<?php } ?>

View File

@ -0,0 +1,31 @@
<?php if ($params['html']['search']) { ?>
<script>
<?php
$search_strings = [
"Search_one_result",
"Search_results",
"Search_no_results",
"Search_common_words_ignored",
"Search_too_short",
"Search_one_character_or_more",
"Search_should_be_x_or_more",
"Link_previous",
"Link_next",
];
$search_translations = [];
foreach($search_strings as $key) {
$search_translations[$key] = $this->translate($key);
}
?>
window.searchLanguage = <?= json_encode($page['language']) ?>;
window.searchTranslation = <?= json_encode($search_translations) ?>;
</script>
<!-- Search -->
<script type="text/javascript" src="<?php echo $base_url; ?>daux_libraries/search.min.js"></script>
<script>
window.search({'base_url': '<?php echo $base_url?>'})
</script>
<?php } ?>

View File

@ -0,0 +1,7 @@
<?php foreach ($params['html']['twitter'] as $handle) { ?>
<a class="Twitter__button" target="_blank" title="Follow @<?= $handle; ?> on Twitter" href="https://twitter.com/intent/follow?screen_name=<?= $handle; ?>">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72"><path fill="none" d="M0 0h72v72H0z"/><path class="icon" fill="#fff" d="M68.812 15.14c-2.348 1.04-4.87 1.744-7.52 2.06 2.704-1.62 4.78-4.186 5.757-7.243-2.53 1.5-5.33 2.592-8.314 3.176C56.35 10.59 52.948 9 49.182 9c-7.23 0-13.092 5.86-13.092 13.093 0 1.026.118 2.02.338 2.98C25.543 24.527 15.9 19.318 9.44 11.396c-1.125 1.936-1.77 4.184-1.77 6.58 0 4.543 2.312 8.552 5.824 10.9-2.146-.07-4.165-.658-5.93-1.64-.002.056-.002.11-.002.163 0 6.345 4.513 11.638 10.504 12.84-1.1.298-2.256.457-3.45.457-.845 0-1.666-.078-2.464-.23 1.667 5.2 6.5 8.985 12.23 9.09-4.482 3.51-10.13 5.605-16.26 5.605-1.055 0-2.096-.06-3.122-.184 5.794 3.717 12.676 5.882 20.067 5.882 24.083 0 37.25-19.95 37.25-37.25 0-.565-.013-1.133-.038-1.693 2.558-1.847 4.778-4.15 6.532-6.774z"/></svg>
<span class="Twitter__button__label">Follow @<?= $handle; ?></span>
</a>
<br />
<?php } ?>

View File

@ -20,6 +20,7 @@ class LinkRendererTest extends TestCase
'Widgets' => [
'Page.md' => 'another page',
'Button.md' => 'another page',
'Page_with_#_hash.md' => 'page with hash',
],
];
$root = vfsStream::setup('root', null, $structure);
@ -38,6 +39,11 @@ class LinkRendererTest extends TestCase
public function providerRenderLink()
{
return [
// /Widgets/Page_with_#_hash
['<a href="../Widgets/Page_with_hash.html">Link</a>', '[Link](../Widgets/Page_with_#_hash.md)', 'Content/Page.html'],
['<a href="../Widgets/Page_with_hash.html">Link</a>', '[Link](!Widgets/Page_with_#_hash)', 'Content/Page.html'],
['<a href="Page_with_hash.html">Link</a>', '[Link](Page_with_#_hash.md)', 'Widgets/Page.html'],
// /Widgets/Page
['<a href="http://google.ch" class="Link--external">Link</a>', '[Link](http://google.ch)', 'Widgets/Page.html'],
['<a href="#features">Link</a>', '[Link](#features)', 'Widgets/Page.html'],

View File

@ -1,5 +1,6 @@
<?php
namespace Todaymade\Daux\Format\HTML;
namespace Todaymade\Daux\Format\HTML\Test;
use Todaymade\Daux\Config as MainConfig;
use \Todaymade\Daux\Format\HTML\ContentTypes\Markdown\CommonMarkConverter;

View File

@ -0,0 +1,99 @@
<?php
namespace Todaymade\Daux\Format\Template;
use org\bovigo\vfs\vfsStream;
use Todaymade\Daux\Config;
use Todaymade\Daux\Daux;
use Todaymade\Daux\DauxHelper;
use Todaymade\Daux\Format\HTML\Template;
use Todaymade\Daux\Tree\Builder;
use Todaymade\Daux\Tree\Entry;
use Todaymade\Daux\Tree\Root;
use PHPUnit\Framework\TestCase;
/**
* Class TranslateTest
*
* @package Todaymade\Daux\Format\Template
*/
class TranslateTest extends TestCase
{
protected function getTree(Config $config)
{
$structure = [
'en' => [
'Page.md' => 'some text content',
],
'it' => [
'Page.md' => 'another page',
],
];
$root = vfsStream::setup('root', null, $structure);
$config->setDocumentationDirectory($root->url());
$config['valid_content_extensions'] = ['md'];
$config['mode'] = Daux::STATIC_MODE;
$config['index_key'] = 'index.html';
$tree = new Root($config);
Builder::build($tree, []);
return $tree;
}
public function translateDataProvider()
{
return [
['Previous', 'en'],
['Pagina precedente', 'it'],
];
}
/**
* @dataProvider translateDataProvider
*
* @param $expectedTranslation
* @param $language
*/
public function testTranslate($expectedTranslation, $language)
{
$current = $language . '/Page.html';
$entry = $this->prophesize(Entry::class);
$config = new Config();
$config['tree'] = $this->getTree($config);
$config['title'] = '';
$config['index'] = $entry->reveal();
$config['language'] = $language;
$config['base_url'] = '';
$config['base_page'] = '';
$config['templates'] = '';
$config['page']['language'] = $language;
$config['html'] = [
'search' => '',
'toggle_code' => false,
'piwik_analytics' => '',
'google_analytics' => '',
];
$config['theme'] = [
'js' => [''],
'css' => [''],
'fonts' => [''],
'favicon' => '',
'templates' => 'name',
];
$config['strings'] = [
'en' => ['Link_previous' => 'Previous',],
'it' => ['Link_previous' => 'Pagina precedente',],
];
$config->setCurrentPage(DauxHelper::getFile($config['tree'], $current));
$template = new Template($config);
$value = $template->getEngine($config)->getFunction('translate')->call(null, ['Link_previous']);
$this->assertEquals($expectedTranslation, $value);
}
}

View File

@ -0,0 +1,39 @@
<?php namespace Todaymade\Daux\Server;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpFoundation\Request;
use Todaymade\Daux\Format\HTML\RawPage;
use Todaymade\Daux\Config;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Server\Server;
use org\bovigo\vfs\vfsStream;
class ServerTest extends TestCase
{
function testCreateResponse() {
$structure = [
'index.md' => 'first page',
'Page.md' => 'another page',
'somefile.css' => 'body {}',
'22.png' => ''
];
$root = vfsStream::setup('root', null, $structure);
$daux = new Daux(Daux::LIVE_MODE, new NullOutput());
$daux->getParams()->setDocumentationDirectory($root->url());
$daux->initializeConfiguration();
$daux->getParams()['index_key'] = 'index';
$daux->generateTree();
$page = new RawPage($daux->tree['somefile.css']->getPath());
$server = new Server($daux);
$response = $server->createResponse($page)->prepare(Request::createFromGlobals());
$this->assertEquals("text/css", $response->headers->get('Content-Type'));
}
}

View File

@ -82,16 +82,27 @@ class BuilderTest extends TestCase
return new Root($config);
}
public function testGetOrCreatePage()
public function providerCreatePage()
{
return [
['A Page.md', 'dir/A_Page.html', 'A_Page.html', 'A Page'],
['Page#1.md', 'dir/Page1.html', 'Page1.html', 'Page#1']
];
}
/**
* @dataProvider providerCreatePage
*/
public function testGetOrCreatePage($file, $url, $uri, $title)
{
$directory = new Directory($this->getStaticRoot(), 'dir');
$entry = Builder::getOrCreatePage($directory, 'A Page.md');
$entry = Builder::getOrCreatePage($directory, $file);
$this->assertSame($directory, $entry->getParent());
$this->assertEquals('dir/A_Page.html', $entry->getUrl());
$this->assertEquals('A_Page.html', $entry->getUri());
$this->assertEquals('A Page', $entry->getTitle());
$this->assertEquals($url, $entry->getUrl());
$this->assertEquals($uri, $entry->getUri());
$this->assertEquals($title, $entry->getTitle());
$this->assertInstanceOf('Todaymade\Daux\Tree\Content', $entry);
}

2
themes/d3/js/daux.min.js vendored Normal file
View File

@ -0,0 +1,2 @@
var e=document.querySelectorAll(".s-content pre"),t=document.querySelector(".CodeToggler"),n="daux_code_blocks_hidden";function a(t){for(var a=0;a<e.length;a++)e[a].classList.toggle("Hidden",t);try{localStorage.setItem(n,t)}catch(e){}}t&&(e.length?function(){var e=t.querySelector(".CodeToggler__button--main");e.addEventListener("change",(function(e){a(!e.target.checked)}),!1);var r=!1;try{"false"===(r=localStorage.getItem(n))?r=!1:"true"===r&&(r=!0),r&&(a(!!r),e.checked=!r)}catch(e){}}():t.classList.add("Hidden"));var r=document.querySelector(".Collapsible__trigger");if(r){var o=document.querySelector(".Collapsible__content");r.addEventListener("click",(function(e){o.classList.contains("Collapsible__content--open")?(o.style.height=0,o.classList.remove("Collapsible__content--open"),r.setAttribute("aria-expanded","false")):(r.setAttribute("aria-expanded","true"),o.style.transitionDuration="150ms",o.style.height="".concat(o.scrollHeight,"px"),o.classList.add("Collapsible__content--open"))}))}var l=document.querySelectorAll("pre > code:not(.hljs)");if(l.length){var i=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.async=!0,c.src="".concat(window.base_url,"daux_libraries/highlight.pack.js"),c.onload=function(e){[].forEach.call(l,window.hljs.highlightBlock)},i.appendChild(c)}function s(e){var t=void 0!==e.preventDefault;t&&e.preventDefault();var n=function(e){for(var t=e;(t=t.parentNode)&&9!==t.nodeType;)if(1===t.nodeType&&t.classList.contains("Nav__item"))return t;throw new Error("Could not find a NavItem...")}(e.target),a=n.querySelector("ul.Nav");t&&n.classList.contains("Nav__item--open")?(a.style.height="".concat(a.scrollHeight,"px"),a.style.transitionDuration="150ms",a.style.height="0px",n.classList.remove("Nav__item--open")):t?(a.style.transitionDuration="150ms",a.addEventListener("transitionend",(function e(t){"0px"!==t.target.style.height&&(t.target.style.height="auto"),t.target.removeEventListener("transitionend",e)})),a.style.height="".concat(a.scrollHeight,"px"),n.classList.add("Nav__item--open")):a.style.height="auto"}for(var d,u=document.querySelectorAll(".Nav__item.has-children i.Nav__arrow"),h=u.length-1;h>=0;h--)(d=u[h]).addEventListener("click",s),d.parentNode.parentNode.classList.contains("Nav__item--open")&&s({target:d});var g=document.querySelectorAll(".Nav__item__link--nopage"),v=!0,p=!1,_=void 0;try{for(var y,m=g[Symbol.iterator]();!(v=(y=m.next()).done);v=!0){y.value.addEventListener("click",s)}}catch(e){p=!0,_=e}finally{try{v||null==m.return||m.return()}finally{if(p)throw _}}
//# sourceMappingURL=daux.min.js.map

File diff suppressed because one or more lines are too long

24
themes/daux/config.json Normal file
View File

@ -0,0 +1,24 @@
{
"favicon": "<theme_url>img/favicon.png",
"js": [
"<theme_url>js/daux.min.js"
],
"variants": {
"blue": {
"favicon": "<theme_url>img/favicon-blue.png",
"css": ["<theme_url>css/theme-blue.min.css"]
},
"green": {
"favicon": "<theme_url>img/favicon-green.png",
"css": ["<theme_url>css/theme-green.min.css"]
},
"navy": {
"favicon": "<theme_url>img/favicon-navy.png",
"css": ["<theme_url>css/theme-navy.min.css"]
},
"red": {
"favicon": "<theme_url>img/favicon-red.png",
"css": ["<theme_url>css/theme-red.min.css"]
}
}
}

10
themes/daux/css/theme-blue.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
themes/daux/css/theme-green.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

10
themes/daux/css/theme-navy.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More