8
0
Fork 0

Commits vergleichen

...

287 Commits

Autor SHA1 Nachricht Datum
Daniel Seifert 4686d48902
Merge remote-tracking branch 'remotes/upstream/master' 2020-05-28 09:10:07 +02:00
Stéphane Goetz 079b22f249 Handle anchors on confluence links #208 2020-05-25 22:49:51 +02:00
Stéphane Goetz af0510e114 Update dependencies 2020-05-25 22:19:08 +02:00
Stéphane Goetz 981b53df93 Allow images to be displayed inline #204 2020-05-25 22:18:53 +02:00
Stéphane Goetz 98d3e455a1 Update dependencies 2020-05-25 21:35:06 +02:00
Stéphane Goetz aee33cde34
Check if image is not just an empty string. #205 2020-05-04 11:51:16 +02:00
Stéphane Goetz 04f95c8376
Update README.md 2020-05-01 22:09:02 +02:00
Stéphane Goetz db772b6a5e Allow to create a `style.css` file in the documentation to override some styles. #180 2020-04-25 22:32:43 +02:00
Stéphane Goetz 4d312a44e6 Reformat documentation 2020-04-25 14:44:43 +02:00
Stéphane Goetz ec8530b264 Remove small leftover 2020-04-24 23:45:28 +02:00
Stéphane Goetz 68bf50c595 Improve accessibility and performance 2020-04-24 23:41:18 +02:00
Stéphane Goetz 710150c550 Use async Google Analytics tag. #202 2020-04-24 23:06:41 +02:00
Stéphane Goetz 22fd55e9f7 Switch search to use jsonp to load the index, fully works offline. #198 2020-04-24 22:58:52 +02:00
Stéphane Goetz 213b33b9b5 Support Plausible.io Analytics 2020-04-24 22:22:57 +02:00
Stéphane Goetz 9383fa5f94 Restore report change 2020-04-23 22:50:02 +02:00
Stéphane Goetz f16734d160 Fix Disabling Google analytics #194 2020-04-23 22:44:13 +02:00
Stéphane Goetz 67d5e9a319 Disable report path fixing to test how Sonar-scanner reacts 2020-04-23 22:38:58 +02:00
Stéphane Goetz fcf6a860f8 Fix sonarCloud reports output 2020-04-23 22:19:12 +02:00
Stéphane Goetz d4832b2ca4 Add SonarCloud scanner 2020-04-22 23:23:39 +02:00
Stéphane Goetz 765fc8963e Fix Actions workflow, add SonarCloud 2020-04-22 23:17:36 +02:00
Stéphane Goetz ab3aa4e391 Update dependencies 2020-04-22 23:11:24 +02:00
Stéphane Goetz 8cf6a7667b More reformatting 2020-04-22 22:24:52 +02:00
Stéphane Goetz 9c13185620 Reformat 2020-04-22 21:55:53 +02:00
Stéphane Goetz 684267b47c Update dependencies 2020-04-22 21:39:15 +02:00
Renovate Bot 47d64c2488 Update composer Docker tag to v1.10.5 2020-04-18 15:09:54 +02:00
Renovate Bot 1333595977 Update composer Docker tag to v1.10.4 2020-04-13 10:21:45 +02:00
dependabot[bot] 4d6a2ec162 Bump symfony/http-foundation from 5.0.2 to 5.0.7
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 5.0.2 to 5.0.7.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v5.0.2...v5.0.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-31 08:13:57 +02:00
Renovate Bot 8165ea2300 Update composer Docker tag to v1.10.1 2020-03-21 09:56:39 +01:00
dependabot[bot] 940aa984a9 Bump acorn from 5.7.3 to 5.7.4
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-15 13:16:52 +01:00
Renovate Bot 31d2c50ee4 Update composer Docker tag to v1.10.0 2020-03-15 13:15:51 +01:00
Stéphane Goetz 55e665ea4b Remove unused translations 2020-02-11 19:45:51 +01:00
Renovate Bot 3cfffd651d Update composer Docker tag to v1.9.3 2020-02-08 15:59:31 +01:00
Stéphane Goetz 6bc11d84e7 Use iife, fix CSS linting warnings 2020-02-08 15:49:07 +01:00
Stéphane Goetz d08393fbe5 Fix piwik check 2020-02-07 22:51:21 +01:00
Stéphane Goetz f268f889a4 Fix PHP 7.4 warnings #189 2020-02-07 22:38:28 +01:00
Stéphane Goetz de78382bf5 Fix references to older PHP versions in the documentation 2020-02-07 22:38:01 +01:00
Stéphane Goetz d110f2685c Update dependencies, fix page readiness issues (#190) 2020-02-07 22:16:48 +01:00
Stéphane Goetz d55a615654 Remove search option, can be changed in json easily or with --value 2020-02-07 22:15:38 +01:00
Stéphane Goetz 45426c7c14 Change renovate schedule 2020-02-07 21:40:39 +01:00
proggeler 40e7b83b50 #185: fixed fatal error whilst generating html 2020-01-16 16:06:49 +01:00
Stéphane Goetz 3276d4b611
Fix an edge case in sorting 2020-01-08 08:43:02 +01:00
Stéphane Goetz 437a52e90e
path can be null in case of generated pages 2020-01-08 08:17:33 +01:00
Stéphane Goetz 13377c5ba6 Fix nesting level too deep error #182 2019-12-29 22:40:34 +01:00
Stéphane Goetz 1c4cadf826 add missing intl extension for scrutinizer 2019-12-29 21:01:03 +01:00
Stéphane Goetz e06e94d09b Add intl extension in builds 2019-12-29 20:56:55 +01:00
Stéphane Goetz 0966f90b2c only transliterate if the function exists 2019-12-29 20:54:17 +01:00
Stéphane Goetz 695d2db311 Use transliteration for slug #183 2019-12-29 20:41:13 +01:00
Stéphane Goetz 21eb4992d3 Add failing test for #183 2019-12-29 17:40:05 +01:00
Stéphane Goetz 43a4d8ef0d Update dependencies 2019-12-29 15:26:05 +01:00
Stéphane Goetz b764bcaa82 Update lockfile 2019-12-09 20:49:14 +01:00
Stéphane Goetz 01c97c64c7 Fix generation issue, update dependencies 2019-12-09 19:21:16 +01:00
Stéphane Goetz ac60948fab Other Scrutinizer fixes 2019-12-07 16:32:38 +01:00
Stéphane Goetz 8215808282 Fix scrutinizer hints 2019-12-07 11:22:40 +01:00
Stéphane Goetz b5633e93c7 #171 Redo the configuration layer to add a ConfigBuilder and group configuration parts 2019-12-05 21:25:58 +01:00
Stéphane Goetz 688de1d5b9 Fix warnings and errors reported by Scrutinizer 2019-11-30 22:24:10 +01:00
Stéphane Goetz abaf36bec6 Lazy load CommonMark converter, speeds up generation in serve mode when file is cached (~ -10ms) 2019-11-30 21:46:58 +01:00
Stéphane Goetz 727c5c015e Add custom image renderer to fix relative links to images #78 2019-11-30 20:40:42 +01:00
Stéphane Goetz 7acf4e5b55
Don't pin dependencies 2019-11-30 14:27:39 +01:00
Renovate Bot f55a4ce091 Update all non-major dependencies Docker tags 2019-11-30 14:07:20 +01:00
Stéphane Goetz 6fe7a0bbd7
Update Schedule 2019-11-30 14:05:24 +01:00
Stéphane Goetz 9cb935dc53 Group minor updates 2019-11-30 14:01:23 +01:00
Renovate Bot 639cab7c92 Add renovate.json 2019-11-30 14:01:23 +01:00
Stéphane Goetz 7ab15cfc48 time to go to sleep 2019-11-28 23:44:24 +01:00
Stéphane Goetz 780b224175 fix small oopsies 2019-11-28 23:41:53 +01:00
Stéphane Goetz 13be180582 Fix lots of scrutinizer warnings, remove Travis 2019-11-28 23:32:33 +01:00
Stéphane Goetz 56efd83f2c Add dom extension 2019-11-28 22:46:35 +01:00
Stéphane Goetz 4c7f3816f8 Fix small issues 2019-11-28 22:41:53 +01:00
Stéphane Goetz e04335abeb Update dependencies, min PHP 7.2 2019-11-28 22:36:26 +01:00
Stéphane Goetz f62b2bec96 Output logs from serve in verbose mode #171 2019-11-26 22:43:12 +01:00
Stéphane Goetz 98acc7323f Fix bug reported in #169 2019-11-26 22:08:18 +01:00
Stéphane Goetz b2bd23005f Update dependencies 2019-11-26 21:18:55 +01:00
dependabot-preview[bot] a99c4a4a46 Bump symfony/console from 4.3.8 to 4.4.0
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.8 to 4.4.0.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.8...v4.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-22 08:07:13 +01:00
dependabot-preview[bot] 605668bb81 Bump symfony/http-foundation from 4.3.8 to 4.4.0
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.8 to 4.4.0.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.8...v4.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-22 08:06:51 +01:00
dependabot-preview[bot] c68ffa5b08 Bump symfony/process from 4.3.8 to 4.4.0
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.8 to 4.4.0.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.8...v4.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-22 08:06:38 +01:00
Stéphane Goetz bb8065ade1
Use vendors caching correctly 2019-11-14 08:30:21 +01:00
Stéphane Goetz 2b259e9f2b
Multiple OS and PHP Versions 2019-11-14 08:26:13 +01:00
Stéphane Goetz 0397d70070
Add cache for vendor 2019-11-14 08:19:32 +01:00
Stéphane Goetz bac07a17e8
Add GitHub Actions 2019-11-14 08:17:17 +01:00
dependabot-preview[bot] 2d89e13f8e Bump symfony/console from 4.3.7 to 4.3.8
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.7 to 4.3.8.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.7...v4.3.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-14 08:14:21 +01:00
dependabot-preview[bot] b413b7d72e Bump symfony/process from 4.3.7 to 4.3.8
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.7 to 4.3.8.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.7...v4.3.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-14 08:14:08 +01:00
dependabot-preview[bot] a9f15674b3 [Security] Bump symfony/http-foundation from 4.3.7 to 4.3.8
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.7 to 4.3.8. **This update includes a security fix.**
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.7...v4.3.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-13 15:41:44 +01:00
dependabot-preview[bot] 7b73df9a8c [Security] Bump symfony/mime from 4.3.7 to 4.3.8
Bumps [symfony/mime](https://github.com/symfony/mime) from 4.3.7 to 4.3.8. **This update includes a security fix.**
- [Release notes](https://github.com/symfony/mime/releases)
- [Changelog](https://github.com/symfony/mime/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/mime/compare/v4.3.7...v4.3.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-13 15:41:28 +01:00
dependabot-preview[bot] f584868db3 Bump symfony/http-foundation from 4.3.6 to 4.3.7
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.6 to 4.3.7.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.6...v4.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-12 16:49:27 +01:00
dependabot-preview[bot] 0d8ca1663e Bump symfony/process from 4.3.6 to 4.3.7
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.6 to 4.3.7.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.6...v4.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-12 16:49:13 +01:00
dependabot-preview[bot] 622313e962 Bump symfony/console from 4.3.6 to 4.3.7
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.6 to 4.3.7.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.6...v4.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-12 16:48:59 +01:00
dependabot-preview[bot] 1c060ce7f7 Bump symfony/console from 4.3.5 to 4.3.6
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.5 to 4.3.6.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.5...v4.3.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 14:21:38 +01:00
dependabot-preview[bot] c62eeca2d8 Bump symfony/process from 4.3.5 to 4.3.6
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.5 to 4.3.6.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.5...v4.3.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 14:21:24 +01:00
dependabot-preview[bot] 6f6b0df4a5 Bump symfony/http-foundation from 4.3.5 to 4.3.6
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.5 to 4.3.6.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.5...v4.3.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-04 14:21:09 +01:00
dependabot-preview[bot] 097ebbf555 Bump flexsearch from 0.6.30 to 0.6.32
Bumps [flexsearch](https://github.com/nextapps-de/flexsearch) from 0.6.30 to 0.6.32.
- [Release notes](https://github.com/nextapps-de/flexsearch/releases)
- [Changelog](https://github.com/nextapps-de/flexsearch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextapps-de/flexsearch/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-03 19:22:43 +01:00
dependabot-preview[bot] 8cbe53097d Bump mikey179/vfsstream from 1.6.7 to 1.6.8
Bumps [mikey179/vfsstream](https://github.com/bovigo/vfsStream) from 1.6.7 to 1.6.8.
- [Release notes](https://github.com/bovigo/vfsStream/releases)
- [Changelog](https://github.com/bovigo/vfsStream/blob/v1.6.8/CHANGELOG.md)
- [Commits](https://github.com/bovigo/vfsStream/compare/v1.6.7...v1.6.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-11-03 19:21:34 +01:00
J. King 94767de31a Add user of custom theme to README 2019-10-29 21:12:46 +01:00
dependabot-preview[bot] d6661c3cff Bump phpunit/phpunit from 7.5.16 to 7.5.17
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.16 to 7.5.17.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/7.5.17/ChangeLog-7.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.16...7.5.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-29 21:07:07 +01:00
dependabot-preview[bot] 0d73232250 Bump guzzlehttp/guzzle from 6.3.3 to 6.4.1
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 6.3.3 to 6.4.1.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/6.3.3...6.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-24 19:49:50 +02:00
dependabot-preview[bot] d79030ab2c Bump symfony/http-foundation from 4.3.4 to 4.3.5
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.4...v4.3.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-08 20:12:47 +02:00
dependabot-preview[bot] edfc9f0cc0 Bump symfony/console from 4.3.4 to 4.3.5
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.4...v4.3.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-08 20:12:36 +02:00
dependabot-preview[bot] b6793b6179 Bump symfony/process from 4.3.4 to 4.3.5
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.4...v4.3.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-10-08 20:12:24 +02:00
Daniel Seifert 48e0d0c734 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
2019-09-24 10:43:01 +02:00
Stéphane Goetz e796fad862 rename _libraries to daux_libraries and _search_index to daux_search_index otherwise github pages makes the files invisible 2019-09-23 22:10:07 +02:00
Stéphane Goetz 3acee285c7 Set a max width on the content 2019-09-22 21:54:45 +02:00
Stéphane Goetz d02b46e883 Fine tune menus 2019-09-22 21:42:03 +02:00
Stéphane Goetz b0339a32b8 Improve accessibility and lighthouse score 2019-09-22 20:44:01 +02:00
Stéphane Goetz 491c86383d Remove iframe on Twitter for twitter follow buttons 2019-09-22 20:26:26 +02:00
Stéphane Goetz 35aad3f1a8 Change highlightjs code style 2019-09-22 19:47:01 +02:00
Stéphane Goetz 220060ccef Fine tune table of contents 2019-09-21 22:44:09 +02:00
Stéphane Goetz ef496e9381 Remove ability to have code floating on the side 2019-09-21 22:00:00 +02:00
Stéphane Goetz ac6e71030b Move themes to src/css 2019-09-20 23:29:22 +02:00
Stéphane Goetz 92db87e00d Add server side highlighting, fixes #139 2019-09-20 23:20:49 +02:00
Stéphane Goetz 57b3848430 Move search to _libraries 2019-09-20 23:20:05 +02:00
Stéphane Goetz b06009ebbd Compile daux's JavaScript. Lazy load Highlight.js 2019-09-20 23:15:45 +02:00
Stéphane Goetz 94893a2c7a Use flexsearch to power search 2019-09-19 22:00:34 +02:00
Stéphane Goetz 69d4e0cbfa Merge 2019-09-18 23:19:35 +02:00
Stéphane Goetz 194110ea6d Replace tipuesearch's jQuery with a mix of JS and preact 2019-09-18 23:16:35 +02:00
dependabot-preview[bot] 5dfc17200c Bump phpunit/phpunit from 7.5.15 to 7.5.16
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.15 to 7.5.16.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/7.5.16/ChangeLog-7.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.15...7.5.16)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-16 11:53:11 +02:00
Stéphane Goetz fdcb8ea68f Update dependencies 2019-09-12 08:31:02 +02:00
dependabot-preview[bot] 1f1687ab3f Bump @swissquote/crafty from 1.7.3 to 1.8.0
Bumps [@swissquote/crafty](https://github.com/swissquote/crafty) from 1.7.3 to 1.8.0.
- [Release notes](https://github.com/swissquote/crafty/releases)
- [Commits](https://github.com/swissquote/crafty/compare/v1.7.3...v1.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-12 08:23:50 +02:00
Stéphane Goetz 75f34cae30 Put search field in separate template 2019-09-09 19:56:14 +02:00
Stéphane Goetz 49e2aaf44a Correct documentation on PHP compatiblity, fixes #134 2019-09-09 19:53:59 +02:00
Stéphane Goetz 6cce90f2de Allow to specify template to use in attributes 2019-09-05 23:18:51 +02:00
Stéphane Goetz 5d09c539dc Update issue templates 2019-08-29 19:57:03 +02:00
Stéphane Goetz e62c7da77d Create CODE_OF_CONDUCT.md 2019-08-29 19:56:35 +02:00
dependabot-preview[bot] 298eef8f9c Bump symfony/process from 4.3.3 to 4.3.4
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.3...v4.3.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-28 15:42:34 +02:00
dependabot-preview[bot] 4d4a2b2a35 Bump symfony/console from 4.3.3 to 4.3.4
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.3...v4.3.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-28 15:42:21 +02:00
dependabot-preview[bot] 943b5d086a Bump symfony/http-foundation from 4.3.3 to 4.3.4
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.3...v4.3.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-28 15:42:07 +02:00
J. King 1ba6f269bf Fix notice 2019-08-22 20:03:12 +02:00
Dustin Wilson 633fc593bc Menu JavaScript fixes
* Fixed the expansion of child menus, made them expand properly on page 
load, too
* Removed resize/orientationchange event listener as a result of using a 
transitionend event to set the height to auto after the transition ends
2019-08-22 20:03:12 +02:00
Dustin Wilson 5bc71cc7f6 Changed the menu click point to the arrow 2019-08-22 20:03:12 +02:00
dependabot-preview[bot] 3f130712b4 Bump phpunit/phpunit from 7.5.14 to 7.5.15
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.14 to 7.5.15.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/7.5.15/ChangeLog-7.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.14...7.5.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-22 10:14:39 +02:00
J. King 5a19258651 Restore jQuery for searching for now 2019-08-13 11:20:39 +02:00
J. King d883ad19ed Hide code-toggler for non-scripted clients 2019-08-13 11:20:39 +02:00
Dustin Wilson 9d37044303 Menu improvements
* Menus are now expanded when javascript is disabled/not working.
* Menu for the current page now expands upon load.
2019-08-13 11:20:39 +02:00
J. King 47db2e4cba Minify CSS correctly 2019-08-13 11:20:39 +02:00
Dustin Wilson 9b6af9b000 Rewrite menu opening/closing without jQuery 2019-08-13 11:20:39 +02:00
J. King e84c9cc10a Rewrite code-block manipulation without jQuery 2019-08-13 11:20:39 +02:00
J. King e150fb49bc Remove HTML5shiv 2019-08-13 11:20:39 +02:00
dependabot-preview[bot] d1c63a2c3c Bump myclabs/deep-copy from 1.9.1 to 1.9.3
Bumps [myclabs/deep-copy](https://github.com/myclabs/DeepCopy) from 1.9.1 to 1.9.3.
- [Release notes](https://github.com/myclabs/DeepCopy/releases)
- [Commits](https://github.com/myclabs/DeepCopy/compare/1.9.1...1.9.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-12 13:11:53 +02:00
J. King bf377478b5 Catch localStorage access failures 2019-08-09 11:00:30 +02:00
J. King 1d4a4f4522 Include print stylesheet in default theme 2019-08-09 10:59:32 +02:00
Stéphane Goetz a1875a2726 Update dependencies 2019-08-08 14:21:31 +02:00
Stéphane Goetz 61eaad45e2 #121 Add tests to make sure it doesn't break again 2019-08-08 14:14:56 +02:00
DragoonBoots a17b3d7e5e Fix Mime type guessing 2019-08-08 11:39:39 +02:00
dependabot-preview[bot] 3c3ffa8093 Bump symfony/polyfill-intl-icu from 1.11.0 to 1.12.0
Bumps [symfony/polyfill-intl-icu](https://github.com/symfony/polyfill-intl-icu) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/symfony/polyfill-intl-icu/releases)
- [Commits](https://github.com/symfony/polyfill-intl-icu/compare/v1.11.0...v1.12.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-07 10:21:59 +02:00
Stéphane Goetz 154e0d6ddf
remove invade & Annex
link is dead
2019-08-04 19:33:31 +02:00
Florian Gilcher 57d6686322 Remove invade and annex from README
Link is dead.
2019-08-04 19:33:05 +02:00
dependabot-preview[bot] 470800c68e Bump mikey179/vfsstream from 1.6.6 to 1.6.7
Bumps [mikey179/vfsstream](https://github.com/bovigo/vfsStream) from 1.6.6 to 1.6.7.
- [Release notes](https://github.com/bovigo/vfsStream/releases)
- [Changelog](https://github.com/bovigo/vfsStream/blob/v1.6.7/CHANGELOG.md)
- [Commits](https://github.com/bovigo/vfsStream/compare/v1.6.6...v1.6.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-01 16:04:16 +02:00
dependabot-preview[bot] c86b8d4a5f Bump phpunit/phpunit from 7.5.13 to 7.5.14
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.13 to 7.5.14.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/master/ChangeLog-7.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.13...7.5.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 20:40:01 +02:00
dependabot-preview[bot] f77bd5eaa6 Bump symfony/http-foundation from 4.3.2 to 4.3.3
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.2...v4.3.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 20:39:46 +02:00
dependabot-preview[bot] 2b9b89f178 Bump symfony/process from 4.3.2 to 4.3.3
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.2...v4.3.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 20:39:31 +02:00
dependabot-preview[bot] edff4efd4f Bump symfony/console from 4.3.2 to 4.3.3
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.2...v4.3.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-29 20:39:18 +02:00
dependabot-preview[bot] 931d1358fa [Security] Bump lodash.template from 4.4.0 to 4.5.0
Bumps [lodash.template](https://github.com/lodash/lodash) from 4.4.0 to 4.5.0. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.4.0...4.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 13:32:03 +02:00
dependabot-preview[bot] e813931315 [Security] Bump lodash from 4.17.11 to 4.17.14
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14. **This update includes security fixes.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-11 13:30:30 +02:00
Alexander Overvoorde dbfb4cf70d Fix directories with unicode characters not being supported 2019-07-09 21:16:05 +02:00
dependabot-preview[bot] 41866cfd35 Bump symfony/process from 4.3.1 to 4.3.2
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.1...v4.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-27 10:16:34 +02:00
dependabot-preview[bot] ba5295e4aa Bump symfony/console from 4.3.1 to 4.3.2
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.1...v4.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-27 10:16:23 +02:00
dependabot-preview[bot] f6c9373870 Bump symfony/http-foundation from 4.3.1 to 4.3.2
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.1...v4.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-27 10:16:12 +02:00
Stéphane Goetz 3dd865dd0f Update dependencies 2019-06-26 22:12:03 +02:00
dependabot-preview[bot] 1bb938ea17 Bump @swissquote/crafty-runner-gulp from 1.7.2 to 1.7.3
Bumps [@swissquote/crafty-runner-gulp](https://github.com/swissquote/crafty) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/swissquote/crafty/releases)
- [Commits](https://github.com/swissquote/crafty/compare/v1.7.2...v1.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-24 15:46:02 +02:00
dependabot-preview[bot] e8bb48bcbc Bump @swissquote/crafty from 1.7.2 to 1.7.3
Bumps [@swissquote/crafty](https://github.com/swissquote/crafty) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/swissquote/crafty/releases)
- [Commits](https://github.com/swissquote/crafty/compare/v1.7.2...v1.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-24 14:58:33 +02:00
dependabot-preview[bot] f26d09ccd4 Bump phpunit/phpunit from 7.5.12 to 7.5.13
Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 7.5.12 to 7.5.13.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/master/ChangeLog-7.5.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/7.5.12...7.5.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-24 11:50:33 +02:00
dependabot-preview[bot] 3f7bc48a5e Bump @swissquote/crafty-preset-postcss from 1.7.2 to 1.7.3
Bumps [@swissquote/crafty-preset-postcss](https://github.com/swissquote/crafty) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/swissquote/crafty/releases)
- [Commits](https://github.com/swissquote/crafty/compare/v1.7.2...v1.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-24 11:50:10 +02:00
dependabot-preview[bot] 520df945ab Bump symfony/console from 4.3.0 to 4.3.1
Bumps [symfony/console](https://github.com/symfony/console) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.3.0...v4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-07 14:32:08 +02:00
dependabot-preview[bot] f959a5cff8 Bump symfony/http-foundation from 4.3.0 to 4.3.1
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.3.0...v4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-07 14:31:58 +02:00
dependabot-preview[bot] 075a23da38 Bump symfony/process from 4.3.0 to 4.3.1
Bumps [symfony/process](https://github.com/symfony/process) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.3.0...v4.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-06-07 14:31:48 +02:00
dependabot-preview[bot] 8183587120 Bump symfony/http-foundation from 4.2.9 to 4.3.0
Bumps [symfony/http-foundation](https://github.com/symfony/http-foundation) from 4.2.9 to 4.3.0.
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v4.2.9...v4.3.0)
2019-05-31 08:05:10 +02:00
dependabot-preview[bot] b3acb383f4 Bump symfony/process from 4.2.9 to 4.3.0
Bumps [symfony/process](https://github.com/symfony/process) from 4.2.9 to 4.3.0.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v4.2.9...v4.3.0)
2019-05-31 07:43:54 +02:00
dependabot-preview[bot] 458c9247d8 Bump symfony/console from 4.2.9 to 4.3.0
Bumps [symfony/console](https://github.com/symfony/console) from 4.2.9 to 4.3.0.
- [Release notes](https://github.com/symfony/console/releases)
- [Changelog](https://github.com/symfony/console/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/console/compare/v4.2.9...v4.3.0)
2019-05-31 07:43:27 +02:00
Stéphane Goetz 0df9da84db Upgrade composer dependencies 2019-05-28 22:17:30 +02:00
Stéphane Goetz 7a07b61b18 Upgrade NPM Dependencies 2019-05-28 22:12:50 +02:00
Stéphane Goetz f034b48a78 Add 3Q Video in the featured list 2019-05-28 21:28:55 +02:00
Stéphane Goetz 5d2d19141c Sanitize filenames for usage in urls, fixes #86 2019-05-28 21:26:27 +02:00
Stéphane Goetz 667935e927 Update dependencies 2019-05-24 23:25:32 +02:00
Stéphane Goetz d02ebe093b
Fix missing variable 2019-04-29 14:36:22 +02:00
Stéphane Goetz 97f6175f1c Fine tune configuration 2019-03-04 10:26:38 +01:00
Stéphane Goetz 5af4b2398f Update dependencies 2019-03-04 10:17:00 +01:00
Gereon Frey 5f616782fd Fix file permissions
Using the user's uid and gid in the container prevents the output files
to belong to root.
2019-02-25 08:06:45 +01:00
Gereon Frey 59fa9fb3ab Optimize Dockerfile
This change will only copy the `compose.{json|lock}` files prior to
installing the dependencies. This improves container image build time
when only code changed, as it facilitates image caching.
2019-02-25 08:06:45 +01:00
Gereon Frey 63c336039b Use debian instead of alpine
This is related to issues with iconv on alpine linux (see [1]). I
noticed that the content file `tipuesearch_content.json` didn't contain
the sanitized text, but only the boolean `false`. I tracked it down to
the `iconv` call. After migration to the debian docker image it is
working fine. Build was started using `docker run --rm -it -w /build -v
"$PWD":/build daux/daux.io daux generate`.

[1] https://github.com/docker-library/php/issues/428
2019-02-25 08:06:45 +01:00
Stéphane Goetz 0c2032d5f9 Update dependencies 2018-11-30 21:09:46 +01:00
Tim Gerundt c8232b612d Global language get ignored
If a page has no language configured, the global language setting get ignored.
2018-10-15 10:11:23 +02:00
Tim Gerundt b60772ac72 Translate new strings to German 2018-10-15 10:08:36 +02:00
Tim Gerundt ad4f6c7c01 Update PHP Requirements in README.md 2018-10-12 09:06:10 +02:00
Stéphane Goetz f75c5597d9
Replace deprecated call 2018-10-04 08:18:23 +02:00
Stéphane Goetz 7d8d5c86cf Search only in current language, fixes #48 2018-10-01 22:25:59 +02:00
Stéphane Goetz 10070f9b90 Separate documentation deployment 2018-09-30 11:06:28 +02:00
Stéphane Goetz 3e41b5142e Merge remote-tracking branch 'origin/master' 2018-09-30 11:01:45 +02:00
Stéphane Goetz 5acebc567f Update list of who uses Daux, fixes #70 2018-09-30 11:01:34 +02:00
Stéphane Goetz ba097a9be0
Merge pull request #69 from enricobono/translate-framework-on-shown-content
Translate framework based on shown content
2018-09-27 14:05:22 +02:00
enrico 2f0b298b50 Translate new strings into italian 2018-09-27 14:04:42 +02:00
enrico 091edbd7e8 Add italian translation to global.json 2018-09-27 14:04:42 +02:00
enrico f5b7635013 Add italian translation to global.json 2018-09-27 14:04:42 +02:00
enrico bd2b6d01b4 Add italian translation to global.json 2018-09-27 14:04:42 +02:00
enrico 0d72c5a056 Use the page language for the framework translation 2018-09-27 10:13:43 +02:00
Stéphane Goetz b05010fd00 Update dependencies 2018-09-26 21:38:07 +02:00
enrico 2bf251201c Add italian translation to global.json 2018-09-26 15:01:00 +02:00
enrico 5da0aa8996 Add italian translation to global.json 2018-09-26 14:59:20 +02:00
Stéphane Goetz d1089b114e Allow to translate search strings, Fixes #39 2018-09-23 20:38:06 +02:00
Stéphane Goetz 4e0e81cb29 Fix single page generation, make internal links work correctly 2018-09-21 23:43:06 +02:00
Stéphane Goetz 851bad3ada Be more user friendly if the format is incorrect 2018-09-21 23:41:49 +02:00
Stéphane Goetz 098b566496 small changes 2018-09-21 22:12:07 +02:00
Stéphane Goetz d93ad8c6b1 Add translation of modified_at time, using php-intl 2018-09-21 22:12:07 +02:00
Stéphane Goetz 3982139892 Update npm dependencies 2018-09-21 22:12:07 +02:00
Marie P-W ac4bb09d45 Fix TOC template rendering
TOC renderer only takes default template into account. 
Adding `theme::` fix it, it will use `theme` folder if there is one.
2018-09-21 16:29:46 +02:00
Stéphane Goetz 6b6a010261 Remove default command, fixes #60 2018-09-20 20:41:25 +02:00
Stéphane Goetz cfc3be0b32 Remove HHVM specific code 2018-09-20 20:17:51 +02:00
Morgan Zolob 7928b4365b Allow Daux to work from sub-directories
If you try to host Daux from any directory other than the root of a website (like mysite.com/docs, for example), it just gives an error that the page can't be found. This commit will make Daux remove the base directory from the request when handling it, which should make it work properly in sub-directories.
2018-09-20 20:14:43 +02:00
Stéphane Goetz 59a9dd5cf5
Merge pull request #59 from noraj/patch-1
add debian 8 composer path
2018-09-20 10:46:49 +02:00
Stéphane Goetz 434a9d7290
Merge pull request #64 from cambierr/master
Changed Server.php to be able to run on symfony 4.0+
2018-09-20 10:45:47 +02:00
Daniel Seifert 7e53ad4b4a Merge remote-tracking branch 'remotes/origin/d3version' 2018-09-07 13:01:00 +02:00
Romain Cambier 2093eee156
Changed Server.php to be able to run on symfony 4.0+ 2018-08-13 08:42:14 +02:00
Daniel Seifert 146e527561 don't export templates and scss files 2018-07-20 22:11:16 +02:00
Daniel Seifert 38a01e1069 changed wrong resource link 2018-07-20 21:01:23 +02:00
Daniel Seifert 6a52f6bff7 don't forget configuration in case of deeper source directory 2018-07-19 22:04:24 +02:00
Daniel Seifert 618da86277 check for set variables 2018-07-19 20:31:16 +02:00
Daniel Seifert 36a9e7134c add versionselector variable check 2018-07-19 20:27:39 +02:00
Daniel Seifert 0b92136bbd clean themes, note theme name change! 2018-07-11 23:26:40 +02:00
Daniel Seifert 42093faa3a allow parent directory, add version selector in home page 2018-07-10 22:01:30 +02:00
Daniel Seifert e6a5ab0771 fix selected 2018-07-10 01:02:19 +02:00
Daniel Seifert bd04e8ca1e add versionselector option 2018-07-10 00:28:24 +02:00
Daniel Seifert dbcf67cad9 Merge tag '0.7.4' into d3version 2018-07-09 11:19:03 +02:00
Daniel Seifert 21bf9e2922 Merge tag '0.7.3' into branch_0.7.2 2018-07-09 11:11:21 +02:00
Daniel Seifert 06804d97d6 change composer ident 2018-07-08 22:43:52 +02:00
Daniel Seifert 773859d60a add d3 individualizations 2018-07-08 22:39:35 +02:00
Alexandre ZANNI f171faf81e
add debian 8 composer path
not all linux distro have the same path
2018-06-22 15:24:07 +02:00
Stéphane Goetz ba8658d706 Fix cache, add clear-cache command 2018-06-07 20:40:38 +02:00
Stéphane Goetz 6a7dae3023 Fix regression introduced to fix #55 2018-06-06 23:37:26 +02:00
Stéphane Goetz 47a9565b23 Create cache for Markdown content. #51 2018-06-06 23:20:29 +02:00
Stéphane Goetz 4325008a5f Improve performance by calculating. Fixes #55 2018-06-06 21:10:06 +02:00
Stéphane Goetz 0570fb7971 Fix breadcrumb support of multiple folders with the same name. Fixes #54 2018-06-05 23:02:01 +02:00
Stéphane Goetz 049e5cd498 Document how you can create a docker image with the documentation inside. Fixes #37 2018-06-05 22:40:38 +02:00
Stéphane Goetz 7b665558af Use front matter of the index page to define folder's name. Fixes #27 2018-06-05 22:29:31 +02:00
Stéphane Goetz eb89664473 Keep numbers in raw files, as they aren't sorted anyway. Fixes #26 2018-06-05 21:28:54 +02:00
Stéphane Goetz 41c355edb1 Add more details on verbose output #52 2018-06-05 20:31:51 +02:00
Stéphane Goetz 29a8a8d9cc Allow to get version with -V / --version #53 2018-06-04 22:52:21 +02:00
Stéphane Goetz 65f0679d7a Fix formatting 2018-05-05 18:16:24 +02:00
Stéphane Goetz 1e23b4ed90 and again :) 2018-05-05 17:43:23 +02:00
Stéphane Goetz 4b8a487b4f Let's try with other versions 2018-05-05 17:41:09 +02:00
Stéphane Goetz 75cff529c0 Update PHP versions to build on travis 2018-05-05 17:35:28 +02:00
Stéphane Goetz 34aa4d5a76 Build with latest crafty 2018-05-05 17:35:12 +02:00
Stéphane Goetz 5ab15752de fix getTerminalDimensions 2018-05-05 16:58:49 +02:00
Stéphane Goetz eae3f31d65
Merge pull request #47 from kalixi/master
fix: "PHP Notice:  Uninitialized string offset: 0 in ..."
2018-05-05 11:16:49 +02:00
catroll 83464a80e9 fix: "PHP Notice: Uninitialized string offset: 0 in ..." 2018-03-21 16:11:53 +08:00
Stéphane Goetz b5189c5590
Merge pull request #43 from aedart/master
Upgrade dependencies
2018-03-12 09:05:03 +01:00
Alin Eugen Deac 2816da9a71 Remove php 5.x and 7.0 support 2018-03-05 08:51:57 +01:00
Alin Eugen Deac 7837462690 Upgrade dependencies 2018-03-05 08:46:03 +01:00
Stéphane Goetz 2caa193a16 Fix code blocks presentation 2018-02-27 23:43:36 +01:00
Stéphane Goetz e31be9d02e Added Powered By 2018-02-27 22:47:07 +01:00
Stéphane Goetz e3a156f770 Improve default theme 2018-02-26 22:46:36 +01:00
Stéphane Goetz 2a3d513a40 Create a variables file to customize theme easily, lint CSS 2018-02-25 23:02:09 +01:00
Stéphane Goetz 3346dec1d6 Use crafty to build css, convert less to scss 2018-02-25 20:12:18 +01:00
Stéphane Goetz d0b2850434 Auto deploy docs to travis and add examples 2017-12-22 22:53:05 +01:00
Stéphane Goetz da522ba2d3 Repair single page documentation generator 2017-12-11 22:25:45 +01:00
Stéphane Goetz e12465b4de Fix unit tests 2017-12-11 22:02:20 +01:00
Stéphane Goetz 91014cef8b Manage table of contents differently 2017-12-11 21:14:18 +01:00
Stéphane Goetz e844b51f10 Fix Mime Types - fix CLI param 2017-12-08 16:29:44 +01:00
Stéphane Goetz 9269b277e2
Merge pull request #23 from gabriel-caruso/phpunit
Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase
2017-11-13 23:19:23 +02:00
Gabriel Caruso 74ba2b301d Use PHPUnit\Framework\TestCase instead of PHPUnit_Framework_TestCase 2017-11-11 04:22:27 -02:00
Stéphane Goetz 70d15cc0ec fix usages of iconv 2017-11-08 21:51:01 +01:00
Stéphane Goetz d1c7b27563 Add support for + at the beginning, fixes #18 2017-11-08 21:49:30 +01:00
Stéphane Goetz d898eb6edf Fix json output for search index, fixes #21 2017-11-08 00:01:08 +01:00
Stéphane Goetz 837fca6886 Small refactoring and documentation fix 2017-11-07 23:17:05 +01:00
Stéphane Goetz def4b5ed98
Merge pull request #22 from gerundt/meta-tags
Add `description`, `keywords` and `author` to Front Matter (fix #20)
2017-11-08 00:08:27 +02:00
Stéphane Goetz 52ce3714cf More cleanup 2017-11-07 22:54:31 +01:00
Stéphane Goetz c0016c759a More refactoring 2017-11-07 22:44:27 +01:00
Tim Gerundt 0e516797c3 Add `description`, `keywords` and `author` to Front Matter (fix #20) 2017-11-07 22:39:34 +01:00
Stéphane Goetz f281169871 Cleanup publisher 2017-11-07 22:08:30 +01:00
Stéphane Goetz e3a89832c5 Only list deletable pages if there are any 2017-11-06 23:32:41 +01:00
Stéphane Goetz e5ee061ddd Don't upload attachments if they are already uploaded and have the same size 2017-11-06 23:20:42 +01:00
Stéphane Goetz 59b8c04161 Confluences bugfixes, Fix documentation
Make it easier to spot where an error comes from when uploading to confluence.
Allow to upload documentation without a prefix.
2017-11-06 22:46:07 +01:00
Stéphane Goetz 8e7340da3d Allow to set configuration values directly in the command line 2017-11-05 23:56:46 +01:00
Stéphane Goetz 55ee848e32 Update dependencies 2017-11-05 23:55:56 +01:00
Stéphane Goetz 4d97257b74 Remove mentions of Grunt in readme
fixes #17
2017-10-27 11:05:55 +02:00
Stéphane Goetz fc3d88d0ae Merge pull request #16 from gerundt/css-page-header
Use CSS classes for "Modified Date" and "Edit On" in page header
2017-10-27 10:32:24 +02:00
Stéphane Goetz 60c7737e8a Use CSS classes for "Modified Date" and "Edit On" in page header 2017-10-26 21:25:51 +02:00
Stéphane Goetz 165be22445 Merge pull request #14 from gerundt/patch-2
Add German translation
2017-10-23 16:31:36 +02:00
Tim Gerundt 70c9fa5c9e Add German translation
This patch adds the German translation
2017-10-20 08:50:40 +02:00
Stéphane Goetz 46c23aac4c Merge pull request #13 from gerundt/date_format
Add "date_modified_format" option to html export
2017-10-19 22:20:59 +02:00
Stéphane Goetz a1a65bb9f0 Support translations for the UI, fixes #1 2017-10-19 22:18:46 +02:00
Stéphane Goetz ef36a953b4 Use checkbox instead of changing text 2017-10-19 21:20:58 +02:00
Tim Gerundt 1c9806a9b0 Add "date_modified_format" option to html export 2017-10-19 21:20:34 +02:00
Stéphane Goetz 364ce8893d Merge pull request #12 from gerundt/patch-1
Add X-UA-Compatible header for Internet Explorer
2017-10-19 19:35:00 +02:00
Tim Gerundt 278a922be2 Add X-UA-Compatible header for Internet Explorer
The IE opens intranet site often in compatible mode. In this mode looks the DAUX layout not good. With this header we say the IE that he can use the newest browser engine.
2017-10-19 09:11:01 +02:00
Stéphane Goetz 5c95d20280 Embed HTML5 Shiv, fixes #10 2017-10-18 22:41:07 +02:00
Stéphane Goetz ec9344f558 Change Docker's base image to use alpine. Fixes #5 2017-10-18 21:34:54 +02:00
Stéphane Goetz a1fc50ad70 Update dependencies 2017-10-18 21:29:02 +02:00
Stéphane Goetz 0d3e366277 Remove daux.phar 2017-10-18 21:15:35 +02:00
Stéphane Goetz 0270e14121 Added DoctrineWatcher, fixes #2 2017-10-18 20:19:55 +02:00
Stéphane Goetz de92abcfb9 Merge pull request #8 from jandrewstre/master
Fix references to composer package name, dauxio/daux.io -> daux/daux.io
2017-10-18 19:56:58 +02:00
John Andrews adc5e323f0 Fix references to composer package name, dauxio/daux.io -> daux/daux.io 2017-10-13 21:18:00 -07:00
260 geänderte Dateien mit 23485 neuen und 9625 gelöschten Zeilen

2
.dockerignore Normale Datei
Datei anzeigen

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

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normale Datei
Datei anzeigen

@ -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.

20
.github/ISSUE_TEMPLATE/feature_request.md vendored Normale Datei
Datei anzeigen

@ -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.

85
.github/workflows/php.yml vendored Normale Datei
Datei anzeigen

@ -0,0 +1,85 @@
name: CI
on: [push]
jobs:
build:
strategy:
max-parallel: 15
matrix:
# TODO : enable tests on windows
operating-system: [ubuntu-latest, macOS-latest]
php-versions: ['7.2', '7.3', '7.4']
exclude:
- operating-system: macos-latest
php-versions: 7.4
name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }}
runs-on: ${{ matrix.operating-system }}
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@master
with:
php-version: ${{ matrix.php-versions }}
extension-csv: mbstring, dom, intl
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Install tools
run: ./scripts/install_tools.sh
- name: Run test suite
run: composer run-script test
sonarcloud:
name: "SonarCloud"
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- uses: actions/checkout@v1
- name: Setup PHP
uses: shivammathur/setup-php@master
with:
php-version: 7.4
extension-csv: mbstring, dom, intl
coverage: pcov
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Install tools
run: ./scripts/install_tools.sh
- name: Run test suite
run: composer run-script test -- --coverage-clover=coverage.clover --log-junit=test-report.xml
- name: Fix reports
run: scripts/fix_reports.sh
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@v1.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
documentation:
runs-on: ubuntu-latest
if: github.repository == 'dauxio/daux.io' && github.event_name != 'pull_request' && github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Generate documentation
run: bin/daux generate --value html.plausible_domain=daux.io
- uses: JamesIves/github-pages-deploy-action@2.0.3
env:
FOLDER: "static"
BRANCH: gh-pages
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

9
.gitignore vendored
Datei anzeigen

@ -5,3 +5,12 @@ node_modules
static
/vendor
/build
.phpunit.result.cache
.php_cs.cache
coverage.clover
test-report.xml
/prettier.config.js
/.eslintrc.js
/stylelint.config.js

28
.php_cs Normale Datei
Datei anzeigen

@ -0,0 +1,28 @@
<?php
$finder = PhpCsFixer\Finder::create()
->exclude('vendor')
->exclude('templates')
->in(__DIR__)
;
return PhpCsFixer\Config::create()
->setRules([
'@PSR2' => true,
'@PHP70Migration' => true,
'@PHP71Migration' => true,
'@PhpCsFixer' => true,
'explicit_string_variable' => false,
'single_blank_line_before_namespace' => false,
'no_short_echo_tag' => false,
'blank_line_after_opening_tag' => false,
'yoda_style' => false,
'concat_space' => ['spacing' => 'one'],
'php_unit_internal_class' => false,
'php_unit_test_class_requires_covers' => false,
'phpdoc_align' => false,
'multiline_whitespace_before_semicolons' => false,
'ordered_class_elements' => ['use_trait', 'constant_public', 'constant_protected', 'constant_private', 'property_public', 'property_protected', 'property_private', 'construct', 'method']
])
->setFinder($finder)
;

Datei anzeigen

@ -1,21 +0,0 @@
language: php
php:
- '5.6'
- '7.0'
- '7.1'
- nightly
matrix:
allow_failures:
- php: nightly
before_script:
- composer install --dev --prefer-source
script:
- vendor/bin/phpunit --coverage-clover=coverage.clover
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover

76
CODE_OF_CONDUCT.md Normale Datei
Datei anzeigen

@ -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

Datei anzeigen

@ -1,29 +1,30 @@
FROM php:7
FROM composer:1.10.5 AS composer
RUN apt-get update && apt-get install -y unzip && rm -rf /var/lib/apt/lists/*
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
# 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
COPY index.php /daux/index.php
RUN ln -s /daux/bin/daux /usr/local/bin/daux

182
README.md
Datei anzeigen

@ -1,49 +1,48 @@
# Daux.io
[![Latest Version](https://img.shields.io/github/release/dauxio/daux.io.svg?style=flat-square)](https://github.com/dauxio/daux.io/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/dauxio/daux.io/blob/master/LICENSE.md)
[![Build Status](https://img.shields.io/travis/dauxio/daux.io/master.svg?style=flat-square)](https://travis-ci.org/dauxio/daux.io)
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/dauxio/daux.io/CI?style=flat-square)
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/dauxio/daux.io.svg?style=flat-square)](https://scrutinizer-ci.com/g/dauxio/daux.io/code-structure)
[![Quality Score](https://img.shields.io/scrutinizer/g/dauxio/daux.io.svg?style=flat-square)](https://scrutinizer-ci.com/g/dauxio/daux.io)
[![Total Downloads](https://img.shields.io/packagist/dt/dauxio/daux.io.svg?style=flat-square)](https://packagist.org/packages/dauxio/daux.io)
[![Total Downloads](https://img.shields.io/packagist/dt/daux/daux.io.svg?style=flat-square)](https://packagist.org/packages/daux/daux.io)
**Daux.io** is a documentation generator that uses a simple folder structure and Markdown files to create custom documentation on the fly. It helps you create great looking documentation in a developer friendly way.
## Features
* 100% Mobile Responsive
* CommonMark compliant (a Markdown specification)
* Supports Markdown tables
* Auto created homepage/landing page
* Auto Syntax Highlighting
* Auto Generated Navigation
* 4 Built-In Themes or roll your own
* Functional, Flat Design Style
* Shareable/Linkable SEO Friendly URLs
* Built On Bootstrap
* No Build Step
* Git/SVN Friendly
* Supports Google Analytics and Piwik Analytics
* Optional code float layout
* Static Output Generation
- 100% Mobile Responsive
- CommonMark compliant (a Markdown specification)
- Supports Markdown tables
- Auto created homepage/landing page
- Auto Syntax Highlighting
- Auto Generated Navigation
- 4 Built-In Themes or roll your own
- Functional, Flat Design Style
- Shareable/Linkable SEO Friendly URLs
- Built On Bootstrap
- No Build Step
- Git/SVN Friendly
- Supports Google Analytics and Piwik Analytics
- Optional code float layout
- Static Output Generation
## Demos
This is a list of sites using Daux.io:
- With a custom theme:
* [Vulkan Tutorial](https://vulkan-tutorial.com)
* [TrackJs](http://docs.trackjs.com)
- 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)
* [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)
* [Nuntius: A PHP framework for bots](https://roysegall.github.io/nuntius-bot/)
- 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/)
- [The Advanced RSS Environment](https://thearsse.com/manual/)
- With the default Theme
- [Daux.io](https://daux.io/)
_ [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/)
- [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.
@ -54,7 +53,7 @@ Do you use Daux.io? Send me a pull request or open an [issue](https://github.com
If you have PHP and Composer installed, you can install the dependency
```bash
composer global require dauxio/daux.io
composer global require daux/daux.io
# Next to your `docs` folder, run
daux generate
@ -69,7 +68,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
@ -98,18 +97,18 @@ You must use underscores instead of spaces. Here are some example file names and
**Good:**
* 01_Getting_Started.md = Getting Started
* API_Calls.md = API Calls
* 200_Something_Else-Cool.md = Something Else-Cool
* _5_Ways_to_Be_Happy.md = 5 Ways To Be Happy
- 01_Getting_Started.md = Getting Started
- API_Calls.md = API Calls
- 200_Something_Else-Cool.md = Something Else-Cool
- \_5_Ways_to_Be_Happy.md = 5 Ways To Be Happy
**Bad:**
* File Name With Space.md = FAIL
- File Name With Space.md = FAIL
## Sorting
To sort your files and folders in a specific way, you can prefix them with a number and underscore, e.g. `/docs/01_Hello_World.md` and `/docs/05_Features.md` This will list *Hello World* before *Features*, overriding the default alpha-numeric sorting. The numbers will be stripped out of the navigation and urls. For the file `6 Ways to Get Rich`, you can use `/docs/_6_Ways_to_Get_Rich.md`
To sort your files and folders in a specific way, you can prefix them with a number and underscore, e.g. `/docs/01_Hello_World.md` and `/docs/05_Features.md` This will list _Hello World_ before _Features_, overriding the default alpha-numeric sorting. The numbers will be stripped out of the navigation and urls. For the file `6 Ways to Get Rich`, you can use `/docs/_6_Ways_to_Get_Rich.md`
## Landing page
@ -117,9 +116,9 @@ If you want to create a beautiful landing page for your project, simply create a
```json
{
"title": "Daux.io",
"tagline": "The Easiest Way To Document Your Project",
"image": "app.png"
"title": "Daux.io",
"tagline": "The Easiest Way To Document Your Project",
"image": "app.png"
}
```
@ -135,52 +134,50 @@ To customize the look and feel of your documentation, you can create a `config.j
The `config.json` file is a simple JSON object that you can use to change some of the basic settings of the documentation.
### Title
Change the title bar in the docs
```json
{
"title": "Daux.io"
"title": "Daux.io"
}
```
### Themes
We have 4 built-in Bootstrap themes. To use one of the themes, just set the `theme` option to one of the following:
* daux-blue
* daux-green
* daux-navy
* daux-red
- daux-blue
- daux-green
- daux-navy
- daux-red
```json
{
"html": { "theme": "daux-green" }
"html": { "theme": "daux-green" }
}
```
### More options
Many other options are available:
- [Global options](http://daux.io/Configuration/index)
- [HTML Options](http://daux.io/Configuration/Html_export)
- [Confluence options](http://daux.io/Configuration/Confluence_upload)
- [Global options](http://daux.io/Configuration/index)
- [HTML Options](http://daux.io/Configuration/Html_export)
- [Confluence options](http://daux.io/Configuration/Confluence_upload)
## Running Remotely
Copy the files from the repo to a web server that can run PHP 5.4 or greater.
Copy the files from the repo to a web server that can run PHP 7.2.0 or newer.
## Running Locally
There are several ways to run the docs locally. You can use something like <a href="http://www.mamp.info/en/index.html" target="_blank">MAMP</a> or <a href="http://www.wampserver.com/en/" target="_blank">WAMP</a>. If you are like me and use alot of Node.js and <a href="http://gruntjs.com/" target="_blank">Grunt.js</a>, then you can use the optional grunt command I have packaged with the project which will start a PHP web server for you in the project folder.
There are several ways to run the docs locally.
The recommended way is to run `daux serve` which will execute PHP's embedded server.
The Grunt.js task uses the built in web server in PHP 5.4 to host the docs on your local machine. This is really only intended be used when you are writing/updating a ton of docs and want to preview the changes locally.
By default the server will run at: <a href="http://localhost:8085" target="_blank">http://localhost:8085</a>
**To use the optional Grunt command you will need:**
* Node.js
* npm
* Grunt.js
* PHP 5.6 or greater
This project contains a package.json file, so once you have the requirements installed, you can simply run a `npm install` and then `grunt` in the projects folder to start the local web server. By default the server will run at: <a href="http://localhost:8085" target="_blank">http://localhost:8085</a>
This is really only intended be used when you are writing/updating a ton of docs and want to preview the changes locally.
## Generating a set of static files
@ -196,8 +193,8 @@ daux --source=docs --destination=static
If you have set up a local or remote IIS web site, you may need a `web.config` with:
* A rewrite configuration, for handling clean urls.
* A mime type handler for less files, if using a custom theme.
- A rewrite configuration, for handling clean urls.
- A mime type handler for less files, if using a custom theme.
### Clean URLs
@ -205,47 +202,46 @@ The `web.config` needs an entry for `<rewrite>` under `<system.webServer>`:
```xml
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="false" />
</rule>
</rules>
</rewrite>
</system.webServer>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add
input="{REQUEST_FILENAME}"
matchType="IsFile"
negate="true"
/>
<add
input="{REQUEST_FILENAME}"
matchType="IsDirectory"
negate="true"
/>
</conditions>
<action
type="Rewrite"
url="index.php"
appendQueryString="false"
/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
```
To use clean URLs on IIS 6, you will need to use a custom URL rewrite module, such as [URL Rewriter](http://urlrewriter.net/).
## Docker
A docker configuration is also provided to run daux within a container, you can either run daux with php5 or php7.
```
cd docker
docker-compose -f docker-compose.7.yml up -d
```
You can then point your browser to http://localhost:8086
## PHP Requirements
Daux.io is compatible with PHP 5.6 and up.
The reason is because some dependencies we have (mainly Symfony and Guzzle) do not support php 5.4 anymore.
Daux.io is compatible with the [officially supported](https://www.php.net/supported-versions.php) PHP versions; 7.2.0 and up.
### Extensions
PHP Needs the following extension to work : `php-mbstring` and `php-xml`.
Daux.io needs the following PHP extensions 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

Datei anzeigen

@ -1,17 +0,0 @@
#!/usr/bin/env php
<?php
require __DIR__.'/../vendor/autoload.php';
use Todaymade\Daux\Compiler;
error_reporting(-1);
ini_set('display_errors', 1);
try {
$compiler = new Compiler();
$compiler->compile();
} catch (\Exception $e) {
echo 'Failed to compile phar: ['.get_class($e).'] '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine();
exit(1);
}

Datei anzeigen

@ -1,5 +1,5 @@
{
"name": "daux/daux.io",
"name": "d3/daux.io",
"type": "project",
"license": "MIT",
"description": "Documentation generator that uses a simple folder structure and Markdown files to create custom documentation on the fly",
@ -17,17 +17,22 @@
],
"bin": ["bin/daux"],
"require": {
"php": ">=7.2",
"guzzlehttp/guzzle": "~6.0",
"league/commonmark": "^0.15",
"league/commonmark": "^1.0.0",
"league/plates": "~3.1",
"myclabs/deep-copy": "^1.5",
"php": ">=5.6",
"symfony/console": "~3.0",
"symfony/finder": "~3.0",
"webuni/commonmark-table-extension": "0.6.*",
"scrivo/highlight.php": "^9.15",
"symfony/console": "^5.0",
"symfony/http-foundation": "^5.0",
"symfony/mime": "^5.0",
"symfony/polyfill-intl-icu": "^1.10",
"symfony/process": "^5.0",
"webuni/front-matter": "^1.0.0",
"symfony/process": "^3.1",
"symfony/http-foundation": "^3.3"
"ext-json": "*"
},
"suggest":{
"ext-intl": "Allows to translate the modified at date"
},
"autoload": {
"psr-4": {
@ -38,7 +43,12 @@
"justinwalsh/daux.io": "*"
},
"require-dev": {
"phpunit/phpunit": "~5",
"mikey179/vfsStream": "^1.6"
"mikey179/vfsstream": "^1.6"
},
"scripts": {
"test": "build/phpunit",
"test:coverage-html": "build/phpunit --coverage-html=build/coverage",
"lint": "build/php-cs-fixer fix --config=.php_cs --dry-run -v",
"lint:fix": "build/php-cs-fixer fix --config=.php_cs"
}
}

2496
composer.lock generiert

Datei-Diff unterdrückt, da er zu groß ist Diff laden

67
crafty.config.js Normale Datei
Datei anzeigen

@ -0,0 +1,67 @@
module.exports = {
browsers: "defaults, not op_mini all",
presets: [
"@swissquote/crafty-preset-babel",
"@swissquote/crafty-runner-rollup",
"@swissquote/crafty-preset-postcss",
"@swissquote/crafty-runner-gulp"
],
destination_css: ".",
destination_js: ".",
stylelint_pattern: [
"src/css/**/*.scss",
"!*.min.css",
"!**/vendor/**/*.scss"
],
stylelint: {
rules: {
"swissquote/no-type-outside-scope": null,
"plugin/no-unsupported-browser-features": null
}
},
js: {
search: {
runner: "rollup",
format: "iife",
source: "src/js/search/index.js",
destination: "daux_libraries/search.min.js"
},
theme_daux: {
runner: "rollup",
format: "iife",
source: "src/js/theme_daux/index.js",
destination: "themes/daux/js/daux.min.js"
}
},
css: {
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: "src/css/theme_daux/theme-green.scss",
destination: "themes/daux/css/theme-green.min.css",
watch: ["src/css/**/*.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: "src/css/theme_daux/theme-red.scss",
destination: "themes/daux/css/theme-red.min.css",
watch: ["src/css/**/*.scss"]
},
daux_singlepage: {
source: "src/css/theme_daux_singlepage/main.scss",
destination: "themes/daux_singlepage/css/main.min.css",
watch: ["src/css/**/*.scss"]
}
},
postcss(crafty, config, bundle) {
// Add postcss-page-break
config.processor("postcss-page-break").before("autoprefixer");
}
};

BIN
daux.phar

Binäre Datei nicht angezeigt.

192
daux/d3processor.php Normale Datei
Datei anzeigen

@ -0,0 +1,192 @@
<?php
namespace Todaymade\Daux\Extension;
use League\CommonMark\Block\Element\BlockQuote;
use League\CommonMark\Block\Element\Document;
use League\CommonMark\Block\Element\Paragraph;
use League\CommonMark\Environment;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\InlineParserContext;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Parser\AbstractInlineParser;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
USE League\CommonMark\Block\Element\AbstractBlock;
USE League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Code;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Util\Configuration;
use Todaymade\Daux\Daux;
use Symfony\Component\Console\Output\NullOutput;
class d3Parser extends AbstractInlineParser
{
public function getCharacters() {
return ['v', 'V'];
}
public function parse(InlineParserContext $inlineContext)
{
$cursor = $inlineContext->getCursor();
if ($cursor->match('/D3/')) {
$inlineContext->getContainer()->appendChild(new Code('d3logo'));
return true;
}
return false;
}
}
class d3BlockQuoteRenderer implements BlockRendererInterface
{
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
if (!($block instanceof BlockQuote)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$attrs = [];
foreach ($block->getData('attributes', []) as $key => $value) {
$attrs[$key] = $htmlRenderer->escape($value, true);
}
$filling = $htmlRenderer->renderBlocks($block->children());
if ($filling === '') {
return new HtmlElement('blockquote', $attrs, $htmlRenderer->getOption('inner_separator', "\n"));
}
if (stristr($filling, '[!!]')) {
$attrs['class'] = isset($attrs['class']) ? $attrs['class'].' alert alert-danger' : 'alert alert-danger';
$filling = "<i class='fas fa-exclamation-circle'></i> ".trim(str_replace('[!!]', '', $filling));
}
if (stristr($filling, '[!]')) {
$attrs['class'] = isset($attrs['class']) ? $attrs['class'].' alert alert-warning' : 'alert alert-warning';
$filling = "<i class='fas fa-exclamation-triangle'></i> ".trim(str_replace('[!]', '', $filling));
}
if (stristr($filling, '[i]')) {
$attrs['class'] = isset($attrs['class']) ? $attrs['class'].' alert alert-info' : 'alert alert-info';
$filling = "<i class='fas fa-info-circle'></i> ".trim(str_replace('[i]', '', $filling));
}
return new HtmlElement(
'blockquote',
$attrs,
$htmlRenderer->getOption('inner_separator', "\n") . $filling . $htmlRenderer->getOption('inner_separator', "\n")
);
}
}
class d3ParagraphRenderer implements BlockRendererInterface
{
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
if (!($block instanceof Paragraph)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$pattern1 = '/\[\s*?(.{3,})\s*?\]/Uis';
$replace1 = '<span class="navi_element">\\1</span>';
if ($inTightList) {
$content = $htmlRenderer->renderInlines($block->children());
$content = preg_replace($pattern1, $replace1, $content);
return $content;
} else {
$attrs = [];
foreach ($block->getData('attributes', []) as $key => $value) {
$attrs[$key] = $htmlRenderer->escape($value, true);
}
$content = $htmlRenderer->renderInlines($block->children());
$content = preg_replace($pattern1, $replace1, $content);
return new HtmlElement('p', $attrs, $content);
}
}
}
class d3DocumentRenderer implements BlockRendererInterface
{
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
if (!($block instanceof Document)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$wholeDoc = $htmlRenderer->renderBlocks($block->children());
$output = new NullOutput();
$daux = new Daux(Daux::STATIC_MODE, $output);
foreach ($_SERVER['argv'] as $arg) {
if (stristr($arg, '--source=')) {
$docsdir = trim(str_replace('--source=', '', $arg));
$daux->getParams()->setDocumentationDirectory($docsdir);
}
}
$daux->initializeConfiguration();
$params = $daux->getParams();
if (isset($params['variables'])) {
$variables = $params['variables'];
if (isset($variables) && is_array($variables) && count($variables)) {
foreach ($variables as $varname => $varvalue) {
$pattern = '/{\$'.$varname.'}/mU';
$wholeDoc = preg_replace($pattern, $varvalue, $wholeDoc);
}
}
}
return $wholeDoc === '' ? '' : $wholeDoc . "\n";
}
}
class d3TextRenderer implements InlineRendererInterface
{
/**
* @var Configuration
*/
protected $config;
/**
* @param AbstractInline $inline
* @param ElementRendererInterface $htmlRenderer
* @return HtmlElement|mixed|string
* @throws \Todaymade\Daux\Exception
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Text)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
}
$content = $htmlRenderer->escape($inline->getContent());
$search = array(
'D3', 'D³', 'D&sup3;'
);
$replace = "<i class='fab fa-d3 d3fa-color-blue'></i>";
$content = str_replace($search, $replace, $content);
return $content;
}
}
class d3processor extends \Todaymade\Daux\Processor
{
public function extendCommonMarkEnvironment(Environment $environment)
{
// format important and info code blocks
$environment->addBlockRenderer('League\CommonMark\Block\Element\BlockQuote', new d3BlockQuoteRenderer());
$environment->addBlockRenderer('League\CommonMark\Block\Element\Paragraph', new d3ParagraphRenderer());
$environment->addBlockRenderer('League\CommonMark\Block\Element\Document', new d3DocumentRenderer());
$environment->addInlineRenderer('League\CommonMark\Inline\Element\Text', new d3TextRenderer());
}
}

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -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;
}
@ -16,7 +9,7 @@ body.with-search {
margin: 0;
z-index: 100;
position:absolute;
position: absolute;
top: 0;
left: 0;
bottom: 0;
@ -27,18 +20,17 @@ body.with-search {
.SearchResultsBackdrop {
z-index: 90;
width:100%;
width: 100%;
position:absolute;
position: absolute;
top: 0;
left: 0;
bottom: 0;
background: #000;
opacity: .6;
opacity: 0.6;
}
.homepage .SearchResults,
.homepage .SearchResultsBackdrop {
top: 50px;
@ -54,11 +46,12 @@ body.with-search {
}
.SearchResults__warning {
font-weight:300;
font-size:15px;
font-weight: 300;
font-size: 15px;
line-height: 1.6;
color: #555;
margin: 7px 0;
clear: both;
}
.SearchResults__warning a {
@ -71,8 +64,8 @@ body.with-search {
}
.SearchResults__count {
font-weight:300;
font-size:15px;
font-weight: 300;
font-size: 15px;
line-height: 1.7;
color: #555;
}
@ -86,12 +79,12 @@ body.with-search {
cursor: pointer;
padding: 0;
margin: 0;
line-height: .8em;
line-height: 0.8em;
}
.SearchResults__title {
font-weight:300;
font-size:21px;
font-weight: 300;
font-size: 21px;
line-height: 1.7;
margin-top: 23px;
}
@ -106,8 +99,8 @@ body.with-search {
}
.SearchResults__url {
font-weight:300;
font-size:14px;
font-weight: 300;
font-size: 14px;
line-height: 1.9;
word-wrap: break-word;
hyphens: auto;
@ -123,8 +116,8 @@ body.with-search {
}
.SearchResults__text {
font-weight:300;
font-size:15px;
font-weight: 300;
font-size: 15px;
line-height: 1.6;
color: #555;
word-wrap: break-word;
@ -133,8 +126,8 @@ body.with-search {
}
.SearchResults__debug {
font-weight:300;
font-size:13px;
font-weight: 300;
font-size: 13px;
line-height: 1.6;
color: #555;
margin: 5px 0;
@ -164,7 +157,6 @@ body.with-search {
border: 1px solid #e2e2e2;
}
/* spinner */
@media (min-width: 650px) {
@ -175,8 +167,3 @@ body.with-search {
margin-left: -325px;
}
}

2
daux_libraries/search.min.js vendored Normale Datei

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -12,7 +12,7 @@ services:
- phpserver
phpserver:
image: php:7.0-fpm
image: php:7.4-fpm
working_dir: /var/www/
volumes:
- ../:/var/www/

Datei anzeigen

@ -6,42 +6,48 @@
### For Authors
* [Auto Generated Navigation / Page sorting](01_Features/Navigation_and_Sorting.md)
* [Internal documentation links](01_Features/Internal_links.md)
* [CommonMark compliant](01_Features/CommonMark_compliant.md)
* [Auto created homepage/landing page](01_Features/Landing_page.md)
* [Multiple Output Formats](01_Features/Multiple_Output_Formats.md)
* [Multiple Languages Support](01_Features/Multilanguage.md)
* [No Build Step](01_Features/Live_mode.md)
* [Static Output Generation](01_Features/Static_Site_Generation.md)
* [Table of Contents](01_Features/Table_of_contents.md)
- [Auto Generated Navigation / Page sorting](01_Features/Navigation_and_Sorting.md)
- [Internal documentation links](01_Features/Internal_links.md)
- [CommonMark compliant](01_Features/CommonMark_compliant.md)
- [Auto created homepage/landing page](01_Features/Landing_page.md)
- [Multiple Output Formats](01_Features/Multiple_Output_Formats.md)
- [Multiple Languages Support](01_Features/Multilanguage.md)
- [No Build Step](01_Features/Live_mode.md)
- [Static Output Generation](01_Features/Static_Site_Generation.md)
- [Table of Contents](01_Features/Table_of_contents.md)
### For Developers
* [Auto Syntax Highlighting](01_Features/Auto_Syntax_Highlight.md)
* [Extend Daux.io with Processors](01_For_Developers/Creating_a_Processor.md)
* Full access to the internal API to create new pages programatically
* Work with pages metadata
- [Auto Syntax Highlighting](01_Features/Auto_Syntax_Highlight.md)
- [Extend Daux.io with Processors](01_For_Developers/Creating_a_Processor.md)
- Full access to the internal API to create new pages programatically
- Work with pages metadata
### For Marketing
* 100% Mobile Responsive
* 4 Built-In Themes or roll your own
* Functional, Flat Design Style
* Optional code float layout
* Shareable/Linkable SEO Friendly URLs
* Supports Google Analytics and Piwik Analytics
- 100% Mobile Responsive
- 4 Built-In Themes or roll your own
- Functional, Flat Design Style
- Optional code float layout
- Shareable/Linkable SEO Friendly URLs
- Supports Google Analytics and Piwik Analytics
## Demos
This is a list of sites using Daux.io:
* [Daux.io](https://dauxio.github.io/)
* [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/)
- 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/)
_ [DrupalGap](http://docs.drupalgap.org/8/)
- [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.
@ -54,7 +60,7 @@ Do you use Daux.io? Send us a pull request or open an [issue](https://github.com
If you have PHP and Composer installed, you can install the dependency
```bash
composer global require dauxio/daux.io
composer global require daux/daux.io
# Next to your `docs` folder, run
daux generate
@ -62,7 +68,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
@ -74,10 +80,10 @@ docker run --rm -it -w /build -v "$PWD":/build daux/daux.io daux
Any parameter valid in the PHP version is valid in the Docker version
### Writing pages
Creating new pages is very easy:
1. Create a markdown file (`*.md` or `*.markdown`)
2. Start writing
@ -91,14 +97,14 @@ You must use underscores instead of spaces. Here are some example file names and
**Good:**
* 01_Getting_Started.md = Getting Started
* API_Calls.md = API Calls
* 200_Something_Else-Cool.md = Something Else-Cool
* _5_Ways_to_Be_Happy.md = 5 Ways To Be Happy
- 01_Getting_Started.md = Getting Started
- API_Calls.md = API Calls
- 200_Something_Else-Cool.md = Something Else-Cool
- \_5_Ways_to_Be_Happy.md = 5 Ways To Be Happy
**Bad:**
* File Name With Space.md = FAIL
- File Name With Space.md = FAIL
### See your pages
@ -122,9 +128,9 @@ Upload your files to an apache / nginx server and see your documentation
Daux.io is extendable and comes by default with three export formats:
- Export to HTML, same as the website, but can be hosted without PHP.
- Export all documentation in a single HTML page
- Upload to your Atlassian Confluence server.
- Export to HTML, same as the website, but can be hosted without PHP.
- Export all documentation in a single HTML page
- Upload to your Atlassian Confluence server.
[See a detailed feature comparison matrix](01_Features/Multiple_Output_Formats.md)
@ -138,20 +144,13 @@ 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.
The reason is because some dependencies we have do not support php 5.5 anymore.
Daux.io is compatible with the [officially supported](https://www.php.net/supported-versions.php) PHP versions; 7.2.0 and up.
### 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)
## Known Issues
- __Windows UTF-8 files support__ Files with UTF-8 characters cannot be handled on windows with PHP5, PHP7 should work fine.
Daux.io needs the following PHP extensions 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.
## Support

Datei anzeigen

@ -1,17 +1,14 @@
As we support CommonMark, a broad range of markdown features is available to you.
Many of the features shown below were known as Github Flavored Markdown.
We all like making lists
------------------------
## We all like making lists
The above header should be an H2 tag. Now, for a list of fruits:
* Red Apples
* Purple Grapes
* Green Kiwifruits
- Red Apples
- Purple Grapes
- Green Kiwifruits
Let's get crazy:
@ -27,18 +24,17 @@ Let's get crazy:
What about some code **in** a list? That's insane, right?
1. In Ruby you can map like this:
1. In Ruby you can map like this:
['a', 'b'].map { |x| x.uppercase }
2. In Rails, you can do a shortcut:
2. In Rails, you can do a shortcut:
['a', 'b'].map(&:uppercase)
Some people seem to like definition lists
I am a robot
------------
## I am a robot
Maybe you want to print `robot` to the console 1000 times. Why not?
@ -54,8 +50,7 @@ How about we throw some angle braces and ampersands in there?
&copy; 2004 Foo Corporation
</div>
Set in stone
------------
## Set in stone
Preformatted blocks are useful for ASCII art:
@ -63,7 +58,7 @@ Preformatted blocks are useful for ASCII art:
,-.
, ,-. ,-.
/ \ ( )-( )
\ | ,.>-( )-<
\ | ,.>-( )-&lt;
\|,' ( )-( )
Y ___`-' `-'
|/__/ `-'
@ -73,8 +68,7 @@ Preformatted blocks are useful for ASCII art:
___|_____________
</pre>
Playing the blame game
----------------------
## Playing the blame game
If you need to blame someone, the best way to do so is by quoting them:
@ -92,26 +86,23 @@ Or perhaps someone a little less eloquent:
> just put me under the spot here, and maybe I'm not as quick on my feet
> as I should be in coming up with one.
Table for two
-------------
## Table for two
ID | Name | Rank
---|:------:|------:
1 | Tom Preston-Werner | Awesome
2 | Albert Einstein | Nearly as awesome
| ID | Name | Rank |
| --- | :----------------: | ----------------: |
| 1 | Tom Preston-Werner | Awesome |
| 2 | Albert Einstein | Nearly as awesome |
Crazy linking action
--------------------
## Crazy linking action
I get 10 times more traffic from [Google] [1] than from
[Yahoo] [2] or [MSN] [3].
I get 10 times more traffic from [Google][1] than from
[Yahoo][2] or [MSN][3].
[1]: http://google.com/ "Google"
[2]: http://search.yahoo.com/ "Yahoo Search"
[3]: http://search.msn.com/ "MSN Search"
[1]: http://google.com/ "Google"
[2]: http://search.yahoo.com/ "Yahoo Search"
[3]: http://search.msn.com/ "MSN Search"
Images
------
## Images
Here's an image.
@ -119,4 +110,4 @@ Here's an image.
Note: to use images on a landing page (index.md), prefix the image URL with the name of the directory it appears in, omitting the numerical prefix used to order the sections. For example in this section, to display this image on the landing page (index.md), the URL for the image would be "Features/sampleimage.png" to display the same image.
*View the [source of this content](https://github.com/dauxio/daux.io/blob/master/docs/01_Features/CommonMark_compliant.md).*
_View the [source of this content](https://github.com/dauxio/daux.io/blob/master/docs/01_Features/CommonMark_compliant.md)._

Datei anzeigen

@ -1,4 +1,3 @@
As you can see on the top of this page, you can add "Edit on Github" links to your pages, this feature can be enabled with a single parameter.
The value has to be the path to the root of your documentation folder in your repository.
@ -7,12 +6,11 @@ In the value you see below, Daux's documentation is in the `docs` folder in the
Daux.io will handle the rest
```json
{
"html": {
"edit_on_github": "dauxio/daux.io/blob/master/docs"
}
"html": {
"edit_on_github": "dauxio/daux.io/blob/master/docs"
}
}
```
@ -22,14 +20,13 @@ While GitHub is the most popular, it isn't the only, collaborative VCS out there
As long as you can refer your files by a URL, you can create an edit link for your VCS with the following configuration:
```json
{
"html": {
"edit_on": {
"name": "Bitbucket",
"basepath": "https://bitbucket.org/dauxio/daux.io/src/master/docs"
"html": {
"edit_on": {
"name": "Bitbucket",
"basepath": "https://bitbucket.org/dauxio/daux.io/src/master/docs"
}
}
}
}
```

Datei anzeigen

@ -1,18 +1,28 @@
---
description: With Front Matter you can customize your pages even further.
keywords: "Front Matter, Customize, Title, Description, Keywords, Author"
author: Daux.io Team
---
To customize your pages even further, you can add a Front Matter to your files.
Front Matter is a block you add at the top of your file and looks like this:
---
title: Hallo Welt
keywords: "Hallo, Hello, Welt, World, Erde, Earth"
author: German Daux.io Team
date: 12th December 1984
---
## Changing the title
The only implemented customization right now is the override of the title.
If your file is named "Hello_World_de.md" and your front matter is the one displayed above, you will get a page named "Hallo Welt"
## Search Engine Optimization
For a better **SEO** experience you can change the `description`, `keywords` and `author` meta tags.
## For Developers
You can then access this information in each `Content` with `$content->getAttributes()`
You can then access this information in each `Content` with `$content->getAttributes()` or with `$page['attributes']` in a template.

Datei anzeigen

@ -2,9 +2,9 @@ If you want to create a beautiful landing page for your project, create a `_inde
```json
{
"title": "Daux.io",
"tagline": "The Easiest Way To Document Your Project",
"image": "app.png"
"title": "Daux.io",
"tagline": "The Easiest Way To Document Your Project",
"image": "app.png"
}
```
@ -14,8 +14,8 @@ To disable the automatic landing page, you can set `auto_landing` to false in th
```json
{
"html": {
"auto_landing": false
}
"html": {
"auto_landing": false
}
}
```

Datei anzeigen

@ -10,7 +10,6 @@ The easiest is to use PHP's built-in server.
For that i've included a short command, run `daux serve` in the projects folder to start the local web server. By default the server will run at: <a href="http://localhost:8085" target="_blank">http://localhost:8085</a>
## Running Remotely
### Clean URLs configuration
@ -20,15 +19,15 @@ To enable the same, set the toggle in the `config.json` file in the `/docs` fold
```json
{
"live": {
"clean_urls": true
}
"live": {
"clean_urls": true
}
}
```
### Apache
Copy the files from the repo to a web server that can run PHP 5.6 or greater.
Copy the files from the repo to a web server that can run PHP 7.2.0 or newer.
There is an included `.htaccess` for Apache web server.
@ -70,8 +69,8 @@ server {
If you have set up a local or remote IIS web site, you may need a `web.config` with:
* A rewrite configuration, for handling clean urls.
* A mime type handler for less files, if using a custom theme.
- A rewrite configuration, for handling clean urls.
- A mime type handler for less files, if using a custom theme.
### Clean URLs
@ -79,21 +78,51 @@ The `web.config` needs an entry for `<rewrite>` under `<system.webServer>`:
```xml
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="false" />
</rule>
</rules>
</rewrite>
</system.webServer>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add
input="{REQUEST_FILENAME}"
matchType="IsFile"
negate="true"
/>
<add
input="{REQUEST_FILENAME}"
matchType="IsDirectory"
negate="true"
/>
</conditions>
<action
type="Rewrite"
url="index.php"
appendQueryString="false"
/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
```
To use clean URLs on IIS 6, you will need to use a custom URL rewrite module, such as [URL Rewriter](http://urlrewriter.net/).
## Docker
This is not meant for production use, but you can bundle your documentation in Daux's docker container
```
FROM daux/daux.io
WORKDIR /daux/
COPY docs/ /daux/docs/
EXPOSE 80
ENTRYPOINT [ "php", "-S", "0.0.0.0:80", "index.php" ]
```
When you add this to a `Dockerfile` and run `docker build --name my-daux-doc .` and then `docker --rm run -p 8000:80 my-daux-doc`
You can access your documentation at `localhost:8000`

Datei anzeigen

@ -4,11 +4,12 @@ Add this to your config.json :
```json
{
"languages": { "en": "English", "de": "German" }
"languages": { "en": "English", "de": "German" }
}
```
You will the need separate directories for each language in `docs/` folder.
```
├── docs/
│ ├── _index.md

Datei anzeigen

@ -1,18 +1,22 @@
Daux.io is extendable and comes by default with three export formats:
- Export to HTML
- Export all documentation in a single HTML page
- Upload to your Atlassian Confluence server
- Export to HTML
- Export all documentation in a single HTML page
- Upload to your Atlassian Confluence server
## Feature Matrix
Feature | HTML | Single Page HTML | Confluence
--------------:|:----:|:----------------:|:----------:
Multilanguage | √ | X (Planned) | X
Landing Pages | √ | X | X
Index Pages | √ | √ | √
Internal Links | √ | X (Planned) | √
Code Highlight | √ | X (Planned) | √ (Using macros)
Live Mode | √ | X | X
Pages Ordering | √ | √ | X (API Limitation)
Google / Piwik analytics | √ | √ | √ (Configured on Conflence)
| Feature | HTML | Single Page HTML | Confluence |
| -----------------------: | :--: | :--------------: | :-------------------------: |
| Multilanguage | √ | X (Planned) | X |
| Landing Pages | √ | X | X |
| Index Pages | √ | √ | √ |
| Internal Links | √ | X (Planned) | √ |
| Code Highlight | √ | X (Planned) | √ (Using macros) |
| Live Mode | √ | X | X |
| Pages Ordering | √ | √ | X (API Limitation) |
| Google / Piwik analytics | √ | √ | √ (Configured on Conflence) |
## Confluence Example
You can see this documentation uploaded to Confluence : https://dauxio.atlassian.net/wiki/spaces/DOC/overview

Datei anzeigen

@ -1,4 +1,3 @@
## Navigation
The navigation is generated automatically with all pages that end with `.md` or `.markdown`
@ -10,6 +9,23 @@ if you wish to have one defined all you need to do is add an `index.md` file to
For example, `/docs/02_Examples` has a landing page for that section since there exists a `/docs/02_Examples/index.md` file.
## Sorting
To sort your files and folders in a specific way, you can prefix them with a number and underscore, e.g. `/docs/01_Hello_World.md` and `/docs/05_Features.md` This will list *Hello World* before *Features*, overriding the default alpha-numeric sorting. The numbers will be stripped out of the navigation and urls. For the file `6 Ways to Get Rich`, you can use `/docs/_6_Ways_to_Get_Rich.md`
You might also wish to stick certain links to the bottom of a page. You can do so by appending a '-' to the start of the filename, e.g. a new file `/docs/-Contact_Us.md` will always appear at the bottom of the current list. Weights can also be added to further sort the bottom entries. e.g. `/docs/-01_Coming.md` will appear before `/docs/-02_Soon.md` but both will only appear after all positive or non-weighted files.
To sort your files and folders in a specific way, you can prefix them with a number and underscore, e.g. `/docs/01_Hello_World.md` and `/docs/05_Features.md`.
This will list _Hello World_ before _Features_, overriding the default alpha-numeric sorting.
The numbers will be stripped out of the navigation and urls. For the file `6 Ways to Get Rich`, you can use `/docs/_6_Ways_to_Get_Rich.md`
You might also wish to stick certain links to the bottom of a page.
You can do so by prefixing the file name with a '-', e.g. a new file `/docs/-Contact_Us.md` will always appear at the bottom of the current list.
Weights can also be added to further sort the bottom entries. e.g. `/docs/-01_Coming.md` will appear before `/docs/-02_Soon.md` but both will only appear after all positive or non-weighted files.
It works the same for files prefixed with `+`.
Page order priorities are like this:
- `+` in front of the filename and numbers in front
- `+` in front of the filename
- The index page
- Numbers in the front
- Pages without prefix
- `-` in front of the filename and numbers in front
- `-` in front of the filename

Datei anzeigen

@ -6,8 +6,8 @@ To enable the generated search, you can set `search` to true in the `html` secti
```json
{
"html": {
"search": true
}
"html": {
"search": true
}
}
```

Datei anzeigen

@ -1,9 +1,8 @@
If you don't want to serve the live version of your site, you can also generate files, these can be one of the three supported formats :
If you don't want to serve the live version of your site, you can also generate files, these can be one of the three supported formats :
- HTML output
- Single page HTML output
- Atlassian Confluence upload
- HTML output
- Single page HTML output
- Atlassian Confluence upload
Generating a complete set of pages, with navigation
@ -13,7 +12,7 @@ daux --destination=[Output Directory Relative Direction]
## Options
For more options, run
For more options, run
```bash
daux generate --help
@ -32,7 +31,7 @@ daux --format=html
### Specify a processor
A processor can be specified through the `--processor` option, this should be the name of a class inside the `Todaymade\Daux\Extension` namespace.
A processor can be specified through the `--processor` option, this should be the name of a class inside the `Todaymade\Daux\Extension` namespace.
By running :

Datei anzeigen

@ -18,10 +18,8 @@ You can enable this feature in your configuration
```json
{
"html": {
"auto_toc": true
}
"html": {
"auto_toc": true
}
}
```

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei anzeigen

@ -1,2 +1,3 @@
### This is a landing page for the Examples section
Adding a landing page is pretty simple, all you need to do is add an "index.md" file to the related folder.
Adding a landing page is pretty simple, all you need to do is add an "index.md" file to the related folder.

Datei anzeigen

@ -1,21 +1,23 @@
__Table of contents__
**Table of contents**
[TOC]
## Configuring the connection
The connection requires three parameters `base_url`, `user` and `pass`. While `user` and `pass` don't really need an explanation, for `base_url` you need to set the path to the server without `rest/api`, this will be added automatically.
```json
{
"confluence": {
"base_url": "http://my_confluence_server.com/",
"user" : "my_username",
"pass" : "my_password"
}
"confluence": {
"base_url": "http://my_confluence_server.com/",
"user": "my_username",
"pass": "my_password"
}
}
```
## Where to upload
Now that the connection is defined, you need to tell it where you want your documentation to be uploaded.
For that you need a `space_id` (name that appears at the beginning of the urls) and an `ancestor_id`; the id of the page that will be the parent of the documentation's homepage.
@ -24,10 +26,10 @@ You can obtain the `ancestor_id` id by editing the page you want to define as a
```json
{
"confluence": {
"space_id": "my_space",
"ancestor_id": 50370632
}
"confluence": {
"space_id": "my_space",
"ancestor_id": 50370632
}
}
```
@ -36,20 +38,22 @@ You can also provide a `root_id` instead of an `ancestor_id` in this case, you s
You can use that when you're uploading your documentation to the root of a Confluence Space or if your page already exists.
## Prefix
Because confluence can't have two pages with the same name in a space, I recommend you define a prefix for your pages.
```json
{
"confluence": { "prefix": "DAUX -" }
"confluence": { "prefix": "DAUX -" }
}
```
## Update threshold
To make the upload quicker, we try to determine if a page changed or not, first with a strict comparison and if it's not completely identical, we compute the difference.
```json
{
"confluence": { "update_threshold": 1 }
"confluence": { "update_threshold": 1 }
}
```
@ -59,22 +63,22 @@ By default the threshold is 2%.
Setting the value to `0` disables the feature altogether.
## Delete old pages
When a page is renamed, there is no way to tell it was renamed, so when uploading to Confluence, the page will be uploaded and the old page will stay here.
By default, it will inform you that some pages aren't needed anymore and you can delete them by hand.
```json
{
"confluence": { "delete": true }
"confluence": { "delete": true }
}
```
By setting `delete` to `true` (or running `daux.phar` with the `--delete` flag) you tell the generator that it can safely delete the pages.
By setting `delete` to `true` (or running `daux` with the `--delete` flag) you tell the generator that it can safely delete the pages.
## Information message
When you create your page. there is no indication that the upload process will override the content of the pages.
It happens sometimes that users edit the pages to add / fix an information.
@ -83,9 +87,9 @@ You can add a text in a "information" macro on top of the document by setting th
```json
{
"confluence": {
"header": "These pages are updated automatically, your changes will be overriden."
}
"confluence": {
"header": "These pages are updated automatically, your changes will be overriden."
}
}
```

Datei anzeigen

@ -1,24 +1,26 @@
__Table of contents__
**Table of contents**
[TOC]
## Analytics
### Google Analytics
This will embed the google analytics tracking code.
```json
{
"html": { "google_analytics": "UA-XXXXXXXXX-XX" }
"html": { "google_analytics": "UA-XXXXXXXXX-XX" }
}
```
### Piwik Analytics
This will embed the piwik tracking code.
```json
{
"html": { "piwik_analytics": "my-url-for-piwik.com" }
"html": { "piwik_analytics": "my-url-for-piwik.com" }
}
```
@ -26,120 +28,130 @@ You can Also give a specific Piwik ID as well.
```json
{
"html": { "piwik_analytics_id": "43" }
"html": { "piwik_analytics_id": "43" }
}
```
### Plausible Analytics
This will embed the https://plausible.io/ tracking code.
```json
{
"html": { "plausible_domain": "daux.io" }
}
```
## Automatic Table of Contents
You can add a table of contents on each page automatically, read about it [here](../01_Features/Table_of_contents.md)
## Buttons
You can add buttons to the landing page.
```json
{
"html": {
"buttons": {
"My Website": "http://example.com"
"html": {
"buttons": {
"My Website": "http://example.com"
}
}
}
}
```
## Breadcrumb titles
Daux.io provides the option to present page titles as breadcrumb navigation.
You can *optionally* specify the separator used for breadcrumbs.
Daux.io provides the option to present page titles as breadcrumb navigation.
You can _optionally_ specify the separator used for breadcrumbs.
```json
{
"html": {
"breadcrumbs": true,
"breadcrumb_separator" : " > "
}
}
```
## 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 }
"html": {
"breadcrumbs": true,
"breadcrumb_separator": " > "
}
}
```
## 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.
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`.
```json
{
"html": { "date_modified": false }
"html": { "date_modified": false }
}
```
## GitHub Repo
Add a 'Fork me on GitHub' ribbon.
```json
{
"html": { "repo": "dauxio/daux.io" }
"html": { "repo": "dauxio/daux.io" }
}
```
## Inherit Index
This feature will instructs the navigation generator to seek the first available file to use when there is no index in a folder.
```json
{
"html": { "inherit_index": true }
"html": { "inherit_index": true }
}
```
## Jump buttons
You can have previous/next buttons on each page.
They can be disabled by setting `jump_buttons` to `false`.
```json
{
"html": { "jump_buttons": false }
"html": { "jump_buttons": false }
}
```
## Landing page
The automatic landing page can be disabled through the `auto_landing` option, read about it [here](../01_Features/Landing_page.md)
The automatic landing page can be disabled through the `auto_landing` option, read about it [here](../01_Features/Landing_page.md)
## Links
Include custom links in the sidebar.
```json
{
"html": {
"links": {
"GitHub Repo": "https://github.com/dauxio/daux.io",
"Help/Support/Bugs": "https://github.com/dauxio/daux.io/issues",
"Made by Todaymade": "http://todaymade.com"
"html": {
"links": {
"GitHub Repo": "https://github.com/dauxio/daux.io",
"Help/Support/Bugs": "https://github.com/dauxio/daux.io/issues",
"Made by Todaymade": "http://todaymade.com"
}
}
}
}
```
## Search
Daux has an embedded search engine read all about it [here](../01_Features/Search.md)
## Themes
We have 4 built-in Bootstrap themes. To use one of the themes, just set the `theme` option to one of the following:
* daux-blue
* daux-green
* daux-navy
* daux-red
- daux-blue
- daux-green
- daux-navy
- daux-red
```json
{
"html": { "theme": "daux-blue" }
"html": { "theme": "daux-blue" }
}
```
@ -147,25 +159,27 @@ To use a custom theme, just copy over the theme folder into the `themes` directo
```json
{
"html": { "theme": "new-theme" }
"html": { "theme": "new-theme" }
}
```
## Toggling Code Blocks
Some users might wish to hide the code blocks & view just the documentation.
Some users might wish to hide the code blocks & view just the documentation.
By setting the `toggle_code` property to `true`, you can offer a toggle button on the page.
```json
{
"html": { "toggle_code": true }
"html": { "toggle_code": true }
}
```
## Twitter
Include twitter follow buttons in the sidebar.
```json
{
"html": { "twitter": ["justin_walsh", "todaymade"] }
"html": { "twitter": ["justin_walsh", "todaymade"] }
}
```

Datei anzeigen

@ -1,91 +1,100 @@
To customize the look and feel of your documentation, you can create a `config.json` file in the of the `/docs` folder. The `config.json` file is a JSON object that you can use to change some of the basic settings of the documentation.
__Table of contents__
**Table of contents**
[TOC]
### Title
Change the title bar in the docs
```json
{
"title": "Daux.io"
"title": "Daux.io"
}
```
### Tagline
Change the tagline bar in the docs
```json
{
"tagline": "The Easiest Way To Document Your Project"
"tagline": "The Easiest Way To Document Your Project"
}
```
### Author
Change the documentation's author
```json
{
"author": "Stéphane Goetz"
"author": "Stéphane Goetz"
}
```
### Image
An image to show on the landing page. A relative path from the documentation root.
```json
{
"image": "image.png"
"image": "image.png"
}
```
### Format
Change the output format. It is recommended you set only formats that support the live mode as this will also
be read by the integrated web server. And you set the other formats (like confluence) only by command line
```json
{
"format": "html"
"format": "html"
}
```
- __html__ with [its options](./Html_export.md)
- __confluence__ with [its options](./Confluence_upload.md)
- **html** with [its options](./Html_export.md)
- **confluence** with [its options](./Confluence_upload.md)
Available formats are __HTML__ and __Confluence__
Available formats are **HTML** and **Confluence**
### Ignore
Set custom files and entire folders to ignore within your `/docs` folder. For files make sure to include the file extension in the name. For both files and folders, names are case-sensitive.
```json
{
"ignore": {
"files": ["Work_In_Progress.md"],
"folders": ["99_Not_Ready"]
}
"ignore": {
"files": ["Work_In_Progress.md"],
"folders": ["99_Not_Ready"]
}
}
```
### Timezone
If your server does not have a default timezone set in php.ini, it may return errors when it tries to generate the last modified date/time for docs. To fix these errors, specify a timezone in your config file. Valid options are available in the [PHP Manual](http://php.net/manual/en/timezones.php).
```json
{
"timezone": "America/Los_Angeles"
"timezone": "America/Los_Angeles"
}
```
### Multi-language
Enables multi-language support which needs separate directories for each language in `docs/` folder.
```json
{
"languages": {"en": "English", "de": "German"}
"languages": { "en": "English", "de": "German" }
}
```
Directory structure:
```
├── docs/
│ ├── _index.md
@ -107,13 +116,45 @@ Directory structure:
│ │ │ ├── 05_Code_Highlighting.md
```
### Language
You can change the default language with the `language` option.
```json
{
"language": "fr"
}
```
This will change the language of the text within Daux.io and also the `<html lang>` attribute.
You can override the translations with the `strings` option.
A string that isn't found will fall back to english.
```json
{
"strings": {
"fr": {
"CodeBlocks_show": "Afficher le code",
"Search_placeholder": "Rechercher...",
"Link_previous": "Précédent",
"Link_next": "Suivant",
"Edit_on": "Editer sur :name:",
"View_on_github": "Voir sur GitHub",
"View_documentation": "Voir la Documentation"
}
}
}
```
### Processor
You can set the processor in the documentation or as an option to the command line. If you need it when running the server, you should add it to the configuration.
More information on how to create a Processor can be found [here](!For_Developers/Creating_a_Processor).
```json
{
"processor": "MyProcessor"
"processor": "MyProcessor"
}
```

Datei anzeigen

@ -1,13 +1,13 @@
The recommended way to extend Daux is through Processors.
The main advantage, is that you can run it with the source or with `daux.phar` independently. You don't need to hack in the core.
The main advantage, is that you can run it with the source or with `daux` independently. You don't need to hack in the core.
## Adding classes
At the same level as your `daux.phar` file, you will see a `daux` directory, you can create all your classes here.
Next to your `docs` directory, you can create a `daux` directory that can contain your Processor.
The classes must respect the PSR-4 Naming convention. And have `\Todaymade\Daux\Extension` as a base namespace.
By default, we created a `daux/Processor.php` file to get you started.
## A quick test ?
@ -40,7 +40,7 @@ There are a few methods that you can override to add some
By default, Daux.io parses your directory to find pages. but, for a reason or another, you might want to programmatically add some pages.
This can be done with:
This can be done with:
```php
public function manipulateTree(Root $root)
@ -65,7 +65,7 @@ Both methods `getOrCreateDir` and `getOrCreatePage` take two parameters : `paren
The page will automatically be treated as markdown and converted like a normal page.
If you create a new ContentType, like let's say LaTeX, you would set the title `My Page.tex` it will keep the title `My Page` and use your renderer.
If the extension is not mapped to a Generator, it will simply create the file as-is without manipulation.
### Extend the Markdown Generator
@ -82,9 +82,9 @@ See the details on [CommonMark's website](http://commonmark.thephpleague.com/cus
### Add new generators
You can add new generators to Daux.io and use them right away, they must implement the
`\Todaymade\Daux\Format\Base\Generator` interface and if you want to use the live mode with your generator
you have to implement `\Todaymade\Daux\Format\Base\LiveGenerator`.
You can add new generators to Daux.io and use them right away, they must implement the
`\Todaymade\Daux\Format\Base\Generator` interface and if you want to use the live mode with your generator
you have to implement `\Todaymade\Daux\Format\Base\LiveGenerator`.
```php
public function addGenerators()
@ -92,4 +92,3 @@ public function addGenerators()
return ['custom_generator' => '\Todaymade\Daux\Extension\MyNewGenerator'];
}
```

Datei anzeigen

@ -2,49 +2,56 @@ In its simplest form, a theme is an empty folder with a `config.json` file conta
After that, every setting is optional, but you can override everything if you'd like to.
> **Overriding styles**
>
> If you want to tweak a few styles, you can create a `style.css` file at the root of your documentation
> directory and it will be included automatically. By doing this, you don't need to create a new theme.
## `config.json` options
Here is an example `config.json` file :
```json
{
"favicon": "<theme_url>img/favicon.png",
"css": ["<theme_url>css/theme.min.css"],
"js": [],
"fonts": ["https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700&subset=latin,cyrillic-ext,cyrillic"],
"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"]
"favicon": "<theme_url>img/favicon.png",
"css": ["<theme_url>css/theme.min.css"],
"js": [],
"fonts": [
"https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700&subset=latin,cyrillic-ext,cyrillic"
],
"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"]
}
}
}
}
```
There are five options :
- __`favicon`__: The URL to your favicon
- __`css`__: An array of CSS Stylesheets to add to the page
- __`js`__: An array of JavaScript files to load
- __`fonts`__: An array of Font sources, these are added as stylesheets
- __`variants`__: An object containing sub-themes. Each sub theme, can provide the same configurations as the main theme (`favicon`, `css`, `js`, `fonts`)
- **`favicon`**: The URL to your favicon
- **`css`**: An array of CSS Stylesheets to add to the page
- **`js`**: An array of JavaScript files to load
- **`fonts`**: An array of Font sources, these are added as stylesheets
- **`variants`**: An object containing sub-themes. Each sub theme, can provide the same configurations as the main theme (`favicon`, `css`, `js`, `fonts`)
You will also notice this `<theme_url>` in the url.
You will also notice this `<theme_url>` in the url.
This is automatically substituted with the final url to the theme when generating the final page.
There are two possible substitutions :
- __`<theme_url>`__: The url to the current theme
- __`<base_url>`__: The url to the documentation root
- **`<theme_url>`**: The url to the current theme
- **`<base_url>`**: The url to the documentation root
## Theme variants
Like the default Daux.io theme, you might want to provide variants of your theme.
In the example before, there were two variants : blue and green.
The configuration of a variant is added to the configuration of the main theme, it doesn't replace it.
@ -63,10 +70,10 @@ Change the `theme` option inside `html`
```json
{
"themes_directory": "/home/user/themes",
"html": {
"theme": "{theme}-{variant}"
}
"themes_directory": "/home/user/themes",
"html": {
"theme": "{theme}-{variant}"
}
}
```
@ -85,11 +92,12 @@ You can create a folder named `templates` in your theme, copy-paste the original
You can even do it one template at a time if you wish to do only small changes.
By default, we have the following templates :
- `content.php`: The content page.
- `home.php`: The landing page.
- `error.php`: The page to show when a page is not found or some other error happened.
- `partials/navbar_content.php`: The content of the top navigation bar.
- `partials/google_analytics.php`: The script to load Google Analytics.
- `partials/piwik_analytics.php`: The script to load Piwik Analytics.
- `layout/00_layout.php`: The master template, containing the `<html>` tag.
- `layout/05_page.php`: The page layout, with left navigation.
- `content.php`: The content page.
- `home.php`: The landing page.
- `error.php`: The page to show when a page is not found or some other error happened.
- `partials/navbar_content.php`: The content of the top navigation bar.
- `partials/google_analytics.php`: The script to load Google Analytics.
- `partials/piwik_analytics.php`: The script to load Piwik Analytics.
- `layout/00_layout.php`: The master template, containing the `<html>` tag.
- `layout/05_page.php`: The page layout, with left navigation.

Datei anzeigen

@ -1,4 +1,4 @@
<p class="lead">
<p class="HeroText">
<strong>Daux.io</strong> is a documentation generator that uses a simple folder structure and Markdown files to create custom documentation on the fly. It helps you create great looking documentation in a developer friendly way.
</p>
@ -8,42 +8,42 @@
---
<div class=row>
<div class=col-third>
<div class="Row">
<div class="Row__third">
#### For Authors
* [Auto Generated Navigation / Page sorting](01_Features/Navigation_and_Sorting.md)
* [Internal documentation links](01_Features/Internal_links.md)
* [CommonMark compliant](01_Features/CommonMark_compliant.md)
* [Auto created homepage/landing page](01_Features/Landing_page.md)
* [Multiple Output Formats](01_Features/Multiple_Output_Formats.md)
* [Multiple Languages Support](01_Features/Multilanguage.md)
* [No Build Step](01_Features/Live_mode.md)
* [Static Output Generation](01_Features/Static_Site_Generation.md)
* [Table of Contents](01_Features/Table_of_contents.md)
- [Auto Generated Navigation / Page sorting](01_Features/Navigation_and_Sorting.md)
- [Internal documentation links](01_Features/Internal_links.md)
- [CommonMark compliant](01_Features/CommonMark_compliant.md)
- [Auto created homepage/landing page](01_Features/Landing_page.md)
- [Multiple Output Formats](01_Features/Multiple_Output_Formats.md)
- [Multiple Languages Support](01_Features/Multilanguage.md)
- [No Build Step](01_Features/Live_mode.md)
- [Static Output Generation](01_Features/Static_Site_Generation.md)
- [Table of Contents](01_Features/Table_of_contents.md)
</div>
<div class=col-third>
<div class="Row__third">
#### For Developers
* [Auto Syntax Highlighting](01_Features/Auto_Syntax_Highlight.md)
* [Extend Daux.io with Processors](01_For_Developers/Creating_a_Processor.md)
* Full access to the internal API to create new pages programatically
* Work with pages metadata
- [Auto Syntax Highlighting](01_Features/Auto_Syntax_Highlight.md)
- [Extend Daux.io with Processors](01_For_Developers/Creating_a_Processor.md)
- Full access to the internal API to create new pages programatically
- Work with pages metadata
</div>
<div class=col-third>
<div class="Row__third">
#### For Marketing
* 100% Mobile Responsive
* 4 Built-In Themes or roll your own
* Functional, Flat Design Style
* Optional code float layout
* Shareable/Linkable SEO Friendly URLs
* Supports Google Analytics and Piwik Analytics
- 100% Mobile Responsive
- 4 Built-In Themes or roll your own
- Functional, Flat Design Style
- Optional code float layout
- Shareable/Linkable SEO Friendly URLs
- Supports Google Analytics and Piwik Analytics
</div>
</div>
@ -52,16 +52,16 @@
### Installation and usage
If you have __PHP__ and Composer installed
If you have **PHP** and Composer installed
```bash
composer global require dauxio/daux.io
composer global require daux/daux.io
# Next to your `docs` folder, run
daux generate
```
Or if you wish to use __Docker__
Or if you wish to use **Docker**
```bash
# Next to your `docs` folder, run
@ -69,18 +69,3 @@ docker run --rm -it -w /build -v "$PWD":/build daux/daux.io daux generate
```
---
<!-- Google Code -->
<script type="text/javascript">
var google_conversion_id = 983836026;
var google_custom_params = window.google_tag_params;
var google_remarketing_only = true;
</script>
<script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js">
</script>
<noscript>
<div style="display:inline;">
<img height="1" width="1" style="border-style:none;" alt="" src="//googleads.g.doubleclick.net/pagead/viewthroughconversion/983836026/?value=0&amp;guid=ON&amp;script=0"/>
</div>
</noscript>

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 91 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 81 KiB

Binäre Datei nicht angezeigt.

Vorher

Breite:  |  Höhe:  |  Größe: 141 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 100 KiB

Datei anzeigen

@ -16,17 +16,24 @@
"breadcrumb_separator": "Chevrons",
"toggle_code": true,
"date_modified": true,
"float": true,
"inherit_index": true,
"repo": "dauxio/daux.io",
"edit_on_github": "dauxio/daux.io/blob/master/docs",
"twitter": ["onigoetz"],
"google_analytics": "UA-3551397-7",
"google_analytics": false,
"plausible_domain": false,
"links": {
"Download": "https://github.com/dauxio/daux.io/archive/master.zip",
"GitHub Repo": "https://github.com/dauxio/daux.io",
"Help/Support/Bugs": "https://github.com/dauxio/daux.io/issues"
}
"GitHub Repository": "https://github.com/dauxio/daux.io",
"Help/Support/Bugs": "https://github.com/dauxio/daux.io/issues",
"Packagist": "https://packagist.org/packages/daux/daux.io",
"Docker Images": "https://hub.docker.com/r/daux/daux.io"
},
"powered_by": "Powered by Daux.io"
},
"confluence": {
"base_url": "https://dauxio.atlassian.net/wiki/",
"space_id": "DOC",
"root_id": 196610
}
}

Datei anzeigen

@ -1,70 +0,0 @@
#!/usr/bin/env php
<?php
/*
Daux.io
==================
Description
-----------
This is a tool for auto-generating documentation based on markdown files
located in the /docs folder of the project. To see all of the available
options and to read more about how to use the generator, visit:
https://dauxio.github.io/
Author
------
Justin Walsh (Todaymade): justin@todaymade.com, @justin_walsh
Garrett Moon (Todaymade): garrett@todaymade.com, @garrett_moon
Feedback & Suggestions
----
To give us feedback or to suggest an idea, please create an request on the the
GitHub issue tracker:
https://github.com/dauxio/daux.io/issues
Bugs
----
To file bug reports please create an issue using the github issue tracker:
https://github.com/dauxio/daux.io/issues
Copyright and License
---------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
This software is provided by the copyright holders and contributors "as
is" and any express or implied warranties, including, but not limited
to, the implied warranties of merchantability and fitness for a
particular purpose are disclaimed. In no event shall the copyright owner
or contributors be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to,
procurement of substitute goods or services; loss of use, data, or
profits; or business interruption) however caused and on any theory of
liability, whether in contract, strict liability, or tort (including
negligence or otherwise) arising in any way out of the use of this
software, even if advised of the possibility of such damage.
*/
require_once(__DIR__ . '/libs/bootstrap.php');
$application = new \Todaymade\Daux\Console\Application();
$application->run();

Datei anzeigen

@ -8,6 +8,8 @@
"image": "",
"languages": {},
"cache": true,
"format": "html",
"processor": "",
@ -16,6 +18,80 @@
"folders": []
},
"language": "en",
"strings": {
"en": {
"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",
"Toggle_navigation": "Toggle navigation"
},
"fr": {
"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:",
"View_on_github": "Voir sur GitHub",
"View_documentation": "Voir la Documentation",
"Table_of_contents": "Table des matières"
},
"de": {
"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_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"
}
},
"timezone": "America/Los_Angeles",
"live": {
@ -28,7 +104,6 @@
"breadcrumb_separator": "Chevrons",
"toggle_code": true,
"date_modified": false,
"float": false,
"auto_landing": true,
"search": true,
"auto_toc": false,

Datei anzeigen

@ -1,86 +0,0 @@
var cssnano = require('cssnano'),
gulp = require('gulp'),
less = require('gulp-less'),
rename = require('gulp-rename'),
plumber = require('gulp-plumber'),
postcss = require('gulp-postcss'),
stylelint = require('gulp-stylelint');
var resources = {
daux_blue:{source: "themes/daux/less/theme-blue.less", dest: "themes/daux/css/"},
daux_green:{source: "themes/daux/less/theme-green.less", dest: "themes/daux/css/"},
daux_navy:{source: "themes/daux/less/theme-navy.less", dest: "themes/daux/css/"},
daux_red:{source: "themes/daux/less/theme-red.less", dest: "themes/daux/css/"},
daux_singlepage:{source: "themes/daux_singlepage/less/main.less", dest: "themes/daux_singlepage/css/"}
};
var stylelintRules = {
"indentation": 4,
"selector-list-comma-newline-after": "always-multi-line",
"selector-max-id": 0,
// Autoprefixer
"at-rule-no-vendor-prefix": true,
"media-feature-name-no-vendor-prefix": true,
"property-no-vendor-prefix": true,
"selector-no-vendor-prefix": true,
"value-no-vendor-prefix": true
};
var cssnanoOptions = {
safe: true, // Disable dangerous optimisations
filterPlugins: false, // This does very weird stuff
autoprefixer: {
add: true, // Add needed prefixes
remove: true // Remove unnecessary prefixes
}
};
function createCSSTask(source, dest) {
return function () {
return gulp.src(source)
.pipe(plumber())
.pipe(less())
.pipe(postcss([cssnano(cssnanoOptions)]))
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest(dest));
}
}
gulp.task('lint-css', function () {
return gulp
.src(['themes/**/less/**/*.less', '!themes/**/vendor/**/*.less'])
.pipe(stylelint({
failAfterError: true,
config: {
extends: 'stylelint-config-standard',
rules: stylelintRules
},
syntax: 'less',
reporters: [{
formatter: 'string',
console: true
}],
debug: true
}));
});
var style_tasks = [];
for (var style in resources) {
if (resources.hasOwnProperty(style)) {
gulp.task('style_' + style, createCSSTask(resources[style].source, resources[style].dest));
style_tasks.push('style_' + style);
}
}
style_tasks.push('lint-css');
gulp.task("styles", style_tasks);
gulp.task('watch', ['default'], function () {
// Watch .less files
gulp.watch('themes/**/less/**/*.less', ['styles']);
});
gulp.task('default', ['styles']);

Datei anzeigen

@ -5,7 +5,7 @@ use ArrayObject;
class BaseConfig extends ArrayObject
{
/**
* Merge an array into the object
* Merge an array into the object.
*
* @param array $newValues
* @param bool $override
@ -15,8 +15,9 @@ class BaseConfig extends ArrayObject
foreach ($newValues as $key => $value) {
// If the key doesn't exist yet,
// we can simply set it.
if (!array_key_exists($key, $this)) {
if (!array_key_exists($key, (array) $this)) {
$this[$key] = $value;
continue;
}
@ -36,4 +37,19 @@ class BaseConfig extends ArrayObject
}
}
}
public function hasValue($key)
{
return array_key_exists($key, (array) $this);
}
public function getValue($key)
{
return $this[$key];
}
public function setValue($key, $value)
{
$this[$key] = $value;
}
}

103
libs/Cache.php Normale Datei
Datei anzeigen

@ -0,0 +1,103 @@
<?php namespace Todaymade\Daux;
use Symfony\Component\Console\Output\OutputInterface;
class Cache
{
public static $printed = false;
public static function getDirectory(): string
{
$dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'dauxio' . DIRECTORY_SEPARATOR;
if (!Cache::$printed) {
Cache::$printed = true;
Daux::writeln("Using cache dir '$dir'", OutputInterface::VERBOSITY_VERBOSE);
}
return $dir;
}
/**
* Store an item in the cache for a given number of minutes.
*/
public static function put(string $key, string $value): void
{
Cache::ensureCacheDirectoryExists($path = Cache::path($key));
file_put_contents($path, $value);
}
/**
* Create the file cache directory if necessary.
*/
protected static function ensureCacheDirectoryExists(string $path): void
{
$parent = dirname($path);
if (!file_exists($parent)) {
mkdir($parent, 0777, true);
}
}
/**
* Remove an item from the cache.
*/
public static function forget(string $key): bool
{
$path = Cache::path($key);
if (file_exists($path)) {
return unlink($path);
}
return false;
}
/**
* Retrieve an item from the cache by key.
*
* @return mixed
*/
public static function get(string $key): ?string
{
$path = Cache::path($key);
if (file_exists($path)) {
return file_get_contents($path);
}
return null;
}
/**
* Get the full path for the given cache key.
*/
protected static function path(string $key): string
{
$parts = array_slice(str_split($hash = sha1($key), 2), 0, 2);
return Cache::getDirectory() . '/' . implode('/', $parts) . '/' . $hash;
}
public static function clear(): void
{
Cache::rrmdir(Cache::getDirectory());
}
protected static function rrmdir(string $dir): void
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != '.' && $object != '..') {
if (is_dir($dir . '/' . $object)) {
Cache::rrmdir($dir . '/' . $object);
} else {
unlink($dir . '/' . $object);
}
}
}
rmdir($dir);
}
}
}

Datei anzeigen

@ -1,217 +0,0 @@
<?php
/*
* This class is inspired from Composer's compiler
* @see https://github.com/composer/composer/blob/master/src/Composer/Compiler.php
*/
namespace Todaymade\Daux;
use Symfony\Component\Finder\Finder;
/**
* The Compiler class compiles daux into a phar
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Stéphane Goetz <stephane.goetz@onigoetz.ch>
*/
class Compiler
{
/**
* Compiles composer into a single phar file
*
* @throws \RuntimeException
* @param string $pharFile The full path to the file to create
*/
public function compile($pharFile = 'daux.phar')
{
echo "Compiling a new $pharFile\n";
if (file_exists($pharFile)) {
echo "-> Deleting the existing phar\n";
unlink($pharFile);
}
echo "-> Creating the new phar\n";
$phar = new \Phar($pharFile, 0, 'daux.phar');
$phar->setSignatureAlgorithm(\Phar::SHA1);
$phar->startBuffering();
// Daux
echo "-> Adding all daux files\n";
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->name('*.php')
->notName('Compiler.php')
->in(__DIR__ . '/../templates')
->in(__DIR__);
foreach ($finder as $file) {
$this->addFile($phar, $file);
}
// Composer libraries
echo "-> Adding all composer dependencies\n";
$finder = new Finder();
$finder->files()
->ignoreVCS(true)
->exclude('Tests')
->notName('*.png')
->in(__DIR__ . '/../vendor/guzzlehttp/guzzle/src')
->in(__DIR__ . '/../vendor/guzzlehttp/promises/src')
->in(__DIR__ . '/../vendor/guzzlehttp/psr7/src')
->in(__DIR__ . '/../vendor/league/commonmark/src')
->in(__DIR__ . '/../vendor/league/plates/src')
->in(__DIR__ . '/../vendor/myclabs/deep-copy')
->in(__DIR__ . '/../vendor/psr/http-message/src')
->in(__DIR__ . '/../vendor/symfony/console')
->in(__DIR__ . '/../vendor/symfony/polyfill-mbstring')
->in(__DIR__ . '/../vendor/symfony/process')
->in(__DIR__ . '/../vendor/symfony/process')
->in(__DIR__ . '/../vendor/symfony/yaml')
->in(__DIR__ . '/../vendor/webuni/front-matter/src')
->in(__DIR__ . '/../vendor/webuni/commonmark-table-extension/src');
$excluded_files = [
'README.md',
'composer.json',
'LICENSE',
'CHANGELOG.md',
'phpunit.xml.dist',
];
/** @var \SplFileInfo $file */
$count = 0;
foreach ($finder as $file) {
if (in_array($file->getFilename(), $excluded_files)) {
continue;
}
$count++;
$this->addFile($phar, $file);
}
echo " Imported $count files\n";
// Composer autoload
echo "-> Adding the composer autoloader\n";
$this->addComposer($phar);
echo "-> Adding the main binary\n";
$this->addBinary($phar);
echo "-> Writing the stub\n";
$phar->setStub($this->getStub());
$phar->stopBuffering();
echo "-> Writing the licence\n";
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../LICENSE'), false);
chmod($pharFile, 0775);
unset($phar);
echo "Done.\n";
}
private function addFile($phar, $file, $strip = true)
{
$path = strtr(str_replace(dirname(__DIR__) . DIRECTORY_SEPARATOR, '', $file->getRealPath()), '\\', '/');
$content = file_get_contents($file);
if ($strip) {
$content = $this->stripWhitespace($content);
} elseif ('LICENSE' === basename($file)) {
$content = "\n" . $content . "\n";
}
$phar->addFromString($path, $content);
}
private function addComposer($phar)
{
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/autoload.php'));
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_classmap.php'));
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_files.php'));
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_namespaces.php'));
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/autoload_real.php'));
$this->addFile($phar, new \SplFileInfo(__DIR__ . '/../vendor/composer/ClassLoader.php'));
if (file_exists(__DIR__ . '/../vendor/composer/autoload_static.php')) {
$content = file_get_contents(__DIR__ . '/../vendor/composer/autoload_static.php');
$content = str_replace('__DIR__ . \'/../..\' . \'/daux\'', 'PHAR_DIR . \'/daux\'', $content);
$phar->addFromString('vendor/composer/autoload_static.php', $content);
}
$content = file_get_contents(__DIR__ . '/../vendor/composer/autoload_psr4.php');
$content = str_replace('$baseDir . \'/daux\'', 'PHAR_DIR . \'/daux\'', $content);
$phar->addFromString('vendor/composer/autoload_psr4.php', $content);
}
private function addBinary($phar)
{
$content = file_get_contents(__DIR__ . '/../bin/daux');
$content = preg_replace('{^#!/usr/bin/env php\s*}', '', $content);
$phar->addFromString('bin/daux', $content);
}
/**
* Removes whitespace from a PHP source string while preserving line numbers.
*
* @param string $source A PHP string
* @return string The PHP string with the whitespace removed
*/
private function stripWhitespace($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) {
$output .= str_repeat("\n", substr_count($token[1], "\n"));
} elseif (T_WHITESPACE === $token[0]) {
// reduce wide spaces
$whitespace = preg_replace('{[ \t]+}', ' ', $token[1]);
// normalize newlines to \n
$whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
// trim leading spaces
$whitespace = preg_replace('{\n +}', "\n", $whitespace);
$output .= $whitespace;
} else {
$output .= $token[1];
}
}
return $output;
}
private function getStub()
{
return <<<'EOF'
#!/usr/bin/env php
<?php
/*
* This file is part of Daux.
*
* (c) Stéphane Goetz <onigoetz@onigoetz.ch>
*
* For the full copyright and license information, please view
* the license that is located at the bottom of this file.
*/
define('PHAR_DIR', dirname(__FILE__));
Phar::mapPhar('daux.phar');
require 'phar://daux.phar/bin/daux';
__HALT_COMPILER();
EOF;
}
}

Datei anzeigen

@ -1,88 +1,116 @@
<?php namespace Todaymade\Daux;
use Todaymade\Daux\Tree\Content;
use Todaymade\Daux\Format\Confluence\Config as ConfluenceConfig;
use Todaymade\Daux\Format\HTML\Config as HTMLConfig;
use Todaymade\Daux\Format\HTML\Theme as Theme;
use Todaymade\Daux\Tree\Content;
use Todaymade\Daux\Tree\Entry;
class Config extends BaseConfig
{
public function getTitle()
{
return $this['title'];
return $this->getValue('title');
}
public function hasAuthor(): bool
{
return $this->hasValue('author');
}
public function getAuthor()
{
return $this->getValue('author');
}
public function hasTagline(): bool
{
return $this->hasValue('tagline');
}
public function getTagline()
{
return $this->getValue('tagline');
}
public function getCurrentPage()
{
return $this['current_page'];
return $this->getValue('current_page');
}
public function setCurrentPage(Content $entry)
{
$this['current_page'] = $entry;
$this->setValue('current_page', $entry);
}
public function getDocumentationDirectory()
{
return $this['docs_directory'];
}
public function setDocumentationDirectory($documentationPath)
{
$this['docs_directory'] = $documentationPath;
return $this->getValue('docs_directory');
}
public function getThemesDirectory()
{
return $this['themes_directory'];
}
public function setThemesDirectory($directory)
{
$this['themes_directory'] = $directory;
}
public function setThemesPath($themePath)
{
$this['themes_path'] = $themePath;
return $this->getValue('themes_directory');
}
public function getThemesPath()
{
return $this['themes_path'];
}
public function setFormat($format)
{
$this['format'] = $format;
return $this->getValue('themes_path');
}
public function getFormat()
{
return $this['format'];
return $this->getValue('format');
}
public function hasTimezone()
public function hasTimezone(): bool
{
return isset($this['timezone']);
}
public function getTimezone()
{
return $this['timezone'];
return $this->getValue('timezone');
}
public function isMultilanguage()
public function getTree()
{
return array_key_exists('languages', $this) && !empty($this['languages']);
return $this->getValue('tree');
}
public function setTree($tree)
{
$this->setValue('tree', $tree);
}
public function isMultilanguage(): bool
{
return $this->hasValue('languages') && !empty($this->getValue('languages'));
}
public function getLanguages(): array
{
return $this->getValue('languages');
}
public function getLanguage(): string
{
return $this->getValue('language');
}
public function getMode()
{
return $this->getValue('mode');
}
public function isLive()
{
return $this['mode'] == Daux::LIVE_MODE;
return $this->getValue('mode') == Daux::LIVE_MODE;
}
public function isStatic()
{
return $this['mode'] == Daux::STATIC_MODE;
return $this->getValue('mode') == Daux::STATIC_MODE;
}
public function shouldInheritIndex()
@ -90,34 +118,188 @@ class Config extends BaseConfig
// As the global configuration is always present, we
// need to test for the existence of the legacy value
// first. Then use the current value.
if (array_key_exists('live', $this) && array_key_exists('inherit_index', $this['live'])) {
if ($this->hasValue('live') && array_key_exists('inherit_index', $this['live'])) {
return $this['live']['inherit_index'];
}
return $this['html']['inherit_index'];
}
public function setConfigurationOverrideFile($override_file)
public function getIndexKey()
{
$this['override_file'] = $override_file;
return $this->getValue('mode') == Daux::STATIC_MODE ? 'index.html' : 'index';
}
public function getConfigurationOverrideFile()
public function getProcessor()
{
if (array_key_exists('override_file', $this)) {
return $this['override_file'];
return $this->getValue('processor');
}
public function getConfluenceConfiguration(): ConfluenceConfig
{
return new ConfluenceConfig($this->hasValue('confluence') ? $this->getValue('confluence') : []);
}
public function getHTML(): HTMLConfig
{
return new HTMLConfig($this->hasValue('html') ? $this->getValue('html') : []);
}
public function getTheme(): ?Theme
{
return $this->hasValue('theme') ? new Theme($this->getValue('theme')) : null;
}
public function getValidContentExtensions()
{
return $this->getValue('valid_content_extensions');
}
public function setValidContentExtensions(array $value)
{
$this->setValue('valid_content_extensions', $value);
}
public function canCache()
{
if ($this->hasValue('cache')) {
return $this->getValue('cache');
}
return null;
return false;
}
public function getConfluenceConfiguration()
public function getCacheKey()
{
return $this['confluence'];
$cloned = [];
foreach ($this as $key => $value) {
$cloned[$key] = ($value instanceof Entry) ? $value->dump() : $value;
}
return sha1(json_encode($cloned));
}
public function getHTML()
public function hasTranslationKey($language, $key): bool
{
return new HTMLConfig($this['html']);
return array_key_exists($language, $this['strings']) && array_key_exists($key, $this['strings'][$language]);
}
public function getTranslationKey($language, $key)
{
return $this['strings'][$language][$key];
}
public function hasImage(): bool
{
return $this->hasValue('image') && !empty($this->getValue('image'));
}
public function getImage()
{
return $this->getValue('image');
}
public function setImage($value)
{
$this->setValue('image', $value);
}
public function getLocalBase()
{
return $this->getValue('local_base');
}
public function getTemplates()
{
return $this->getValue('templates');
}
public function getBaseUrl()
{
return $this->getValue('base_url');
}
public function getBasePage()
{
if ($this->isLive()) {
$value = '//' . $this->getBaseUrl();
if (!$this['live']['clean_urls']) {
$value .= 'index.php/';
}
return $value;
}
return $this->getBaseUrl();
}
public function hasEntryPage(): bool
{
return $this->hasValue('entry_page') && !empty($this->getValue('entry_page'));
}
public function getEntryPage()
{
return $this->getValue('entry_page');
}
public function setEntryPage($value)
{
$this->setValue('entry_page', $value);
}
public function hasRequest(): bool
{
return $this->hasValue('request') && !empty($this->getValue('request'));
}
public function getRequest()
{
return $this->getValue('request');
}
public function setRequest($value)
{
$this->setValue('request', $value);
}
public function getIndex()
{
return $this->getValue('index');
}
public function setIndex($value)
{
$this->setValue('index', $value);
}
public function hasProcessorInstance()
{
return $this->hasValue('processor_instance');
}
public function getProcessorInstance()
{
return $this->getValue('processor_instance');
}
public function setProcessorInstance($value)
{
$this->setValue('processor_instance', $value);
}
public function getIgnore()
{
return $this->getValue('ignore');
}
public function hasHost()
{
return $this->hasValue('host');
}
public function getHost()
{
return $this->getValue('host');
}
}

327
libs/ConfigBuilder.php Normale Datei
Datei anzeigen

@ -0,0 +1,327 @@
<?php namespace Todaymade\Daux;
class ConfigBuilder
{
/** @var Config */
private $config;
/** @var array */
private $overrideValues = [];
private $configuration_override_file;
private function __construct(string $mode)
{
$this->config = new Config();
$this->config['mode'] = $mode;
$this->config['local_base'] = dirname(__DIR__);
}
public static function fromFile($file): Config
{
return unserialize(file_get_contents($file));
}
public static function withMode($mode = Daux::STATIC_MODE): ConfigBuilder
{
$builder = new ConfigBuilder($mode);
$builder->loadBaseConfiguration();
return $builder;
}
public function with(array $values): ConfigBuilder
{
$this->config->merge($values);
return $this;
}
private function setValue(Config $array, $key, $value)
{
if (is_null($key)) {
return $array = $value;
}
$keys = explode('.', $key);
while (count($keys) > 1) {
$key = array_shift($keys);
if (!isset($array[$key]) || !is_array($array[$key])) {
$array[$key] = [];
}
$array = &$array[$key];
}
$array[array_shift($keys)] = $value;
}
public function withValues(array $values): ConfigBuilder
{
$this->overrideValues = $values;
return $this;
}
public function withDocumentationDirectory($dir): ConfigBuilder
{
$this->config['docs_directory'] = $dir;
return $this;
}
public function withValidContentExtensions(array $value): ConfigBuilder
{
$this->config['valid_content_extensions'] = $value;
return $this;
}
public function withThemesPath($themePath): ConfigBuilder
{
$this->config['themes_path'] = $themePath;
return $this;
}
public function withThemesDirectory($directory): ConfigBuilder
{
$this->config['themes_directory'] = $directory;
return $this;
}
public function withCache(bool $value): ConfigBuilder
{
$this->config['cache'] = $value;
return $this;
}
public function withFormat($format): ConfigBuilder
{
$this->config['format'] = $format;
return $this;
}
public function withConfigurationOverride($file): ConfigBuilder
{
$this->configuration_override_file = $file;
return $this;
}
public function withProcessor($value): ConfigBuilder
{
$this->config['processor'] = $value;
return $this;
}
public function withConfluenceDelete($value): ConfigBuilder
{
$this->config['confluence']['delete'] = $value;
return $this;
}
public function build(): Config
{
$this->initializeConfiguration();
foreach ($this->overrideValues as $value) {
$this->setValue($this->config, $value[0], $value[1]);
}
return $this->config;
}
private function resolveThemeVariant()
{
$theme = $this->config->getHTML()->getTheme();
$themesPath = $this->config->getThemesPath() . DIRECTORY_SEPARATOR;
// If theme directory exists, we're good with that
if (is_dir(realpath(($themesPath . $theme)))) {
return [$theme, ''];
}
$themePieces = explode('-', $theme);
$variant = '';
// Do we have a variant or only a theme ?
if (count($themePieces) > 1) {
$variant = array_pop($themePieces);
$theme = implode('-', $themePieces);
}
if (!is_dir(realpath($themesPath . $theme))) {
throw new \RuntimeException("Theme '{$theme}' not found");
}
return [$theme, $variant];
}
/**
* @param string $override_file
*
* @throws Exception
*/
private function initializeConfiguration()
{
// Validate and set theme path
$docs_path = $this->normalizeDocumentationPath($this->config->getDocumentationDirectory());
$this->config['docs_directory'] = $docs_path;
// Read documentation overrides
$this->loadConfiguration($docs_path . DIRECTORY_SEPARATOR . 'config.json');
// Read command line overrides
$override_file = $this->getConfigurationOverride($this->configuration_override_file);
if ($override_file !== null) {
$this->loadConfiguration($override_file);
}
// Validate and set theme path
$this->withThemesPath($this->normalizeThemePath($this->config->getThemesDirectory()));
// Resolve variant once
$theme = $this->resolveThemeVariant();
$this->config['html']['theme'] = $theme[0];
$this->config['html']['theme-variant'] = $theme[1];
// Set a valid default timezone
if ($this->config->hasTimezone()) {
date_default_timezone_set($this->config->getTimezone());
} elseif (!ini_get('date.timezone')) {
date_default_timezone_set('GMT');
}
// Text search would be too slow on live server
if ($this->config->isLive()) {
$this->config['html']['search'] = false;
}
}
private function normalizeThemePath($path)
{
$validPath = $this->findLocation($path, $this->config->getLocalBase(), 'dir');
if (!$validPath) {
throw new Exception('The Themes directory does not exist. Check the path again : ' . $path);
}
return $validPath;
}
private function normalizeDocumentationPath($path)
{
$validPath = $this->findLocation($path, $this->config->getLocalBase(), 'dir');
if (!$validPath) {
throw new Exception('The Docs directory does not exist. Check the path again : ' . $path);
}
return $validPath;
}
/**
* Load and validate the global configuration.
*
* @throws Exception
*/
private function loadBaseConfiguration()
{
// Set the default configuration
$this->config->merge([
'docs_directory' => 'docs',
'valid_content_extensions' => ['md', 'markdown'],
//Paths and tree
'templates' => 'templates',
'base_url' => '',
]);
// Load the global configuration
$this->loadConfiguration($this->config->getLocalBase() . DIRECTORY_SEPARATOR . 'global.json', false);
}
/**
* @param string $config_file
* @param bool $optional
*
* @throws Exception
*/
private function loadConfiguration($config_file, $optional = true)
{
if (!file_exists($config_file)) {
if ($optional) {
return;
}
throw new Exception('The configuration file is missing. Check path : ' . $config_file);
}
$config = json_decode(file_get_contents($config_file), true);
if (!isset($config)) {
throw new Exception('The configuration file "' . $config_file . '" is corrupt. Is your JSON well-formed ?');
}
$this->config->merge($config);
}
/**
* Get the file requested for configuration overrides.
*
* @param null|string $path
*
* @throws Exception
*
* @return null|string the path to a file to load for configuration overrides
*/
private function getConfigurationOverride($path)
{
$validPath = $this->findLocation($path, $this->config->getLocalBase(), 'file');
if ($validPath === null) {
return null;
}
if (!$validPath) {
throw new Exception('The configuration override file does not exist. Check the path again : ' . $path);
}
return $validPath;
}
/**
* @param null|string $path
* @param string $basedir
* @param string $type
*
* @return null|false|string
*/
private function findLocation($path, $basedir, $type)
{
// If Path is explicitly null, it's useless to go further
if ($path === null) {
return null;
}
// VFS, used only in tests
if (substr($path, 0, 6) == 'vfs://') {
return $path;
}
// Check if it's relative to the current directory or an absolute path
if (DauxHelper::is($path, $type)) {
return DauxHelper::getAbsolutePath($path);
}
// Check if it exists relative to Daux's root
$newPath = $basedir . DIRECTORY_SEPARATOR . $path;
if (DauxHelper::is($newPath, $type)) {
return $newPath;
}
return false;
}
}

Datei anzeigen

@ -10,6 +10,26 @@ class Application extends SymfonyApplication
$this->add(new Generate());
$this->add(new Serve());
$this->setDefaultCommand('generate');
$this->add(new ClearCache());
$app_name = 'daux/daux.io';
$up = '..' . DIRECTORY_SEPARATOR;
$composer = __DIR__ . DIRECTORY_SEPARATOR . $up . $up . $up . $up . $up . 'composer.lock';
$version = 'unknown';
if (file_exists($composer)) {
$app = json_decode(file_get_contents($composer));
$packages = $app->packages;
foreach ($packages as $package) {
if ($package->name == $app_name) {
$version = $package->version;
}
}
}
$this->setVersion($version);
$this->setName($app_name);
}
}

25
libs/Console/ClearCache.php Normale Datei
Datei anzeigen

@ -0,0 +1,25 @@
<?php namespace Todaymade\Daux\Console;
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Cache;
class ClearCache extends SymfonyCommand
{
protected function configure()
{
$this
->setName('clear-cache')
->setDescription('Clears the cache');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln("Clearing cache at '" . Cache::getDirectory() . "'");
Cache::clear();
$output->writeln('<info>Cache cleared</info>');
return 0;
}
}

Datei anzeigen

@ -2,34 +2,66 @@
use Symfony\Component\Console\Command\Command as SymfonyCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\ConfigBuilder;
use Todaymade\Daux\Daux;
class DauxCommand extends SymfonyCommand
{
protected function prepareDaux(InputInterface $input)
protected function configure()
{
$daux = new Daux(Daux::STATIC_MODE);
$this
->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Configuration file')
->addOption('source', 's', InputOption::VALUE_REQUIRED, 'Where to take the documentation from')
->addOption('processor', 'p', InputOption::VALUE_REQUIRED, 'Manipulations on the tree')
->addOption('no-cache', null, InputOption::VALUE_NONE, 'Disable Cache')
->addOption('themes', 't', InputOption::VALUE_REQUIRED, 'Set a different themes directory (Used by HTML format only)')
->addOption('value', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Set different configuration values');
}
// Set the format if requested
if ($input->hasOption('format') && $input->getOption('format')) {
$daux->getParams()->setFormat($input->getOption('format'));
protected function prepareConfig($mode, InputInterface $input, OutputInterface $output): ConfigBuilder
{
$builder = ConfigBuilder::withMode($mode);
if ($input->getOption('configuration')) {
$builder->withConfigurationOverride($input->getOption('configuration'));
}
// Set the source directory
if ($input->getOption('source')) {
$daux->getParams()->setDocumentationDirectory($input->getOption('source'));
$builder->withDocumentationDirectory($input->getOption('source'));
}
if ($input->getOption('processor')) {
$builder->withProcessor($input->getOption('processor'));
}
if ($input->getOption('no-cache')) {
$builder->withCache(false);
}
if ($input->getOption('themes')) {
$daux->getParams()->setThemesDirectory($input->getOption('themes'));
$builder->withThemesDirectory($input->getOption('themes'));
}
$daux->initializeConfiguration($input->getOption('configuration'));
if ($input->hasOption('delete') && $input->getOption('delete')) {
$daux->getParams()['confluence']['delete'] = true;
if ($input->hasOption('value')) {
$values = array_map(
function ($value) {
return array_map('trim', explode('=', $value));
},
$input->getOption('value')
);
$builder->withValues($values);
}
return $daux;
return $builder;
}
protected function prepareProcessor(Daux $daux, $width)
{
$class = $daux->getProcessorClass();
if (!empty($class)) {
$daux->setProcessor(new $class($daux, $daux->getOutput(), $width));
}
}
}

Datei anzeigen

@ -5,30 +5,44 @@ use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Terminal;
use Todaymade\Daux\ConfigBuilder;
use Todaymade\Daux\Daux;
class Generate extends DauxCommand
{
protected function configure()
{
parent::configure();
$description = 'Destination folder, relative to the working directory';
$this
->setName('generate')
->setDescription('Generate documentation')
->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Configuration file')
->addOption('source', 's', InputOption::VALUE_REQUIRED, 'Where to take the documentation from')
->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'Output format, html or confluence', 'html')
->addOption('processor', 'p', InputOption::VALUE_REQUIRED, 'Manipulations on the tree')
->addOption('themes', 't', InputOption::VALUE_REQUIRED, 'Set a different themes directory')
// Confluence format only
->addOption('delete', null, InputOption::VALUE_NONE, 'Delete pages not linked to a documentation page (confluence)')
// HTML Format only
->addOption('destination', 'd', InputOption::VALUE_REQUIRED, $description, 'static')
->addOption('search', null, InputOption::VALUE_NONE, 'Generate full text search');
->addOption('destination', 'd', InputOption::VALUE_REQUIRED, $description, 'static');
}
protected function prepareConfig($mode, InputInterface $input, OutputInterface $output): ConfigBuilder
{
$builder = parent::prepareConfig($mode, $input, $output);
// Set the format if requested
if ($input->hasOption('format') && $input->getOption('format')) {
$builder->withFormat($input->getOption('format'));
}
if ($input->hasOption('delete') && $input->getOption('delete')) {
$builder->withConfluenceDelete(true);
}
return $builder;
}
protected function execute(InputInterface $input, OutputInterface $output)
@ -44,29 +58,20 @@ class Generate extends DauxCommand
$input = new ArgvInput($argv, $this->getDefinition());
}
$daux = $this->prepareDaux($input);
$builder = $this->prepareConfig(Daux::STATIC_MODE, $input, $output);
$daux = new Daux($builder->build(), $output);
$width = $this->getApplication()->getTerminalDimensions()[0];
$width = (new Terminal())->getWidth();
// Instiantiate the processor if one is defined
$this->prepareProcessor($daux, $input, $output, $width);
$this->prepareProcessor($daux, $width);
// Generate the tree
$daux->generateTree();
// Generate the documentation
$daux->getGenerator()->generateAll($input, $output, $width);
}
protected function prepareProcessor(Daux $daux, InputInterface $input, OutputInterface $output, $width)
{
if ($input->getOption('processor')) {
$daux->getParams()['processor'] = $input->getOption('processor');
}
$class = $daux->getProcessorClass();
if (!empty($class)) {
$daux->setProcessor(new $class($daux, $output, $width));
}
return 0;
}
}

Datei anzeigen

@ -1,25 +1,43 @@
<?php namespace Todaymade\Daux\Console;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Daux;
trait RunAction
{
protected function runAction($title, OutputInterface $output, $width, \Closure $closure)
protected function getLength($content)
{
$output->write($title);
return function_exists('mb_strlen') ? mb_strlen($content) : strlen($content);
}
$length = function_exists('mb_strlen') ? mb_strlen($title) : strlen($title);
protected function runAction($title, $width, \Closure $closure)
{
$verbose = Daux::getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
Daux::write($title, $verbose);
// 8 is the length of the label + 2 let it breathe
$padding = $width - $length - 10;
$padding = $width - $this->getLength($title) - 10;
try {
$response = $closure();
$response = $closure(function ($content) use (&$padding, $verbose) {
$padding -= $this->getLength($content);
Daux::write($content, $verbose);
});
} catch (\Exception $e) {
$output->writeln(str_pad(' ', $padding) . '[ <fg=red>FAIL</fg=red> ]');
$this->status($padding, '[ <fg=red>FAIL</fg=red> ]');
throw $e;
}
$output->writeln(str_pad(' ', $padding) . '[ <fg=green>OK</fg=green> ]');
$this->status($padding, '[ <fg=green>OK</fg=green> ]');
return $response;
}
protected function status($padding, $content)
{
$verbose = Daux::getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
$padding = $verbose ? '' : str_pad(' ', $padding);
Daux::writeln($padding . $content);
}
}

Datei anzeigen

@ -1,29 +1,22 @@
<?php namespace Todaymade\Daux\Console;
use Exception;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Terminal;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\ProcessUtils;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Server\Server;
class Serve extends DauxCommand
{
protected function configure()
{
parent::configure();
$this
->setName('serve')
->setDescription('Serve documentation')
->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Configuration file')
->addOption('source', 's', InputOption::VALUE_REQUIRED, 'Where to take the documentation from')
->addOption('processor', 'p', InputOption::VALUE_REQUIRED, 'Manipulations on the tree')
->addOption('themes', 't', InputOption::VALUE_REQUIRED, 'Set a different themes directory')
// Serve the current documentation
->addOption('serve', null, InputOption::VALUE_NONE, 'Serve the current directory')
->addOption('host', null, InputOption::VALUE_REQUIRED, 'The host to serve on', 'localhost')
->addOption('port', null, InputOption::VALUE_REQUIRED, 'The port to serve on', 8085);
}
@ -33,31 +26,44 @@ class Serve extends DauxCommand
$host = $input->getOption('host');
$port = $input->getOption('port');
$daux = $this->prepareDaux($input);
$builder = $this->prepareConfig(Daux::LIVE_MODE, $input, $output);
// Daux can only serve HTML
$daux->getParams()->setFormat('html');
$builder->withFormat('html');
$daux = new Daux($builder->build(), $output);
$width = (new Terminal())->getWidth();
// Instiantiate the processor if one is defined
$this->prepareProcessor($daux, $width);
// Write the current configuration to a file to read it from the other serving side
$file = tmpfile();
if ($file === false) {
$output->writeln('<fg=red>Failed to create temporary file for configuration</fg=red>');
return 1;
}
$path = stream_get_meta_data($file)['uri'];
fwrite($file, serialize($daux->getConfig()));
chdir(__DIR__ . '/../../');
putenv('DAUX_SOURCE=' . $daux->getParams()->getDocumentationDirectory());
putenv('DAUX_THEME=' . $daux->getParams()->getThemesPath());
putenv('DAUX_CONFIGURATION=' . $daux->getParams()->getConfigurationOverrideFile());
putenv('DAUX_EXTENSION=' . DAUX_EXTENSION);
putenv('DAUX_CONFIG=' . $path);
putenv('DAUX_VERBOSITY=' . $output->getVerbosity());
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");
}
passthru("{$binary} -S {$host}:{$port} {$base}/index.php");
fclose($file);
return 0;
}
}

Datei anzeigen

@ -8,7 +8,7 @@ interface ContentType
public function __construct(Config $config);
/**
* Get the file extensions supported by this Content Type
* Get the file extensions supported by this Content Type.
*
* @return string[]
*/
@ -17,6 +17,7 @@ interface ContentType
/**
* @param string $raw The raw text to render
* @param Content $node The original node we are converting
*
* @return string The generated output
*/
public function convert($raw, Content $node);

Datei anzeigen

@ -18,7 +18,7 @@ class ContentTypeHandler
}
/**
* Get all valid content file extensions
* Get all valid content file extensions.
*
* @return string[]
*/
@ -33,9 +33,8 @@ class ContentTypeHandler
}
/**
* Get the ContentType able to handle this node
* Get the ContentType able to handle this node.
*
* @param Content $node
* @return ContentType
*/
public function getType(Content $node)

Datei anzeigen

@ -1,22 +1,25 @@
<?php namespace Todaymade\Daux\ContentTypes\Markdown;
use League\CommonMark\DocParser;
use League\CommonMark\Environment;
use League\CommonMark\HtmlRenderer;
use League\CommonMark\Extension\Autolink\AutolinkExtension;
use League\CommonMark\Extension\SmartPunct\SmartPunctExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Inline\Element as InlineElement;
use Todaymade\Daux\Config;
use Webuni\CommonMark\TableExtension\TableExtension;
class CommonMarkConverter extends \League\CommonMark\CommonMarkConverter
{
/**
* Create a new commonmark converter instance.
*
* @param array $config
*/
public function __construct(array $config = [])
{
$environment = Environment::createCommonMarkEnvironment();
$environment->mergeConfig($config);
$environment->addExtension(new AutolinkExtension());
$environment->addExtension(new SmartPunctExtension());
$environment->addExtension(new StrikethroughExtension());
$environment->addExtension(new TableExtension());
// Table of Contents
@ -24,12 +27,11 @@ class CommonMarkConverter extends \League\CommonMark\CommonMarkConverter
$this->extendEnvironment($environment, $config['daux']);
if (array_key_exists('processor_instance', $config['daux'])) {
$config['daux']['processor_instance']->extendCommonMarkEnvironment($environment);
if ($config['daux']->hasProcessorInstance()) {
$config['daux']->getProcessorInstance()->extendCommonMarkEnvironment($environment);
}
$this->docParser = new DocParser($environment);
$this->htmlRenderer = new HtmlRenderer($environment);
parent::__construct($config, $environment);
}
protected function getLinkRenderer(Environment $environment)
@ -39,6 +41,6 @@ class CommonMarkConverter extends \League\CommonMark\CommonMarkConverter
protected function extendEnvironment(Environment $environment, Config $config)
{
$environment->addInlineRenderer('Link', $this->getLinkRenderer($environment));
$environment->addInlineRenderer(InlineElement\Link::class, $this->getLinkRenderer($environment));
}
}

Datei anzeigen

@ -1,6 +1,9 @@
<?php namespace Todaymade\Daux\ContentTypes\Markdown;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Cache;
use Todaymade\Daux\Config;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Tree\Content;
class ContentType implements \Todaymade\Daux\ContentTypes\ContentType
@ -9,12 +12,25 @@ class ContentType implements \Todaymade\Daux\ContentTypes\ContentType
protected $config;
/** @var CommonMarkConverter */
protected $converter;
private $converter;
public function __construct(Config $config)
{
$this->config = $config;
$this->converter = new CommonMarkConverter(['daux' => $config]);
}
protected function createConverter()
{
return new CommonMarkConverter(['daux' => $this->config]);
}
protected function getConverter()
{
if (!$this->converter) {
$this->converter = $this->createConverter();
}
return $this->converter;
}
/**
@ -25,10 +41,37 @@ class ContentType implements \Todaymade\Daux\ContentTypes\ContentType
return ['md', 'markdown'];
}
protected function doConversion($raw)
{
Daux::writeln('Running conversion', OutputInterface::VERBOSITY_VERBOSE);
return $this->getConverter()->convertToHtml($raw);
}
public function convert($raw, Content $node)
{
$this->config->setCurrentPage($node);
return $this->converter->convertToHtml($raw);
$can_cache = $this->config->canCache();
// TODO :: add daux version to cache key
$cacheKey = $this->config->getCacheKey() . sha1($raw);
$payload = Cache::get($cacheKey);
if ($can_cache && $payload) {
Daux::writeln('Using cached version', OutputInterface::VERBOSITY_VERBOSE);
}
if (!$can_cache || !$payload) {
Daux::writeln($can_cache ? 'Not found in the cache, generating...' : 'Cache disabled, generating...', OutputInterface::VERBOSITY_VERBOSE);
$payload = $this->doConversion($raw);
}
if ($can_cache) {
Cache::put($cacheKey, $payload);
}
return $payload;
}
}

Datei anzeigen

@ -4,102 +4,58 @@ use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
use Todaymade\Daux\Config;
use Todaymade\Daux\DauxHelper;
use Todaymade\Daux\Exception\LinkNotFoundException;
use Todaymade\Daux\Tree\Entry;
class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
class LinkRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var Config
*/
protected $daux;
/**
* @var \League\CommonMark\Inline\Renderer\LinkRenderer
*/
protected $parent;
public function __construct($daux)
{
$this->daux = $daux;
}
/**
* @param string $url
* @return Entry
* @throws LinkNotFoundException
*/
protected function resolveInternalFile($url)
{
$triedAbsolute = false;
// Legacy absolute paths could start with
// "!" In this case we will try to find
// the file starting at the root
if ($url[0] == '!' || $url[0] == '/') {
$url = ltrim($url, '!/');
if ($file = DauxHelper::getFile($this->daux['tree'], $url)) {
return $file;
}
$triedAbsolute = true;
}
// Seems it's not an absolute path or not found,
// so we'll continue with the current folder
if ($file = DauxHelper::getFile($this->daux->getCurrentPage()->getParent(), $url)) {
return $file;
}
// If we didn't already try it, we'll
// do a pass starting at the root
if (!$triedAbsolute && $file = DauxHelper::getFile($this->daux['tree'], $url)) {
return $file;
}
throw new LinkNotFoundException("Could not locate file '$url'");
}
protected function isValidUrl($url)
{
return !empty($url) && $url[0] != '#';
}
protected function isExternalUrl($url)
{
return preg_match('#^(?:[a-z]+:)?//|^mailto:#', $url);
$this->parent = new \League\CommonMark\Inline\Renderer\LinkRenderer();
}
/**
* @param AbstractInline|Link $inline
* @param ElementRendererInterface $htmlRenderer
* @return HtmlElement
*
* @throws LinkNotFoundException
*
* @return HtmlElement
*/
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"
);
if (!($inline instanceof Link)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$element = parent::render($inline, $htmlRenderer);
$element = $this->parent->render($inline, $htmlRenderer);
$url = $inline->getUrl();
// empty urls and anchors should
// not go through the url resolver
if (!$this->isValidUrl($url)) {
if (!DauxHelper::isValidUrl($url)) {
return $element;
}
// Absolute urls, shouldn't either
if ($this->isExternalUrl($url)) {
$element->setAttribute('class', 'external');
if (DauxHelper::isExternalUrl($url)) {
$element->setAttribute('class', 'Link--external');
$element->setAttribute('rel', 'noopener noreferrer');
return $element;
}
@ -109,18 +65,35 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
$urlAndHash = explode('#', $url);
$url = $urlAndHash[0];
$foundWithHash = false;
try {
$file = $this->resolveInternalFile($url);
$file = DauxHelper::resolveInternalFile($this->daux, $url);
$url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
} catch (LinkNotFoundException $e) {
if ($this->daux->isStatic()) {
throw $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 = DauxHelper::resolveInternalFile($this->daux, $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.
}
$element->setAttribute('class', 'broken');
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];
}
@ -128,4 +101,9 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
return $element;
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->parent->setConfiguration($configuration);
}
}

Datei anzeigen

@ -6,43 +6,22 @@ use League\CommonMark\Cursor;
class TableOfContents extends AbstractBlock
{
/**
* Returns true if this block can contain the given block as a child node
*
* @param AbstractBlock $block
*
* @return bool
* Returns true if this block can contain the given block as a child node.
*/
public function canContain(AbstractBlock $block)
public function canContain(AbstractBlock $block): bool
{
return false;
}
/**
* Returns true if block type can accept lines of text
*
* @return bool
* Whether this is a code block.
*/
public function acceptsLines()
public function isCode(): bool
{
return false;
}
/**
* Whether this is a code block
*
* @return bool
*/
public function isCode()
{
return false;
}
/**
* @param Cursor $cursor
*
* @return bool
*/
public function matchesNextLine(Cursor $cursor)
public function matchesNextLine(Cursor $cursor): bool
{
return false;
}

Datei anzeigen

@ -1,25 +1,19 @@
<?php namespace Todaymade\Daux\ContentTypes\Markdown;
use League\CommonMark\Block\Parser\AbstractBlockParser;
use League\CommonMark\Block\Parser\BlockParserInterface;
use League\CommonMark\ContextInterface;
use League\CommonMark\Cursor;
class TableOfContentsParser extends AbstractBlockParser
class TableOfContentsParser implements BlockParserInterface
{
/**
* @param ContextInterface $context
* @param Cursor $cursor
*
* @return bool
*/
public function parse(ContextInterface $context, Cursor $cursor)
public function parse(ContextInterface $context, Cursor $cursor): bool
{
if ($cursor->isIndented()) {
return false;
}
$previousState = $cursor->saveState();
$cursor->advanceToFirstNonSpace();
$cursor->advanceToNextNonSpaceOrNewline();
$fence = $cursor->match('/^\[TOC\]/');
if (is_null($fence)) {
$cursor->restoreState($previousState);

Datei anzeigen

@ -1,10 +1,9 @@
<?php namespace Todaymade\Daux;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\ContentTypes\ContentTypeHandler;
use Todaymade\Daux\Tree\Builder;
use Todaymade\Daux\Tree\Content;
use Todaymade\Daux\Tree\Directory;
use Todaymade\Daux\Tree\Root;
class Daux
@ -12,11 +11,13 @@ class Daux
const STATIC_MODE = 'DAUX_STATIC';
const LIVE_MODE = 'DAUX_LIVE';
/** @var string */
public $local_base;
public static $output;
/** @var string */
public $internal_base;
/** @var Tree\Root */
public $tree;
/** @var Config */
public $config;
/** @var \Todaymade\Daux\Format\Base\Generator */
protected $generator;
@ -24,221 +25,35 @@ class Daux
/** @var ContentTypeHandler */
protected $typeHandler;
/**
* @var string[]
*/
/** @var string[] */
protected $validExtensions;
/** @var Processor */
protected $processor;
/** @var Tree\Root */
public $tree;
/** @var Config */
public $options;
/** @var string */
private $mode;
/** @var bool */
private $merged_tree = false;
/**
* @param string $mode
*/
public function __construct($mode)
public function __construct(Config $config, OutputInterface $output)
{
$this->mode = $mode;
Daux::$output = $output;
$this->local_base = $this->internal_base = dirname(__DIR__);
// In case we're inside the phar archive
// we save the path to the directory
// in which it is contained
if (defined('PHAR_DIR')) {
$this->local_base = PHAR_DIR;
}
// global.json
$this->loadBaseConfiguration();
$this->config = $config;
}
/**
* @param string $override_file
* @throws Exception
*/
public function initializeConfiguration($override_file = null)
{
$params = $this->getParams();
// Validate and set theme path
$params->setDocumentationDirectory(
$docs_path = $this->normalizeDocumentationPath($this->getParams()->getDocumentationDirectory())
);
// Read documentation overrides
$this->loadConfiguration($docs_path . DIRECTORY_SEPARATOR . 'config.json');
// Read command line overrides
$override_file = $this->getConfigurationOverride($override_file);
if ($override_file != null) {
$params->setConfigurationOverrideFile($override_file);
$this->loadConfiguration($override_file);
}
// Validate and set theme path
$params->setThemesPath($this->normalizeThemePath($params->getThemesDirectory()));
// Set a valid default timezone
if ($params->hasTimezone()) {
date_default_timezone_set($params->getTimezone());
} elseif (!ini_get('date.timezone')) {
date_default_timezone_set('GMT');
}
}
/**
* Get the file requested for configuration overrides
*
* @param string|null $override_file
* @return string|null the path to a file to load for configuration overrides
* @throws Exception
*/
public function getConfigurationOverride($override_file)
{
// When running through `daux --serve` we set an environment variable to know where we started from
$env = getenv('DAUX_CONFIGURATION');
if ($env && file_exists($env)) {
return $env;
}
if ($override_file == null) {
return null;
}
if (file_exists($override_file)) {
if (DauxHelper::isAbsolutePath($override_file)) {
return $override_file;
}
return getcwd() . '/' . $override_file;
}
$newPath = $this->local_base . DIRECTORY_SEPARATOR . $override_file;
if (file_exists($newPath)) {
return $newPath;
}
throw new Exception('The configuration override file does not exist. Check the path again : ' . $override_file);
}
public function normalizeThemePath($path)
{
// When running through `daux --serve` we set an environment variable to know where we started from
$env = getenv('DAUX_THEME');
if ($env && is_dir($env)) {
return $env;
}
if (is_dir($path)) {
if (DauxHelper::isAbsolutePath($path)) {
return $path;
}
return getcwd() . '/' . $path;
}
$newPath = $this->local_base . DIRECTORY_SEPARATOR . $path;
if (is_dir($newPath)) {
return $newPath;
}
throw new Exception('The Themes directory does not exist. Check the path again : ' . $path);
}
public function normalizeDocumentationPath($path)
{
// When running through `daux --serve` we set an environment variable to know where we started from
$env = getenv('DAUX_SOURCE');
if ($env && is_dir($env)) {
return $env;
}
if (is_dir($path)) {
if (DauxHelper::isAbsolutePath($path)) {
return $path;
}
return getcwd() . '/' . $path;
}
throw new Exception('The Docs directory does not exist. Check the path again : ' . $path);
}
/**
* Load and validate the global configuration
*
* @throws Exception
*/
protected function loadBaseConfiguration()
{
$this->options = new Config();
// Set the default configuration
$this->options->merge([
'docs_directory' => 'docs',
'valid_content_extensions' => ['md', 'markdown'],
//Paths and tree
'mode' => $this->mode,
'local_base' => $this->local_base,
'templates' => 'templates',
'index_key' => 'index.html',
'base_page' => '',
'base_url' => '',
]);
// Load the global configuration
$this->loadConfiguration($this->local_base . DIRECTORY_SEPARATOR . 'global.json', false);
}
/**
* @param string $config_file
* @param bool $optional
* @throws Exception
*/
protected function loadConfiguration($config_file, $optional = true)
{
if (!file_exists($config_file)) {
if ($optional) {
return;
}
throw new Exception('The configuration file is missing. Check path : ' . $config_file);
}
$config = json_decode(file_get_contents($config_file), true);
if (!isset($config)) {
throw new Exception('The configuration file "' . $config_file . '" is corrupt. Is your JSON well-formed ?');
}
$this->options->merge($config);
}
/**
* Generate the tree that will be used
* Generate the tree that will be used.
*/
public function generateTree()
{
$this->options['valid_content_extensions'] = $this->getContentExtensions();
$this->config->setValidContentExtensions($this->getContentExtensions());
$this->tree = new Root($this->getParams());
Builder::build($this->tree, $this->options['ignore']);
$this->tree = new Root($this->getConfig());
Builder::build($this->tree, $this->config->getIgnore());
// Apply the language name as Section title
if ($this->options->isMultilanguage()) {
foreach ($this->options['languages'] as $key => $node) {
if ($this->config->isMultilanguage()) {
foreach ($this->config->getLanguages() as $key => $node) {
$this->tree->getEntries()[$key]->setTitle($node);
}
}
@ -247,58 +62,43 @@ class Daux
$this->getProcessor()->manipulateTree($this->tree);
// Sort the tree one last time before it is finalized
$this->sortTree($this->tree);
Builder::sortTree($this->tree);
$this->finalizeTree($this->tree);
}
public function sortTree(Directory $current)
{
$current->sort();
foreach ($current->getEntries() as $entry) {
if ($entry instanceof Directory) {
$this->sortTree($entry);
}
}
}
public function finalizeTree(Directory $current, $prev = null)
{
foreach ($current->getEntries() as $entry) {
if ($entry instanceof Directory) {
$prev = $this->finalizeTree($entry, $prev);
} elseif ($entry instanceof Content) {
if ($prev) {
$prev->setNext($entry);
$entry->setPrevious($prev);
}
$prev = $entry;
}
}
return $prev;
Builder::finalizeTree($this->tree);
}
/**
* @return Config
*/
public function getParams()
public function getConfig()
{
if ($this->tree && !$this->merged_tree) {
$this->options['tree'] = $this->tree;
$this->options['index'] = $this->tree->getIndexPage() ?: $this->tree->getFirstPage();
if ($this->options->isMultilanguage()) {
foreach ($this->options['languages'] as $key => $name) {
$this->options['entry_page'][$key] = $this->tree->getEntries()[$key]->getFirstPage();
$this->config->setTree($this->tree);
$this->config->setIndex($this->tree->getIndexPage() ?: $this->tree->getFirstPage());
$entry_page = null;
if ($this->config->isMultilanguage()) {
$entry_page = [];
foreach ($this->config->getLanguages() as $key => $name) {
$entry_page[$key] = $this->tree->getEntries()[$key]->getFirstPage();
}
} else {
$this->options['entry_page'] = $this->tree->getFirstPage();
$entry_page = $this->tree->getFirstPage();
}
$this->config->setEntryPage($entry_page);
$this->merged_tree = true;
}
return $this->options;
return $this->config;
}
/**
* @return Config
*
* @deprecated Use getConfig instead
*/
public function getParams()
{
return $this->getConfig();
}
/**
@ -307,23 +107,20 @@ class Daux
public function getProcessor()
{
if (!$this->processor) {
$this->processor = new Processor($this, new NullOutput(), 0);
$this->processor = new Processor($this, Daux::getOutput(), 0);
}
return $this->processor;
}
/**
* @param Processor $processor
*/
public function setProcessor(Processor $processor)
{
$this->processor = $processor;
// This is not the cleanest but it's
// the best i've found to use the
// the best I've found to use the
// processor in very remote places
$this->options['processor_instance'] = $processor;
$this->config->setProcessorInstance($processor);
}
public function getGenerators()
@ -339,10 +136,9 @@ class Daux
return array_replace($default, $extended);
}
public function getProcessorClass()
{
$processor = $this->getParams()['processor'];
$processor = $this->getConfig()->getProcessor();
if (empty($processor)) {
return null;
@ -360,6 +156,21 @@ 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
*/
@ -371,10 +182,22 @@ class Daux
$generators = $this->getGenerators();
$format = $this->getParams()->getFormat();
$format = $this->getConfig()->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];
@ -406,7 +229,7 @@ class Daux
}
/**
* Get all content file extensions
* Get all content file extensions.
*
* @return string[]
*/
@ -418,4 +241,41 @@ class Daux
return $this->validExtensions = $this->getContentTypeHandler()->getContentExtensions();
}
public static function getOutput()
{
if (!Daux::$output) {
Daux::$output = new NullOutput();
}
return Daux::$output;
}
/**
* Writes a message to the output.
*
* @param array|string $messages The message as an array of lines or a single string
* @param bool $newline Whether to add a newline
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
*/
public static function write($messages, $newline = false, $options = 0)
{
Daux::getOutput()->write($messages, $newline, $options);
}
/**
* Writes a message to the output and adds a newline at the end.
*
* @param array|string $messages The message as an array of lines of a single string
* @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
*/
public static function writeln($messages, $options = 0)
{
Daux::getOutput()->write($messages, true, $options);
}
public static function getVerbosity()
{
return Daux::getOutput()->getVerbosity();
}
}

Datei anzeigen

@ -1,65 +1,48 @@
<?php namespace Todaymade\Daux;
use Todaymade\Daux\Exception\LinkNotFoundException;
use Todaymade\Daux\Tree\Builder;
use Todaymade\Daux\Tree\Directory;
use Todaymade\Daux\Tree\Entry;
class DauxHelper
{
/**
* Set a new base_url for the configuration
* Set a new base_url for the configuration.
*
* @param Config $config
* @param string $base_url
*/
public static function rebaseConfiguration(Config $config, $base_url)
{
// Avoid changing the url if it is already correct
if ($config['base_url'] == $base_url && !empty($config['theme'])) {
if ($config->getBaseUrl() == $base_url && !empty($config->getTheme())) {
return;
}
// Change base url for all links on the pages
$config['base_url'] = $config['base_page'] = $base_url;
$config['base_url'] = $base_url;
$config['theme'] = static::getTheme($config, $base_url);
$config['image'] = str_replace('<base_url>', $base_url, $config['image']);
}
protected static function resolveVariant(Config $params)
{
if (array_key_exists('theme-variant', $params['html'])) {
return;
}
if (is_dir(realpath(($params->getThemesPath() . DIRECTORY_SEPARATOR . $params['html']['theme'])))) {
return;
}
$theme = explode('-', $params['html']['theme']);
// do we have a variant or only a theme ?
if (isset($theme[1])) {
$params['html']['theme-variant'] = array_pop($theme);
$params['html']['theme'] = implode('-', $theme);
} else {
$params['html']['theme'] = array_pop($theme);
}
if (!is_dir(realpath($params->getThemesPath() . DIRECTORY_SEPARATOR . $params['html']['theme']))) {
throw new \RuntimeException("Theme '{$params['html']['theme']}' not found");
}
$config['image'] = str_replace('<base_url>', $base_url, $config->getImage());
}
/**
* @param Config $params
* @param string $current_url
*
* @return array
*/
protected static function getTheme(Config $params, $current_url)
protected static function getTheme(Config $config, $current_url)
{
self::resolveVariant($params);
static $cache = [];
$theme_folder = $params->getThemesPath() . DIRECTORY_SEPARATOR . $params['html']['theme'];
$theme_url = $params['base_url'] . 'themes/' . $params['html']['theme'] . '/';
$htmlTheme = $config->getHTML()->getTheme();
$theme_folder = $config->getThemesPath() . DIRECTORY_SEPARATOR . $htmlTheme;
$theme_url = $config->getBaseUrl() . 'themes/' . $htmlTheme . '/';
$cache_key = "$current_url-$htmlTheme";
if (array_key_exists($cache_key, $cache)) {
return $cache[$cache_key];
}
$theme = [];
if (is_file($theme_folder . DIRECTORY_SEPARATOR . 'config.json')) {
@ -69,19 +52,20 @@ class DauxHelper
}
}
//Default parameters for theme
// Default parameters for theme
$theme += [
'name' => $params['html']['theme'],
'name' => $htmlTheme,
'css' => [],
'js' => [],
'fonts' => [],
'favicon' => '<base_url>themes/daux/img/favicon.png',
'templates' => $theme_folder . DIRECTORY_SEPARATOR . 'templates',
'variants' => [],
'with_search' => $config->getHTML()->hasSearch()
];
if (array_key_exists('theme-variant', $params['html'])) {
$variant = $params['html']['theme-variant'];
if ($config->getHTML()->hasThemeVariant()) {
$variant = $config->getHTML()->getThemeVariant();
if (!array_key_exists($variant, $theme['variants'])) {
throw new Exception("Variant '$variant' not found for theme '$theme[name]'");
}
@ -101,8 +85,16 @@ class DauxHelper
}
}
if ($theme['with_search']) {
$theme['css'][] = '<base_url>daux_libraries/search.css';
}
if (is_file($config->getDocumentationDirectory() . DIRECTORY_SEPARATOR . 'style.css')) {
$theme['css'][]= '<base_url>style.css';
}
$substitutions = [
'<local_base>' => $params['local_base'],
'<local_base>' => $config->getLocalBase(),
'<base_url>' => $current_url,
'<theme_url>' => $theme_url,
];
@ -117,13 +109,16 @@ class DauxHelper
}
}
$cache[$cache_key] = $theme;
return $theme;
}
/**
* Remove all '/./' and '/../' in a path, without actually checking the path
* Remove all '/./' and '/../' in a path, without actually checking the path.
*
* @param string $path
*
* @return string
*/
public static function getCleanPath($path)
@ -148,13 +143,13 @@ class DauxHelper
/**
* Get the possible output file names for a source file.
*
* @param Config $config
* @param string $part
*
* @return string[]
*/
public static function getFilenames(Config $config, $part)
{
$extensions = implode('|', array_map('preg_quote', $config['valid_content_extensions'])) . '|html';
$extensions = implode('|', array_map('preg_quote', $config->getValidContentExtensions())) . '|html';
$raw = preg_replace('/(.*)?\\.(' . $extensions . ')$/', '$1', $part);
$raw = Builder::removeSortingInformations($raw);
@ -163,11 +158,12 @@ class DauxHelper
}
/**
* Locate a file in the tree. Returns the file if found or false
* Locate a file in the tree. Returns the file if found or false.
*
* @param Directory $tree
* @param string $request
* @return Tree\Content|Tree\Raw|false
*
* @return false|Tree\Content|Tree\Raw
*/
public static function getFile($tree, $request)
{
@ -186,16 +182,24 @@ class DauxHelper
if ($node == '..') {
$tree = $tree->getParent();
continue;
}
$node = urldecode($node);
// if the node exists in the current request tree,
// change the $tree variable to reference the new
// node and proceed to the next url part
if (isset($tree->getEntries()[$node])) {
$tree = $tree->getEntries()[$node];
continue;
}
// We try a second time by decoding the url
$node = DauxHelper::slug(urldecode($node));
if (isset($tree->getEntries()[$node])) {
$tree = $tree->getEntries()[$node];
continue;
}
@ -205,6 +209,7 @@ class DauxHelper
foreach (static::getFilenames($tree->getConfig(), $node) as $filename) {
if (isset($tree->getEntries()[$filename])) {
$tree = $tree->getEntries()[$filename];
continue 2;
}
}
@ -237,22 +242,28 @@ class DauxHelper
* Taken from Stringy
*
* @param string $title
*
* @return string
*/
public static function slug($title)
{
foreach (static::charsArray() as $key => $value) {
$title = str_replace($value, $key, $title);
// Convert to ASCII
if (function_exists('transliterator_transliterate')) {
$title = transliterator_transliterate('Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC;', $title);
}
$title = iconv('utf-8', 'ASCII//TRANSLIT//IGNORE', $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);
@ -260,149 +271,10 @@ class DauxHelper
return trim($title, $separator);
}
/**
* Returns the replacements for the slug() method.
*
* Taken from Stringy
*
* @return array An array of replacements.
*/
public static function charsArray()
{
static $charsArray;
if (isset($charsArray)) {
return $charsArray;
}
return $charsArray = [
'a' => [
'à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ',
'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ä', 'ā', 'ą',
'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ',
'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ',
'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', ],
'b' => ['б', 'β', 'Ъ', 'Ь', 'ب'],
'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ',
'д', 'δ', 'د', 'ض', ],
'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ',
'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ',
'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э',
'є', 'ə', ],
'f' => ['ф', 'φ', 'ف'],
'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ج'],
'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه'],
'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į',
'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ',
'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ',
'ῗ', 'і', 'ї', 'и', ],
'j' => ['ĵ', 'ј', 'Ј'],
'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك'],
'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل'],
'm' => ['м', 'μ', 'م'],
'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن'],
'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ',
'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő',
'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό',
'ö', 'о', 'و', 'θ', ],
'p' => ['п', 'π'],
'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر'],
's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص'],
't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط'],
'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ',
'ự', 'ü', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', ],
'v' => ['в'],
'w' => ['ŵ', 'ω', 'ώ'],
'x' => ['χ'],
'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ',
'ϋ', 'ύ', 'ΰ', 'ي', ],
'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز'],
'aa' => ['ع'],
'ae' => ['æ'],
'ch' => ['ч'],
'dj' => ['ђ', 'đ'],
'dz' => ['џ'],
'gh' => ['غ'],
'kh' => ['х', 'خ'],
'lj' => ['љ'],
'nj' => ['њ'],
'oe' => ['œ'],
'ps' => ['ψ'],
'sh' => ['ш'],
'shch' => ['щ'],
'ss' => ['ß'],
'th' => ['þ', 'ث', 'ذ', 'ظ'],
'ts' => ['ц'],
'ya' => ['я'],
'yu' => ['ю'],
'zh' => ['ж'],
'(c)' => ['©'],
'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ',
'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Ä', 'Å', 'Ā',
'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ',
'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ',
'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', ],
'B' => ['Б', 'Β'],
'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ',
'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ',
'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э',
'Є', 'Ə', ],
'F' => ['Ф', 'Φ'],
'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
'H' => ['Η', 'Ή'],
'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į',
'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ',
'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', ],
'K' => ['К', 'Κ'],
'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ'],
'M' => ['М', 'Μ'],
'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ',
'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ö', 'Ø', 'Ō',
'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ',
'Ὸ', 'Ό', 'О', 'Θ', 'Ө', ],
'P' => ['П', 'Π'],
'R' => ['Ř', 'Ŕ', 'Р', 'Ρ'],
'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ',
'Ự', 'Û', 'Ü', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', ],
'V' => ['В'],
'W' => ['Ω', 'Ώ'],
'X' => ['Χ'],
'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ',
'Ы', 'Й', 'Υ', 'Ϋ', ],
'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
'AE' => ['Æ'],
'CH' => ['Ч'],
'DJ' => ['Ђ'],
'DZ' => ['Џ'],
'KH' => ['Х'],
'LJ' => ['Љ'],
'NJ' => ['Њ'],
'PS' => ['Ψ'],
'SH' => ['Ш'],
'SHCH' => ['Щ'],
'SS' => ['ẞ'],
'TH' => ['Þ'],
'TS' => ['Ц'],
'YA' => ['Я'],
'YU' => ['Ю'],
'ZH' => ['Ж'],
' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81",
"\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84",
"\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87",
"\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A",
"\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", ],
];
}
/**
* @param string $from
* @param string $to
*
* @return string
*/
public static function getRelativePath($from, $to)
@ -429,10 +301,10 @@ class DauxHelper
// add traversals up to first matching dir
$padLength = (count($relPath) + $remaining - 1) * -1;
$relPath = array_pad($relPath, $padLength, '..');
break;
} else {
//$relPath[0] = './' . $relPath[0];
}
//$relPath[0] = './' . $relPath[0];
}
}
@ -443,11 +315,13 @@ class DauxHelper
{
if (!is_string($path)) {
$mess = sprintf('String expected but was given %s', gettype($path));
throw new \InvalidArgumentException($mess);
}
if (!ctype_print($path)) {
$mess = 'Path can NOT have non-printable characters or be empty';
throw new \DomainException($mess);
}
@ -463,9 +337,74 @@ class DauxHelper
$parts = [];
if (!preg_match($regExp, $path, $parts)) {
$mess = sprintf('Path is NOT valid, was given %s', $path);
throw new \DomainException($mess);
}
return '' !== $parts['root'];
}
public static function getAbsolutePath($path)
{
if (DauxHelper::isAbsolutePath($path)) {
return $path;
}
return getcwd() . '/' . $path;
}
public static function is($path, $type)
{
return ($type == 'dir') ? is_dir($path) : file_exists($path);
}
/**
* @param Config $config
* @param string $url
*
* @throws LinkNotFoundException
*
* @return Entry
*/
public static function resolveInternalFile($config, $url)
{
$triedAbsolute = false;
// Legacy absolute paths could start with
// "!" In this case we will try to find
// the file starting at the root
if ($url[0] == '!' || $url[0] == '/') {
$url = ltrim($url, '!/');
if ($file = DauxHelper::getFile($config->getTree(), $url)) {
return $file;
}
$triedAbsolute = true;
}
// Seems it's not an absolute path or not found,
// so we'll continue with the current folder
if ($file = DauxHelper::getFile($config->getCurrentPage()->getParent(), $url)) {
return $file;
}
// If we didn't already try it, we'll
// do a pass starting at the root
if (!$triedAbsolute && $file = DauxHelper::getFile($config->getTree(), $url)) {
return $file;
}
throw new LinkNotFoundException("Could not locate file '$url'");
}
public static function isValidUrl($url)
{
return !empty($url) && $url[0] != '#';
}
public static function isExternalUrl($url)
{
return preg_match('#^(?:[a-z]+:)?//|^mailto:#', $url);
}
}

Datei anzeigen

@ -14,7 +14,7 @@ abstract class ContentPage extends SimplePage
/**
* @var Config
*/
protected $params;
protected $config;
/**
* @var ContentType
@ -38,9 +38,17 @@ abstract class ContentPage extends SimplePage
return $this->file;
}
public function setParams(Config $params)
public function setConfig(Config $config)
{
$this->params = $params;
$this->config = $config;
}
/**
* @deprecated use setConfig instead
*/
public function setParams(Config $config)
{
$this->setConfig($config);
}
/**
@ -65,11 +73,11 @@ abstract class ContentPage extends SimplePage
return $this->getPureContent();
}
public static function fromFile(Content $file, $params, ContentType $contentType)
public static function fromFile(Content $file, $config, ContentType $contentType)
{
$page = new static($file->getTitle(), $file->getContent());
$page->setFile($file);
$page->setParams($params);
$page->setConfig($config);
$page->setContentType($contentType);
return $page;

Datei anzeigen

@ -3,7 +3,7 @@
* Created by IntelliJ IDEA.
* User: onigoetz
* Date: 06/11/15
* Time: 20:27
* Time: 20:27.
*/
namespace Todaymade\Daux\Format\Base;
@ -67,7 +67,6 @@ class EmbedImages
//Get any file corresponding to the right one
$file = DauxHelper::getFile($this->tree, $url);
if ($file === false) {
return false;
}

Datei anzeigen

@ -6,15 +6,11 @@ use Todaymade\Daux\Daux;
interface Generator
{
/**
* @param Daux $daux
*/
public function __construct(Daux $daux);
/**
* @param InputInterface $input
* @param OutputInterface $output
* @param int $width
*
* @return mixed
*/
public function generateAll(InputInterface $input, OutputInterface $output, $width);

Datei anzeigen

@ -6,9 +6,7 @@ use Todaymade\Daux\Tree\Entry;
interface LiveGenerator extends Generator
{
/**
* @param Entry $node
* @param Config $params
* @return \Todaymade\Daux\Format\Base\Page
*/
public function generateOne(Entry $node, Config $params);
public function generateOne(Entry $node, Config $config);
}

Datei anzeigen

@ -3,14 +3,14 @@
interface Page
{
/**
* Get the converted content, without any template
* Get the converted content, without any template.
*
* @return string
*/
public function getPureContent();
/**
* Get the full content
* Get the full content.
*
* @return mixed
*/

Datei anzeigen

@ -24,7 +24,8 @@ class Api
}
/**
* This method is public due to test purposes
* This method is public due to test purposes.
*
* @return Client
*/
public function getClient()
@ -39,9 +40,8 @@ class Api
/**
* The standard error message from guzzle is quite poor in informations,
* this will give little bit more sense to it and return it
* this will give little bit more sense to it and return it.
*
* @param BadResponseException $e
* @return \Exception
*/
protected function handleError(BadResponseException $e)
@ -60,9 +60,9 @@ class Api
}
$message = $label .
' [url] ' . $request->getUri() .
' [status code] ' . $response->getStatusCode() .
' [message] ';
"\n [url] " . $request->getUri() .
"\n [status code] " . $response->getStatusCode() .
"\n [message] ";
$body = $response->getBody();
$json = json_decode($body, true);
@ -101,10 +101,11 @@ class Api
}
/**
* Get a list of pages
* Get a list of pages.
*
* @param int $rootPage
* @param bool $recursive
*
* @return array
*/
public function getList($rootPage, $recursive = false)
@ -153,6 +154,7 @@ class Api
* @param int $parent_id
* @param string $title
* @param string $content
*
* @return int
*/
public function createPage($parent_id, $title, $content)
@ -201,14 +203,56 @@ class Api
try {
$this->getClient()->put("content/$page_id", ['json' => $body]);
} catch (BadResponseException $e) {
throw $this->handleError($e);
$error = $this->handleError($e);
$re = '/\[([0-9]*),([0-9]*)\]$/';
preg_match($re, $error->getMessage(), $matches, PREG_OFFSET_CAPTURE, 0);
if (count($matches) == 3) {
echo "\nContent: \n";
echo $this->showSourceCode($content, $matches[1][0], $matches[2][0]);
}
throw $error;
}
}
public function showSourceCode($css, $lineNumber, $column)
{
$lines = preg_split("/\r?\n/", $css);
if ($lines === false) {
return $css;
}
$start = max($lineNumber - 3, 0);
$end = min($lineNumber + 2, count($lines));
$maxWidth = strlen("$end");
$filtered = array_slice($lines, $start, $end - $start);
$prepared = [];
foreach ($filtered as $index => $line) {
$number = $start + 1 + $index;
$gutter = substr(' ' . (' ' . $number), -$maxWidth) . ' | ';
if ($number == $lineNumber) {
$spacing = str_repeat(' ', strlen($gutter) + $column - 2);
$prepared[] = '>' . $gutter . $line . "\n " . $spacing . '^';
} else {
$prepared[] = ' ' . $gutter . $line;
}
}
return implode("\n", $prepared);
}
/**
* Delete a page
* Delete a page.
*
* @param int $page_id
*
* @return mixed
*/
public function deletePage($page_id)
@ -220,29 +264,21 @@ class Api
}
}
/**
* @param int $id
* @param array $attachment
*/
public function uploadAttachment($id, $attachment)
private function getAttachment($id, $attachment)
{
// Check if an attachment with
// this name is uploaded
try {
$url = "content/$id/child/attachment?filename=" . urlencode($attachment['filename']);
$result = json_decode($this->getClient()->get($url)->getBody(), true);
return json_decode($this->getClient()->get($url)->getBody(), true);
} catch (BadResponseException $e) {
throw $this->handleError($e);
}
}
$url = "content/$id/child/attachment";
// If the attachment is already uploaded,
// the update URL is different
if (count($result['results'])) {
$url .= "/{$result['results'][0]['id']}/data";
}
private function putAttachment($url, $attachment)
{
$contents = array_key_exists('file', $attachment) ? fopen($attachment['file']->getPath(), 'r') : $attachment['content'];
try {
@ -257,4 +293,43 @@ class Api
throw $this->handleError($e);
}
}
private function getFileSize($attachment)
{
if (array_key_exists('file', $attachment)) {
return filesize($attachment['file']->getPath());
}
if (function_exists('mb_strlen')) {
return mb_strlen($attachment['content']);
}
return strlen($attachment['content']);
}
/**
* @param int $id
* @param array $attachment
* @param callback $write Write output to the console
*/
public function uploadAttachment($id, $attachment, $write)
{
$result = $this->getAttachment($id, $attachment);
$url = "content/$id/child/attachment";
// If the attachment is already uploaded,
// the update URL is different
if (count($result['results'])) {
if ($this->getFileSize($attachment) == $result['results'][0]['extensions']['fileSize']) {
$write(' ( An attachment of the same size already exists, skipping. )');
return;
}
$url .= "/{$result['results'][0]['id']}/data";
}
$this->putAttachment($url, $attachment);
}
}

Datei anzeigen

@ -0,0 +1,80 @@
<?php namespace Todaymade\Daux\Format\Confluence;
use Todaymade\Daux\BaseConfig;
class Config extends BaseConfig
{
public function shouldAutoDeleteOrphanedPages()
{
if ($this->hasValue('delete')) {
return $this->getValue('delete');
}
return false;
}
public function getUpdateThreshold()
{
return $this->hasValue('update_threshold') ? $this->getValue('update_threshold') : 2;
}
public function getPrefix()
{
return $this->getValue('prefix');
}
public function getBaseUrl()
{
return $this->getValue('base_url');
}
public function getUser()
{
return $this->getValue('user');
}
public function getPassword()
{
return $this->getValue('pass');
}
public function getSpaceId()
{
return $this->getValue('space_id');
}
public function hasAncestorId()
{
return $this->hasValue('ancestor_id');
}
public function getAncestorId()
{
return $this->getValue('ancestor_id');
}
public function setAncestorId($value)
{
$this->setValue('ancestor_id', $value);
}
public function hasRootId()
{
return $this->hasValue('root_id');
}
public function getRootId()
{
return $this->getValue('root_id');
}
public function hasHeader()
{
return $this->hasValue('header');
}
public function getHeader()
{
return $this->getValue('header');
}
}

Datei anzeigen

@ -15,39 +15,40 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
//Embed images
// We do it after generation so we can catch the images that were in html already
$content = (new EmbedImages($this->params['tree']))
$content = (new EmbedImages($this->config->getTree()))
->embed(
$content,
$this->file,
function ($src, array $attributes, Entry $file) {
//Add the attachment for later upload
if ($file instanceof Raw) {
$filename = basename($file->getPath());
$this->attachments[$filename] = ['filename' => $filename, 'file' => $file];
} else if ($file instanceof ComputedRaw) {
} elseif ($file instanceof ComputedRaw) {
$filename = $file->getUri();
$this->attachments[$filename] = ['filename' => $filename, 'content' => $file->getContent()];
} else {
throw new \RuntimeException("Cannot embed image as we don't understand its type.");
}
return $this->createImageTag($filename, $attributes);
}
);
$intro = '';
if (array_key_exists('confluence', $this->params) && array_key_exists('header', $this->params['confluence']) && !empty($this->params['confluence']['header'])) {
$intro = '<ac:structured-macro ac:name="info"><ac:rich-text-body>' . $this->params['confluence']['header'] . '</ac:rich-text-body></ac:structured-macro>';
if ($this->config->getConfluenceConfiguration()->hasHeader()) {
$intro = '<ac:structured-macro ac:name="info"><ac:rich-text-body>' . $this->config->getConfluenceConfiguration()->getHeader() . '</ac:rich-text-body></ac:structured-macro>';
}
return $intro . $content;
}
/**
* Create an image tag for the specified filename
* Create an image tag for the specified filename.
*
* @param string $filename
* @param array $attributes
*
* @return string
*/
private function createImageTag($filename, $attributes)
@ -59,7 +60,7 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
$re = '/float:\s*?(left|right);?/';
if (preg_match($re, $value, $matches)) {
$img .= ' ac:align="' . $matches[1] . '"';
$value = preg_replace($re, "", $value, 1);
$value = preg_replace($re, '', $value, 1);
}
}

Datei anzeigen

@ -0,0 +1,31 @@
<?php namespace Todaymade\Daux\Format\Confluence\ContentTypes\Markdown;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\HtmlElement;
abstract class CodeRenderer implements BlockRendererInterface
{
public function escapeCDATA($content)
{
return str_replace(']]>', ']]]]><![CDATA[>', $content);
}
public function getHTMLElement($body, $language)
{
$body = '<![CDATA[' . $this->escapeCDATA($body) . ']]>';
$content = [];
if ($language) {
$content[] = new HtmlElement('ac:parameter', ['ac:name' => 'language'], $language);
}
$content[] = new HtmlElement('ac:plain-text-body', [], $body);
return new HtmlElement(
'ac:structured-macro',
['ac:name' => 'code'],
$content
);
}
}

Datei anzeigen

@ -1,7 +1,10 @@
<?php namespace Todaymade\Daux\Format\Confluence\ContentTypes\Markdown;
use League\CommonMark\Block\Element as BlockElement;
use League\CommonMark\Environment;
use League\CommonMark\Inline\Element as InlineElement;
use Todaymade\Daux\Config;
use Todaymade\Daux\ContentTypes\Markdown\TableOfContents;
class CommonMarkConverter extends \Todaymade\Daux\ContentTypes\Markdown\CommonMarkConverter
{
@ -14,12 +17,12 @@ class CommonMarkConverter extends \Todaymade\Daux\ContentTypes\Markdown\CommonMa
{
parent::extendEnvironment($environment, $config);
$environment->addBlockRenderer('Todaymade\Daux\ContentTypes\Markdown\TableOfContents', new TOCRenderer());
$environment->addBlockRenderer(TableOfContents::class, new TOCRenderer());
//Add code renderer
$environment->addBlockRenderer('FencedCode', new FencedCodeRenderer());
$environment->addBlockRenderer('IndentedCode', new IndentedCodeRenderer());
$environment->addBlockRenderer(BlockElement\FencedCode::class, new FencedCodeRenderer());
$environment->addBlockRenderer(BlockElement\IndentedCode::class, new IndentedCodeRenderer());
$environment->addInlineRenderer('Image', new ImageRenderer());
$environment->addInlineRenderer(InlineElement\Image::class, new ImageRenderer());
}
}

Datei anzeigen

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

Datei anzeigen

@ -2,11 +2,11 @@
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
class FencedCodeRenderer extends CodeRenderer
{
protected $supported_languages = [
'actionscript3',
@ -36,8 +36,6 @@ class FencedCodeRenderer implements BlockRendererInterface
protected $known_conversions = ['html' => 'html/xml', 'xml' => 'html/xml', 'js' => 'javascript'];
/**
* @param AbstractBlock $block
* @param HtmlRendererInterface $htmlRenderer
* @param bool $inTightList
*
* @return HtmlElement|string
@ -48,28 +46,18 @@ class FencedCodeRenderer implements BlockRendererInterface
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$content = [];
$language = $this->getLanguage($block->getInfoWords());
if ($language = $this->getLanguage($block->getInfoWords(), $htmlRenderer)) {
$content[] = new HtmlElement('ac:parameter', ['ac:name' => 'language'], $language);
}
$content[] = new HtmlElement('ac:plain-text-body', [], '<![CDATA[' . $block->getStringContent() . ']]>');
return new HtmlElement(
'ac:structured-macro',
['ac:name' => 'code'],
$content
);
return $this->getHTMLElement($block->getStringContent(), $language);
}
public function getLanguage($infoWords, ElementRendererInterface $htmlRenderer)
public function getLanguage($infoWords)
{
if (count($infoWords) === 0 || strlen($infoWords[0]) === 0) {
return false;
}
$language = $htmlRenderer->escape($infoWords[0], true);
$language = Xml::escape($infoWords[0]);
if (array_key_exists($language, $this->known_conversions)) {
$language = $this->known_conversions[$language];

Datei anzeigen

@ -4,12 +4,29 @@ use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Image;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
class ImageRenderer extends \League\CommonMark\Inline\Renderer\ImageRenderer
class ImageRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var ConfigurationInterface
*/
protected $config;
/**
* @var \League\CommonMark\Inline\Renderer\ImageRenderer
*/
protected $parent;
public function __construct()
{
$this->parent = new \League\CommonMark\Inline\Renderer\ImageRenderer();
}
/**
* @param Image $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
@ -28,6 +45,11 @@ class ImageRenderer extends \League\CommonMark\Inline\Renderer\ImageRenderer
);
}
return parent::render($inline, $htmlRenderer);
return $this->parent->render($inline, $htmlRenderer);
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->parent->setConfiguration($configuration);
}
}

Datei anzeigen

@ -2,15 +2,12 @@
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Element\IndentedCode;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
class IndentedCodeRenderer implements BlockRendererInterface
class IndentedCodeRenderer extends CodeRenderer
{
/**
* @param AbstractBlock $block
* @param HtmlRendererInterface $htmlRenderer
* @param bool $inTightList
*
* @return HtmlElement
@ -21,10 +18,6 @@ class IndentedCodeRenderer implements BlockRendererInterface
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
return new HtmlElement(
'ac:structured-macro',
['ac:name' => 'code'],
new HtmlElement('ac:plain-text-body', [], '<![CDATA[' . $block->getStringContent() . ']]>')
);
return $this->getHTMLElement($block->getStringContent(), '');
}
}

Datei anzeigen

@ -4,26 +4,19 @@ use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Link;
use Todaymade\Daux\DauxHelper;
class LinkRenderer extends \Todaymade\Daux\ContentTypes\Markdown\LinkRenderer
{
/**
* @param AbstractInline|Link $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
*/
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"
);
if (!($inline instanceof Link)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
// Default handling
@ -33,19 +26,29 @@ class LinkRenderer extends \Todaymade\Daux\ContentTypes\Markdown\LinkRenderer
// empty urls, anchors and absolute urls
// should not go through the url resolver
if (!$this->isValidUrl($url) || $this->isExternalUrl($url)) {
if (!DauxHelper::isValidUrl($url) || DauxHelper::isExternalUrl($url)) {
return $element;
}
//Internal links
$file = $this->resolveInternalFile($url);
// if there's a hash component in the url, ensure we
// don't put that part through the resolver.
$urlAndHash = explode('#', $url);
$url = $urlAndHash[0];
$link_props = [
'ri:content-title' => trim($this->daux['confluence']['prefix']) . ' ' . $file->getTitle(),
//Internal links
$file = DauxHelper::resolveInternalFile($this->daux, $url);
$link_props = [];
if (isset($urlAndHash[1])) {
$link_props["ac:anchor"] = $urlAndHash[1];
}
$page_props = [
'ri:content-title' => trim(trim($this->daux['confluence']['prefix']) . ' ' . $file->getTitle()),
'ri:space-key' => $this->daux['confluence']['space_id'],
];
$page = strval(new HtmlElement('ri:page', $link_props, '', true));
$page = strval(new HtmlElement('ri:page', $page_props, '', true));
$children = $htmlRenderer->renderInlines($inline->children());
if (strpos($children, '<') !== false) {
$children = '<ac:link-body>' . $children . '</ac:link-body>';
@ -53,6 +56,6 @@ class LinkRenderer extends \Todaymade\Daux\ContentTypes\Markdown\LinkRenderer
$children = '<ac:plain-text-link-body><![CDATA[' . $children . ']]></ac:plain-text-link-body>';
}
return new HtmlElement('ac:link', [], $page . $children);
return new HtmlElement('ac:link', $link_props, $page . $children);
}
}

Datei anzeigen

@ -3,11 +3,16 @@
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use Todaymade\Daux\ContentTypes\Markdown\TableOfContents;
class TOCRenderer implements BlockRendererInterface
{
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
if (!($block instanceof TableOfContents)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
return '<ac:structured-macro ac:name="toc"></ac:structured-macro>';
}
}

Datei anzeigen

@ -2,7 +2,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Config;
use Todaymade\Daux\Config as GlobalConfig;
use Todaymade\Daux\Console\RunAction;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Tree\Content;
@ -18,9 +18,6 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
/** @var Daux */
protected $daux;
/**
* @param Daux $daux
*/
public function __construct(Daux $daux)
{
$this->daux = $daux;
@ -30,7 +27,7 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
public function checkConfiguration()
{
$config = $this->daux->getParams();
$config = $this->daux->getConfig();
$confluence = $config->getConfluenceConfiguration();
if ($confluence == null) {
@ -40,7 +37,7 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
$mandatory = ['space_id', 'base_url', 'user', 'pass', 'prefix'];
$errors = [];
foreach ($mandatory as $key) {
if (!array_key_exists($key, $confluence)) {
if (!$confluence->hasValue($key)) {
$errors[] = $key;
}
}
@ -49,7 +46,7 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
throw new \RuntimeException("The following options are mandatory for confluence : '" . implode("', '", $errors) . "'");
}
if (!array_key_exists('ancestor_id', $confluence) && !array_key_exists('root_id', $confluence)) {
if (!$confluence->hasAncestorId() && !$confluence->hasRootId()) {
throw new \RuntimeException("You must specify an 'ancestor_id' or a 'root_id' for confluence.");
}
}
@ -60,7 +57,7 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
public function getContentTypes()
{
return [
new ContentTypes\Markdown\ContentType($this->daux->getParams()),
new ContentTypes\Markdown\ContentType($this->daux->getConfig()),
];
}
@ -69,18 +66,20 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
*/
public function generateAll(InputInterface $input, OutputInterface $output, $width)
{
$params = $this->daux->getParams();
$config = $this->daux->getConfig();
$confluence = $params['confluence'];
$this->prefix = trim($confluence['prefix']) . ' ';
$confluence = $config->getConfluenceConfiguration();
$this->prefix = trim($confluence->getPrefix()) . ' ';
if ($this->prefix == ' ') {
$this->prefix = '';
}
$tree = $this->runAction(
'Generating Tree ...',
$output,
$width,
function () use ($params) {
$tree = $this->generateRecursive($this->daux->tree, $params);
$tree['title'] = $this->prefix . $params['title'];
function () use ($config) {
$tree = $this->generateRecursive($this->daux->tree, $config);
$tree['title'] = $this->prefix . $config->getTitle();
return $tree;
}
@ -94,31 +93,31 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator
$publisher->publish($tree);
}
private function generateRecursive(Directory $tree, Config $params, $base_url = '')
private function generateRecursive(Directory $tree, GlobalConfig $config, $base_url = '')
{
$final = ['title' => $this->prefix . $tree->getTitle()];
$params['base_url'] = $params['base_page'] = $base_url;
$config['base_url'] = $base_url;
$params['image'] = str_replace('<base_url>', $base_url, $params['image']);
$config->setImage(str_replace('<base_url>', $base_url, $config->getImage()));
if ($base_url !== '') {
$params['entry_page'] = $tree->getFirstPage();
$config->setEntryPage($tree->getFirstPage());
}
foreach ($tree->getEntries() as $key => $node) {
if ($node instanceof Directory) {
$final['children'][$this->prefix . $node->getTitle()] = $this->generateRecursive(
$node,
$params,
$config,
'../' . $base_url
);
} elseif ($node instanceof Content) {
$params['request'] = $node->getUrl();
$config->setRequest($node->getUrl());
$contentType = $this->daux->getContentTypeHandler()->getType($node);
$data = [
'title' => $this->prefix . $node->getTitle(),
'file' => $node,
'page' => ContentPage::fromFile($node, $params, $contentType),
'page' => ContentPage::fromFile($node, $config, $contentType),
];
if ($key == 'index.html') {

Datei anzeigen

@ -7,71 +7,50 @@ class Publisher
{
use RunAction;
/**
* @var Api
*/
protected $client;
/**
* @var array
*/
protected $confluence;
/**
* @var string
*/
protected $previous_title;
/**
* @var int terminal width
*/
public $width;
/**
* @var
* @var \Symfony\Component\Console\Output\OutputInterface
*/
public $output;
/**
* @var Api
*/
protected $client;
/**
* @var Config
*/
protected $confluence;
/**
* @param $confluence
*/
public function __construct($confluence)
public function __construct(Config $confluence)
{
$this->confluence = $confluence;
$this->client = new Api($confluence['base_url'], $confluence['user'], $confluence['pass']);
$this->client->setSpace($confluence['space_id']);
$this->client = new Api($confluence->getBaseUrl(), $confluence->getUser(), $confluence->getPassword());
$this->client->setSpace($confluence->getSpaceId());
}
public function run($title, $closure)
{
try {
return $this->runAction($title, $this->output, $this->width, $closure);
return $this->runAction($title, $this->width, $closure);
} catch (BadResponseException $e) {
$this->output->writeLn(' <error>' . $e->getMessage() . '</error>');
$this->output->writeLn('<fg=red>' . $e->getMessage() . '</>');
}
}
public function publish(array $tree)
{
echo "Finding Root Page...\n";
if (array_key_exists('ancestor_id', $this->confluence)) {
$pages = $this->client->getList($this->confluence['ancestor_id']);
$published = null;
foreach ($pages as $page) {
if ($page['title'] == $tree['title']) {
$published = $page;
break;
}
}
} elseif (array_key_exists('root_id', $this->confluence)) {
$published = $this->client->getPage($this->confluence['root_id']);
$this->confluence['ancestor_id'] = $published['ancestor_id'];
} else {
throw new \RuntimeException('You must at least specify a `root_id` or `ancestor_id` in your confluence configuration.');
}
$this->output->writeLn('Finding Root Page...');
$published = $this->getRootPage($tree);
$this->run(
'Getting already published pages...',
@ -83,38 +62,43 @@ class Publisher
);
$published = $this->run(
"Create placeholder pages...\n",
'Create placeholder pages...',
function () use ($tree, $published) {
return $this->createRecursive($this->confluence['ancestor_id'], $tree, $published);
return $this->createRecursive($this->confluence->getAncestorId(), $tree, $published);
}
);
$this->output->writeLn('Publishing updates...');
$published = $this->updateRecursive($this->confluence['ancestor_id'], $tree, $published);
$published = $this->updateRecursive($this->confluence->getAncestorId(), $tree, $published);
if ($this->shouldDelete()) {
$this->output->writeLn('Deleting obsolete pages...');
} else {
$this->output->writeLn('Listing obsolete pages...');
echo "> The following pages will not be deleted, but just listed for information.\n";
echo "> If you want to delete these pages, you need to set the --delete flag on the command.\n";
}
$this->deleteRecursive($published);
$delete = new PublisherDelete($this->output, $this->confluence->shouldAutoDeleteOrphanedPages(), $this->client);
$delete->handle($published);
}
protected function niceTitle($title)
protected function getRootPage($tree)
{
if ($title == 'index.html') {
return 'Homepage';
if ($this->confluence->hasAncestorId()) {
$pages = $this->client->getList($this->confluence->getAncestorId());
foreach ($pages as $page) {
if ($page['title'] == $tree['title']) {
return $page;
}
}
}
return rtrim(strtr($title, ['index.html' => '', '.html' => '']), '/');
if ($this->confluence->hasRootId()) {
$published = $this->client->getPage($this->confluence->getRootId());
$this->confluence->setAncestorId($published['ancestor_id']);
return $published;
}
throw new \RuntimeException('You must at least specify a `root_id` or `ancestor_id` in your confluence configuration.');
}
protected function createPage($parent_id, $entry, $published)
{
echo '- ' . $this->niceTitle($entry['file']->getUrl()) . "\n";
echo '- ' . PublisherUtilities::niceTitle($entry['file']->getUrl()) . "\n";
$published['version'] = 1;
$published['title'] = $entry['title'];
$published['id'] = $this->client->createPage($parent_id, $entry['title'], 'The content will come very soon !');
@ -192,88 +176,15 @@ class Publisher
return $this->recursiveWithCallback($parent_id, $entry, $published, $callback);
}
protected function shouldDelete()
{
return array_key_exists('delete', $this->confluence) && $this->confluence['delete'];
}
protected function deleteRecursive($published, $prefix = '')
{
foreach ($published['children'] as $child) {
if (array_key_exists('children', $child) && count($child['children'])) {
$this->deleteRecursive($child, $child['title'] . '/');
}
if (!array_key_exists('needed', $child)) {
if ($this->shouldDelete()) {
$this->run(
'- ' . $prefix . $child['title'],
function () use ($child) {
$this->client->deletePage($child['id']);
}
);
} else {
echo '- ' . $prefix . $child['title'] . "\n";
}
}
}
}
protected function shouldUpdate($local, $local_content, $published)
{
if (!array_key_exists('content', $published)) {
return true;
}
$trimmed_local = trim($local_content);
$trimmed_distant = trim($published['content']);
if ($trimmed_local == $trimmed_distant) {
return false;
}
// I consider that if the files are 98% identical you
// don't need to update. This will work for false positives.
// But sadly will miss if it's just a typo update
// This is configurable with `update_threshold`
$threshold = 98;
if (array_key_exists('update_threshold', $this->confluence)) {
$threshold = 100 - $this->confluence['update_threshold'];
}
if ($threshold < 100) {
similar_text($trimmed_local, $trimmed_distant, $percent);
if ($percent > $threshold) {
return false;
}
}
//DEBUG
if (getenv('DEBUG') && strtolower(getenv('DEBUG')) != 'false') {
$prefix = 'static/export/';
if (!is_dir($prefix)) {
mkdir($prefix, 0777, true);
}
$url = $local->getFile()->getUrl();
file_put_contents($prefix . strtr($url, ['/' => '_', '.html' => '_local.html']), $trimmed_local);
file_put_contents($prefix . strtr($url, ['/' => '_', '.html' => '_distant.html']), $trimmed_distant);
}
return true;
}
protected function updatePage($parent_id, $entry, $published)
{
if ($this->previous_title != 'Updating') {
$this->previous_title = 'Updating';
echo "Updating Pages...\n";
}
$updateThreshold = $this->confluence->getUpdateThreshold();
$this->run(
'- ' . $this->niceTitle($entry['file']->getUrl()),
function () use ($entry, $published, $parent_id) {
'- ' . PublisherUtilities::niceTitle($entry['file']->getUrl()),
function () use ($entry, $published, $parent_id, $updateThreshold) {
$generated_content = $entry['page']->getContent();
if ($this->shouldUpdate($entry['page'], $generated_content, $published)) {
if (PublisherUtilities::shouldUpdate($entry['page'], $generated_content, $published, $updateThreshold)) {
$this->client->updatePage(
$parent_id,
$published['id'],
@ -289,8 +200,8 @@ class Publisher
foreach ($entry['page']->attachments as $attachment) {
$this->run(
" With attachment: $attachment[filename]",
function () use ($published, $attachment) {
$this->client->uploadAttachment($published['id'], $attachment);
function ($write) use ($published, $attachment) {
$this->client->uploadAttachment($published['id'], $attachment, $write);
}
);
}

Datei anzeigen

@ -0,0 +1,80 @@
<?php namespace Todaymade\Daux\Format\Confluence;
class PublisherDelete
{
/**
* @var \Symfony\Component\Console\Output\OutputInterface
*/
public $output;
/**
* @var array files that can be deleted
*/
protected $deletable;
/**
* @var bool should delete ?
*/
protected $delete;
/**
* @var Api
*/
protected $client;
public function __construct($output, bool $delete, $client)
{
$this->output = $output;
$this->delete = $delete;
$this->client = $client;
$this->deletable = [];
}
protected function listDeletable($published, $prefix = '')
{
foreach ($published['children'] as $child) {
if (array_key_exists('children', $child) && count($child['children'])) {
$this->listDeletable($child, $child['title'] . '/');
}
if (!array_key_exists('needed', $child)) {
$this->deletable[$child['id']] = $prefix . $child['title'];
}
}
}
public function handle($published)
{
$this->listDeletable($published);
if (!count($this->deletable)) {
return;
}
if ($this->delete) {
$this->doDelete();
} else {
$this->displayDeletable();
}
}
protected function doDelete()
{
$this->output->writeLn('Deleting obsolete pages...');
foreach ($this->deletable as $id => $title) {
$this->output->writeLn("- $title");
$this->client->deletePage($id);
}
}
protected function displayDeletable()
{
$this->output->writeLn('Listing obsolete pages...');
$this->output->writeLn('> The following pages will not be deleted, but just listed for information.');
$this->output->writeLn('> If you want to delete these pages, you need to set the --delete flag on the command.');
foreach ($this->deletable as $id => $title) {
$this->output->writeLn("- $title");
}
}
}

Datei anzeigen

@ -0,0 +1,53 @@
<?php namespace Todaymade\Daux\Format\Confluence;
class PublisherUtilities
{
public static function niceTitle($title)
{
if ($title == 'index.html') {
return 'Homepage';
}
return rtrim(strtr($title, ['index.html' => '', '.html' => '']), '/');
}
public static function shouldUpdate($local, $local_content, $published, $threshold)
{
if (!array_key_exists('content', $published)) {
return true;
}
$trimmed_local = trim($local_content);
$trimmed_distant = trim($published['content']);
if ($trimmed_local == $trimmed_distant) {
return false;
}
// I consider that if the files are 98% identical you
// don't need to update. This will work for false positives.
// But sadly will miss if it's just a typo update
// This is configurable with `update_threshold`
$threshold = 100 - $threshold;
if ($threshold < 100) {
similar_text($trimmed_local, $trimmed_distant, $percent);
if ($percent > $threshold) {
return false;
}
}
//DEBUG
if (getenv('DEBUG') && strtolower(getenv('DEBUG')) != 'false') {
$prefix = 'static/export/';
if (!is_dir($prefix)) {
mkdir($prefix, 0777, true);
}
$url = $local->getFile()->getUrl();
file_put_contents($prefix . strtr($url, ['/' => '_', '.html' => '_local.html']), $trimmed_local);
file_put_contents($prefix . strtr($url, ['/' => '_', '.html' => '_distant.html']), $trimmed_distant);
}
return true;
}
}

Datei anzeigen

@ -10,27 +10,182 @@ class Config extends BaseConfig
return [
'name' => 'GitHub',
'basepath' => (strpos($url, 'https://github.com/') === 0 ? '' : 'https://github.com/') . trim($url, '/')
'basepath' => (strpos($url, 'https://github.com/') === 0 ? '' : 'https://github.com/') . trim($url, '/'),
];
}
function getEditOn()
public function getEditOn()
{
if (array_key_exists('edit_on', $this)) {
if (is_string($this['edit_on'])) {
return $this->prepareGithubUrl($this['edit_on']);
} else {
$this['edit_on']['basepath'] = rtrim($this['edit_on']['basepath'], '/');
return $this['edit_on'];
if ($this->hasValue('edit_on')) {
$edit_on = $this->getValue('edit_on');
if (is_string($edit_on)) {
return $this->prepareGithubUrl($edit_on);
}
$edit_on['basepath'] = rtrim($edit_on['basepath'], '/');
return $edit_on;
}
if (array_key_exists('edit_on_github', $this)) {
return $this->prepareGithubUrl($this['edit_on_github']);
if ($this->hasValue('edit_on_github')) {
return $this->prepareGithubUrl($this->getValue('edit_on_github'));
}
return null;
}
public function hasSearch()
{
return $this->hasValue('search') && $this->getValue('search');
}
public function showDateModified()
{
return $this->hasValue('date_modified') && $this->getValue('date_modified');
}
public function showPreviousNextLinks()
{
if ($this->hasValue('jump_buttons')) {
return $this->getValue('jump_buttons');
}
return true;
}
public function showCodeToggle()
{
if ($this->hasValue('toggle_code')) {
return $this->getValue('toggle_code');
}
return true;
}
public function hasAutomaticTableOfContents(): bool
{
return $this->hasValue('auto_toc') && $this->getValue('auto_toc');
}
public function hasGoogleAnalytics()
{
return $this->hasValue('google_analytics') && $this->getValue('google_analytics');
}
public function getGoogleAnalyticsId()
{
return $this->getValue('google_analytics');
}
public function hasPlausibleAnalyticsDomain()
{
return $this->hasValue('plausible_domain') && $this->getValue('plausible_domain');
}
public function getPlausibleAnalyticsDomain()
{
return $this->getValue('plausible_domain');
}
public function hasPiwikAnalytics()
{
return $this->getValue('piwik_analytics') && $this->hasValue('piwik_analytics_id');
}
public function getPiwikAnalyticsId()
{
return $this->getValue('piwik_analytics_id');
}
public function getPiwikAnalyticsUrl()
{
return $this->getValue('piwik_analytics');
}
public function hasPoweredBy()
{
return $this->hasValue('powered_by') && !empty($this->getValue('powered_by'));
}
public function getPoweredBy()
{
return $this->getValue('powered_by');
}
public function hasTwitterHandles()
{
return $this->hasValue('twitter') && !empty($this->getValue('twitter'));
}
public function getTwitterHandles()
{
return $this->getValue('twitter');
}
public function hasLinks()
{
return $this->hasValue('links') && !empty($this->getValue('links'));
}
public function getLinks()
{
return $this->getValue('links');
}
public function hasRepository()
{
return $this->hasValue('repo') && !empty($this->getValue('repo'));
}
public function getRepository()
{
return $this->getValue('repo');
}
public function hasButtons()
{
return $this->hasValue('buttons') && !empty($this->getValue('buttons'));
}
public function getButtons()
{
return $this->getValue('buttons');
}
public function hasLandingPage()
{
if ($this->hasValue('auto_landing')) {
return $this->getValue('auto_landing');
}
return true;
}
public function hasBreadcrumbs()
{
if ($this->hasValue('breadcrumbs')) {
return $this->getValue('breadcrumbs');
}
return true;
}
public function getBreadcrumbsSeparator()
{
return $this->getValue('breadcrumb_separator');
}
public function getTheme()
{
return $this->getValue('theme');
}
public function hasThemeVariant()
{
return $this->hasValue('theme-variant') && !empty($this->getValue('theme-variant'));
}
public function getThemeVariant()
{
return $this->getValue('theme-variant');
}
}

Datei anzeigen

@ -4,27 +4,34 @@ use Todaymade\Daux\Tree\Root;
class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
{
/**
* @var Template
*/
public $templateRenderer;
/**
* @var string
*/
private $language;
/**
* @var bool
*/
private $homepage;
private function isHomepage()
private function isHomepage(): bool
{
// If the current page isn't the index, no chance it is the landing page
if ($this->file->getParent()->getIndexPage() != $this->file) {
return false;
}
// If the direct parent is root, this is the homage
// If the direct parent is root, this is the homepage
return $this->file->getParent() instanceof Root;
}
private function isLanding() {
// If we don't have the auto_landing parameter, we don't want any homepage
if (array_key_exists('auto_landing', $this->params['html']) && !$this->params['html']['auto_landing']) {
return false;
}
return $this->homepage;
private function isLanding(): bool
{
return $this->config->getHTML()->hasLandingPage() && $this->homepage;
}
private function initialize()
@ -32,7 +39,7 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
$this->homepage = $this->isHomepage();
$this->language = '';
if ($this->params->isMultilanguage() && count($this->file->getParents())) {
if ($this->config->isMultilanguage() && count($this->file->getParents())) {
$language_dir = $this->file->getParents()[0];
$this->language = $language_dir->getName();
}
@ -41,6 +48,7 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
/**
* @param \Todaymade\Daux\Tree\Directory[] $parents
* @param bool $multilanguage
*
* @return array
*/
private function getBreadcrumbTrail($parents, $multilanguage)
@ -52,7 +60,7 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
if (!empty($parents)) {
foreach ($parents as $node) {
$page = $node->getIndexPage() ?: $node->getFirstPage();
$breadcrumb_trail[$node->getTitle()] = $page ? $page->getUrl() : '';
$breadcrumb_trail[] = ['title' => $node->getTitle(), 'url' => $page ? $page->getUrl() : ''];
}
}
@ -62,16 +70,16 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
protected function generatePage()
{
$this->initialize();
$params = $this->params;
$config = $this->config;
$entry_page = [];
if ($this->homepage) {
if ($params->isMultilanguage()) {
foreach ($params['languages'] as $key => $name) {
$entry_page[$name] = $params['base_page'] . $params['entry_page'][$key]->getUrl();
if ($config->isMultilanguage()) {
foreach ($config->getLanguages() as $key => $name) {
$entry_page[$name] = $config->getBasePage() . $config->getEntryPage()[$key]->getUrl();
}
} else {
$entry_page['View Documentation'] = $params['base_page'] . $params['entry_page']->getUrl();
$entry_page['__VIEW_DOCUMENTATION__'] = $config->getBasePage() . $config->getEntryPage()->getUrl();
}
}
@ -85,26 +93,34 @@ class ContentPage extends \Todaymade\Daux\Format\Base\ContentPage
'relative_path' => $this->file->getRelativePath(),
'modified_time' => filemtime($this->file->getPath()),
'markdown' => $this->content,
'request' => $params['request'],
'request' => $config->getRequest(),
'content' => $this->getPureContent(),
'breadcrumbs' => $params['html']['breadcrumbs'],
'breadcrumbs' => $config->getHTML()->hasBreadcrumbs(),
'prev' => $this->file->getPrevious(),
'next' => $this->file->getNext(),
'attributes' => $this->file->getAttribute(),
];
if ($page['breadcrumbs']) {
$page['breadcrumb_trail'] = $this->getBreadcrumbTrail($this->file->getParents(), $params->isMultilanguage());
$page['breadcrumb_separator'] = $params['html']['breadcrumb_separator'];
$page['breadcrumb_trail'] = $this->getBreadcrumbTrail($this->file->getParents(), $config->isMultilanguage());
$page['breadcrumb_separator'] = $this->config->getHTML()->getBreadcrumbsSeparator();
if ($this->homepage) {
$page['breadcrumb_trail'] = [$this->file->getTitle() => ''];
$page['breadcrumb_trail'] = [['title' => $this->file->getTitle(), 'url' => '']];
}
}
$context = ['page' => $page, 'params' => $params];
$context = ['page' => $page, 'config' => $config];
$template = new Template($params['templates'], $params['theme']['templates']);
$template = 'theme::content';
if ($this->isLanding()) {
$template = 'theme::home';
}
return $template->render($this->isLanding() ? 'theme::home' : 'theme::content', $context);
if (array_key_exists('template', $page['attributes'])) {
$template = 'theme::' . $page['attributes']['template'];
}
return $this->templateRenderer->render($template, $context);
}
}

Datei anzeigen

@ -1,7 +1,11 @@
<?php namespace Todaymade\Daux\Format\HTML\ContentTypes\Markdown;
use League\CommonMark\Block\Element as BlockElement;
use League\CommonMark\Environment;
use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Inline\Element as InlineElement;
use Todaymade\Daux\Config;
use Todaymade\Daux\ContentTypes\Markdown\TableOfContents;
class CommonMarkConverter extends \Todaymade\Daux\ContentTypes\Markdown\CommonMarkConverter
{
@ -9,7 +13,12 @@ class CommonMarkConverter extends \Todaymade\Daux\ContentTypes\Markdown\CommonMa
{
parent::extendEnvironment($environment, $config);
$environment->addDocumentProcessor(new TOC\Processor($config));
$environment->addBlockRenderer('Todaymade\Daux\ContentTypes\Markdown\TableOfContents', new TOC\Renderer());
$environment->addBlockRenderer(BlockElement\FencedCode::class, new FencedCodeRenderer());
$processor = new TOC\Processor($config);
$environment->addEventListener(DocumentParsedEvent::class, [$processor, 'onDocumentParsed']);
$environment->addBlockRenderer(TableOfContents::class, new TOC\Renderer($config));
$environment->addInlineRenderer(InlineElement\Image::class, new ImageRenderer($config));
}
}

Datei anzeigen

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

Datei anzeigen

@ -0,0 +1,74 @@
<?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
{
/**
* @var Highlighter
*/
private $hl;
public function __construct()
{
$this->hl = new Highlighter();
}
/**
* @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]);
}
}

Datei anzeigen

@ -0,0 +1,95 @@
<?php namespace Todaymade\Daux\Format\HTML\ContentTypes\Markdown;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Inline\Element\Image;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
use League\CommonMark\Util\ConfigurationAwareInterface;
use League\CommonMark\Util\ConfigurationInterface;
use Todaymade\Daux\Config;
use Todaymade\Daux\DauxHelper;
use Todaymade\Daux\Exception\LinkNotFoundException;
class ImageRenderer implements InlineRendererInterface, ConfigurationAwareInterface
{
/**
* @var Config
*/
protected $daux;
/**
* @var ConfigurationInterface
*/
protected $config;
/**
* @var \League\CommonMark\Inline\Renderer\ImageRenderer
*/
protected $parent;
public function __construct($daux)
{
$this->daux = $daux;
$this->parent = new \League\CommonMark\Inline\Renderer\ImageRenderer();
}
/**
* Relative URLs can be done using either the folder with
* number prefix or the final name (with prefix stripped).
* This ensures that we always use the final name when generating.
*
* @param mixed $url
*
* @throws LinkNotFoundException
*/
protected function getCleanUrl($url)
{
// empty urls and anchors should
// not go through the url resolver
if (!DauxHelper::isValidUrl($url)) {
return $url;
}
// Absolute urls, shouldn't either
if (DauxHelper::isExternalUrl($url)) {
return $url;
}
try {
$file = DauxHelper::resolveInternalFile($this->daux, $url);
return DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
} catch (LinkNotFoundException $e) {
if ($this->daux->isStatic()) {
throw $e;
}
}
return $url;
}
/**
* @param Image $inline
*
* @throws LinkNotFoundException
*
* @return HtmlElement
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
if (!($inline instanceof Image)) {
throw new \InvalidArgumentException('Incompatible inline type: ' . \get_class($inline));
}
$inline->setUrl($this->getCleanUrl($inline->getUrl()));
return $this->parent->render($inline, $htmlRenderer);
}
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->config = $configuration;
$this->parent->setConfiguration($configuration);
}
}

Datei anzeigen

@ -6,7 +6,7 @@ class Entry
{
protected $content;
protected $level;
protected $parent = null;
protected $parent;
protected $children = [];
public function __construct(Heading $content)
@ -56,7 +56,6 @@ class Entry
}
/**
* @param Entry $parent
* @param bool $addChild
*/
public function setParent(Entry $parent, $addChild = true)
@ -67,9 +66,6 @@ class Entry
}
}
/**
* @param Entry $child
*/
public function addChild(Entry $child)
{
$child->setParent($this, false);

Datei anzeigen

@ -7,16 +7,20 @@ use League\CommonMark\Block\Element\ListBlock;
use League\CommonMark\Block\Element\ListData;
use League\CommonMark\Block\Element\ListItem;
use League\CommonMark\Block\Element\Paragraph;
use League\CommonMark\DocumentProcessorInterface;
use League\CommonMark\Event\DocumentParsedEvent;
use League\CommonMark\Inline\Element\Link;
use League\CommonMark\Inline\Element\Text;
use League\CommonMark\Node\Node;
use ReflectionMethod;
use Todaymade\Daux\Config;
use Todaymade\Daux\ContentTypes\Markdown\TableOfContents;
use Todaymade\Daux\DauxHelper;
class Processor implements DocumentProcessorInterface
class Processor
{
/**
* @var Config
*/
protected $config;
public function __construct(Config $config)
@ -24,18 +28,9 @@ class Processor implements DocumentProcessorInterface
$this->config = $config;
}
public function hasAutoTOC()
{
return array_key_exists('html', $this->config) && array_key_exists('auto_toc', $this->config['html']) && $this->config['html']['auto_toc'];
}
/**
* @param Document $document
*
* @return void
*/
public function processDocument(Document $document)
public function onDocumentParsed(DocumentParsedEvent $event)
{
$document = $event->getDocument();
/** @var TableOfContents[] $tocs */
$tocs = [];
@ -48,6 +43,7 @@ class Processor implements DocumentProcessorInterface
if ($node instanceof TableOfContents && !$event->isEntering()) {
$tocs[] = $node;
continue;
}
@ -59,7 +55,7 @@ class Processor implements DocumentProcessorInterface
$headings[] = new Entry($node);
}
if (count($headings) && (count($tocs) || $this->hasAutoTOC())) {
if (count($headings) && (count($tocs) || $this->config->getHTML()->hasAutomaticTableOfContents())) {
$generated = $this->generate($headings);
if (count($tocs)) {
@ -72,49 +68,33 @@ class Processor implements DocumentProcessorInterface
}
}
/**
* Get an escaped version of the link
* @param string $url
* @return string
*/
protected function escaped($url) {
$url = trim($url);
$url = preg_replace('~[^\\pL0-9_]+~u', '-', $url);
$url = trim($url, "-");
$url = iconv("utf-8", "us-ascii//TRANSLIT", $url);
$url = preg_replace('~[^-a-zA-Z0-9_]+~', '', $url);
return $url;
}
protected function getUniqueId(Document $document, $proposed) {
if ($proposed == "page_") {
$proposed = "page_section_" . (count($document->heading_ids) + 1);
protected function getUniqueId(Document $document, $proposed)
{
if ($proposed == 'page_') {
$proposed = 'page_section_' . (count($document->heading_ids) + 1);
}
// Quick path, it's a unique ID
if (!in_array($proposed, $document->heading_ids)) {
$document->heading_ids[] = $proposed;
return $proposed;
}
$extension = 1; // Initialize the variable at one, so on the first iteration we have 2
do {
$extension++;
++$extension;
} while (in_array("$proposed-$extension", $document->heading_ids));
return "$proposed-$extension";
}
/**
* @param Heading $node
*/
protected function ensureHeadingHasId(Document $document, Heading $node)
{
// If the node has an ID, no need to generate it, just check it's unique
$attributes = $node->getData('attributes', []);
if (array_key_exists('id', $attributes) && !empty($attributes['id'])) {
$node->data['attributes']['id'] = $this->getUniqueId($document, $attributes['id']);
$node->data['attributes']['id'] = $this->getUniqueId($document, $attributes['id']);
return;
}
@ -139,13 +119,14 @@ class Processor implements DocumentProcessorInterface
}
}
$node->data['attributes']['id'] = $this->getUniqueId($document,'page_'. $this->escaped($text));
$node->data['attributes']['id'] = $this->getUniqueId($document, 'page_' . DauxHelper::slug($text));
}
/**
* Make a tree of the list of headings
* Make a tree of the list of headings.
*
* @param Entry[] $headings
*
* @return RootEntry
*/
public function generate($headings)
@ -161,19 +142,21 @@ class Processor implements DocumentProcessorInterface
$parent->addChild($heading);
$previous = $heading;
continue;
}
if ($heading->getLevel() > $previous->getLevel()) {
$previous->addChild($heading);
$previous = $heading;
continue;
}
//if ($heading->getLevel() == $previous->getLevel()) {
$previous->getParent()->addChild($heading);
$previous = $heading;
continue;
//}
}
@ -183,6 +166,7 @@ class Processor implements DocumentProcessorInterface
/**
* @param Entry[] $entries
*
* @return ListBlock
*/
protected function render(array $entries)
@ -234,7 +218,6 @@ class Processor implements DocumentProcessorInterface
}
/**
* @param Heading $node
* @return Node[]
*/
protected function cloneChildren(Heading $node)
@ -254,8 +237,6 @@ class Processor implements DocumentProcessorInterface
$method->invoke($subnode, $firstClone);
}
$deepCopy = new DeepCopy();
return $deepCopy->copy($firstClone)->children();
return (new DeepCopy())->copy($firstClone)->children();
}
}

Datei anzeigen

@ -3,11 +3,31 @@
use League\CommonMark\Block\Element\AbstractBlock;
use League\CommonMark\Block\Renderer\BlockRendererInterface;
use League\CommonMark\ElementRendererInterface;
use Todaymade\Daux\Config;
use Todaymade\Daux\ContentTypes\Markdown\TableOfContents;
class Renderer implements BlockRendererInterface
{
/**
* @var Config
*/
private $config;
public function __construct(Config $config)
{
$this->config = $config;
}
public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, $inTightList = false)
{
return $htmlRenderer->renderBlocks($block->children());
if (!($block instanceof TableOfContents)) {
throw new \InvalidArgumentException('Incompatible block type: ' . get_class($block));
}
$content = $htmlRenderer->renderBlocks($block->children());
return $this->config->templateRenderer
->getEngine($this->config)
->render('theme::partials/table_of_contents', ['content' => $content]);
}
}

Datei anzeigen

@ -2,7 +2,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Config;
use Todaymade\Daux\Config as GlobalConfig;
use Todaymade\Daux\Console\RunAction;
use Todaymade\Daux\Daux;
use Todaymade\Daux\DauxHelper;
@ -17,18 +17,23 @@ use Todaymade\Daux\Tree\Raw;
class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
{
use RunAction;
use HTMLUtils;
/** @var Daux */
protected $daux;
/** @var Template */
protected $templateRenderer;
protected $indexed_pages = [];
/**
* @param Daux $daux
*/
public function __construct(Daux $daux)
{
$config = $daux->getConfig();
$this->daux = $daux;
$this->templateRenderer = new Template($config);
$config->templateRenderer = $this->templateRenderer;
}
/**
@ -37,71 +42,47 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
public function getContentTypes()
{
return [
'markdown' => new ContentType($this->daux->getParams()),
'markdown' => new ContentType($this->daux->getConfig()),
];
}
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');
$params = $this->daux->getParams();
$config = $this->daux->getConfig();
if (is_null($destination)) {
$destination = $this->daux->local_base . DIRECTORY_SEPARATOR . 'static';
$destination = $config->getLocalBase() . DIRECTORY_SEPARATOR . 'static';
}
$this->runAction(
'Copying Static assets ...',
$output,
$width,
function () use ($destination, $params) {
function () use ($destination, $config) {
$this->ensureEmptyDestination($destination);
$this->copyThemes($destination, $params->getThemesPath());
$this->copyThemes($destination, $config->getThemesPath());
}
);
$output->writeLn('Generating ...');
if (!array_key_exists('search', $params['html']) || !$params['html']['search']) {
$params['html']['search'] = $input->getOption('search');
}
$this->generateRecursive($this->daux->tree, $destination, $config, $output, $width, $config->getHTML()->hasSearch());
$this->generateRecursive($this->daux->tree, $destination, $params, $output, $width, $params['html']['search']);
GeneratorHelper::copyRecursive(
$config->getLocalBase() . DIRECTORY_SEPARATOR . 'daux_libraries' . DIRECTORY_SEPARATOR,
$destination . DIRECTORY_SEPARATOR . 'daux_libraries'
);
if ($params['html']['search']) {
GeneratorHelper::copyRecursive(
$this->daux->local_base . DIRECTORY_SEPARATOR . 'tipuesearch' . DIRECTORY_SEPARATOR,
$destination . DIRECTORY_SEPARATOR . 'tipuesearch'
);
if ($config->getHTML()->hasSearch()) {
file_put_contents(
$destination . DIRECTORY_SEPARATOR . 'tipuesearch' . DIRECTORY_SEPARATOR . 'tipuesearch_content.json',
json_encode(['pages' => $this->indexed_pages])
$destination . DIRECTORY_SEPARATOR . 'daux_search_index.js',
'load_search_index(' . json_encode(['pages' => $this->indexed_pages]) . ');'
);
if (json_last_error()) {
echo "Could not write search index: \n" . json_last_error_msg() . "\n";
}
}
}
@ -110,12 +91,13 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
* script code, and embedded objects. Add line breaks around
* block-level tags to prevent word joining after tag removal.
* Also collapse whitespace to single space and trim result.
* modified from: http://nadeausoftware.com/articles/2007/09/php_tip_how_strip_html_tags_web_page
* modified from: http://nadeausoftware.com/articles/2007/09/php_tip_how_strip_html_tags_web_page.
*
* @param string $text
*
* @return string
*/
private function strip_html_tags($text)
private function sanitize($text)
{
$text = preg_replace(
[
@ -146,43 +128,45 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
$text
);
return trim(preg_replace('/\s+/', ' ', strip_tags($text)));
$text = trim(preg_replace('/\s+/', ' ', strip_tags($text)));
// Sometimes strings are detected as invalid UTF-8 and json_encode can't treat them
// iconv can fix those strings
return iconv('UTF-8', 'UTF-8//IGNORE', $text);
}
/**
* Recursively generate the documentation
* Recursively generate the documentation.
*
* @param Directory $tree
* @param string $output_dir
* @param \Todaymade\Daux\Config $params
* @param OutputInterface $output
* @param int $width
* @param bool $index_pages
* @param string $base_url
*
* @throws \Exception
*/
private function generateRecursive(Directory $tree, $output_dir, $params, $output, $width, $index_pages, $base_url = '')
private function generateRecursive(Directory $tree, $output_dir, GlobalConfig $config, $output, $width, $index_pages, $base_url = '')
{
DauxHelper::rebaseConfiguration($params, $base_url);
DauxHelper::rebaseConfiguration($config, $base_url);
if ($base_url !== '' && empty($params['entry_page'])) {
$params['entry_page'] = $tree->getFirstPage();
if ($base_url !== '' && !$config->hasEntryPage()) {
$config->setEntryPage($tree->getFirstPage());
}
foreach ($tree->getEntries() as $key => $node) {
if ($node instanceof Directory) {
$new_output_dir = $output_dir . DIRECTORY_SEPARATOR . $key;
mkdir($new_output_dir);
$this->generateRecursive($node, $new_output_dir, $params, $output, $width, $index_pages, '../' . $base_url);
$this->generateRecursive($node, $new_output_dir, $config, $output, $width, $index_pages, '../' . $base_url);
// Rebase configuration again as $params is a shared object
DauxHelper::rebaseConfiguration($params, $base_url);
// Rebase configuration again as $config is a shared object
DauxHelper::rebaseConfiguration($config, $base_url);
} else {
$this->runAction(
'- ' . $node->getUrl(),
$output,
$width,
function () use ($node, $output_dir, $key, $params, $index_pages) {
function () use ($node, $output_dir, $key, $config, $index_pages) {
if ($node instanceof Raw) {
copy($node->getPath(), $output_dir . DIRECTORY_SEPARATOR . $key);
@ -191,13 +175,13 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
$this->daux->tree->setActiveNode($node);
$generated = $this->generateOne($node, $params);
$generated = $this->generateOne($node, $config);
file_put_contents($output_dir . DIRECTORY_SEPARATOR . $key, $generated->getContent());
if ($index_pages) {
$this->indexed_pages[] = [
'title' => $node->getTitle(),
'text' => utf8_encode($this->strip_html_tags($generated->getPureContent())),
'tags' => '',
'text' => $this->sanitize($generated->getPureContent()),
'tags' => '',
'url' => $node->getUrl(),
];
}
@ -208,11 +192,9 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
}
/**
* @param Entry $node
* @param Config $params
* @return \Todaymade\Daux\Format\Base\Page
*/
public function generateOne(Entry $node, Config $params)
public function generateOne(Entry $node, GlobalConfig $config)
{
if ($node instanceof Raw) {
return new RawPage($node->getPath());
@ -222,8 +204,11 @@ class Generator implements \Todaymade\Daux\Format\Base\Generator, LiveGenerator
return new ComputedRawPage($node);
}
$params['request'] = $node->getUrl();
$config->setRequest($node->getUrl());
return ContentPage::fromFile($node, $params, $this->daux->getContentTypeHandler()->getType($node));
$contentPage = ContentPage::fromFile($node, $config, $this->daux->getContentTypeHandler()->getType($node));
$contentPage->templateRenderer = $this->templateRenderer;
return $contentPage;
}
}

Datei anzeigen

@ -0,0 +1,30 @@
<?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'
);
}
}

Datei anzeigen

@ -1,6 +1,10 @@
<?php namespace Todaymade\Daux\Format\HTML;
<?php
namespace Todaymade\Daux\Format\HTML;
use League\Plates\Engine;
use Symfony\Component\Console\Output\OutputInterface;
use Todaymade\Daux\Config as GlobalConfig;
use Todaymade\Daux\Daux;
use Todaymade\Daux\Tree\Content;
use Todaymade\Daux\Tree\Directory;
@ -9,20 +13,30 @@ class Template
{
protected $engine;
protected $config;
/**
* @param string $base
* @param string $theme
*/
public function __construct($base, $theme)
public function __construct(GlobalConfig $config)
{
// Use internal templates or the ones in the phar
// archive if no templates dir exists in the working directory
$this->config = $config;
}
public function getEngine(GlobalConfig $config)
{
if ($this->engine) {
return $this->engine;
}
$base = $config->getTemplates();
$theme = $config->getTheme()->getTemplates();
// Use internal templates if no templates
// dir exists in the working directory
if (!is_dir($base)) {
if (is_dir(__DIR__ . '/../../../templates')) {
$base = __DIR__ . '/../../../templates';
} else {
$base = 'phar://daux.phar/templates';
}
$base = __DIR__ . '/../../../templates';
}
// Create new Plates instance
@ -32,41 +46,71 @@ class Template
}
$this->engine->addFolder('theme', $theme, true);
$this->registerFunctions();
Daux::writeln("Starting Template engine with basedir '$base' and theme folder '$theme'.", OutputInterface::VERBOSITY_VERBOSE);
$this->registerFunctions($this->engine);
return $this->engine;
}
/**
* @param string $name
* @param array $data
*
* @return string
*/
public function render($name, array $data = [])
{
$this->engine->addData([
'base_url' => $data['params']['base_url'],
'base_page' => $data['params']['base_page'],
$engine = $this->getEngine($data['config']);
$engine->addData([
'base_url' => $data['config']->getBaseUrl(),
'base_page' => $data['config']->getBasePage(),
'page' => $data['page'],
'params' => $data['params'],
'tree' => $data['params']['tree'],
'params' => $data['config'], // legacy name for config
'config' => $data['config'],
'tree' => $data['config']['tree'],
]);
return $this->engine->render($name, $data);
Daux::writeln("Rendering template '$name'", OutputInterface::VERBOSITY_VERBOSE);
return $engine->render($name, $data);
}
protected function registerFunctions()
protected function registerFunctions($engine)
{
$this->engine->registerFunction('get_navigation', function ($tree, $path, $current_url, $base_page, $mode) {
$engine->registerFunction('get_navigation', function ($tree, $path, $current_url, $base_page, $mode) {
$nav = $this->buildNavigation($tree, $path, $current_url, $base_page, $mode);
return $this->renderNavigation($nav);
});
$this->engine->registerFunction('get_breadcrumb_title', function ($page, $base_page) {
$engine->registerFunction('translate', function ($key) {
$language = $this->config->getLanguage();
if (isset($this->engine->getData('page')['page'])) {
$page = $this->engine->getData('page');
if (!empty($page['page']['language'])) {
$language = $page['page']['language'];
}
}
if ($this->config->hasTranslationKey($language, $key)) {
return $this->config->getTranslationKey($language, $key);
}
if ($this->config->hasTranslationKey('en', $key)) {
return $this->config->getTranslationKey('en', $key);
}
return "Unknown key $key";
});
$engine->registerFunction('get_breadcrumb_title', function ($page, $base_page) {
$title = '';
$breadcrumb_trail = $page['breadcrumb_trail'];
$separator = $this->getSeparator($page['breadcrumb_separator']);
foreach ($breadcrumb_trail as $key => $value) {
$title .= '<a href="' . $base_page . $value . '">' . $key . '</a>' . $separator;
foreach ($breadcrumb_trail as $value) {
$title .= '<a href="' . $base_page . $value['url'] . '">' . $value['title'] . '</a>' . $separator;
}
if ($page['filename'] === 'index' || $page['filename'] === '_index') {
if ($page['title'] != '') {
@ -88,9 +132,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']);
@ -152,6 +196,7 @@ class Template
/**
* @param string $separator
*
* @return string
*/
private function getSeparator($separator)

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen