1
0
mirror of https://github.com/lrsjng/h5ai.git synced 2025-08-29 08:40:34 +02:00

Compare commits

..

169 Commits

Author SHA1 Message Date
Lars Jung
427ca82722 Maintenance. 2019-03-22 02:33:58 +01:00
Lars Jung
c521ecd055 Update deps. 2019-02-20 22:06:03 +01:00
Lars Jung
44e53ab213 Dev options. 2016-08-13 20:24:54 +02:00
Lars Jung
5af71185ff Release v0.29.0. 2016-08-12 14:57:36 +02:00
Lars Jung
d714ea90fb Prepare release. 2016-08-12 14:49:20 +02:00
Lars Jung
1e12faa756 Clean PHP. 2016-08-12 14:35:34 +02:00
Lars Jung
85ddff9c2d Turn onReady/Load into promised code. 2016-08-12 12:28:56 +02:00
Lars Jung
00232389ad Update changelog. 2016-08-11 19:51:55 +02:00
Lars Jung
e10fe49cc0 Add chunksize to thumbnail requests. 2016-08-11 19:50:28 +02:00
Lars Jung
6c52ae659f Update deps. 2016-08-11 17:31:42 +02:00
Lars Jung
3c54c1d66c Add space. 2016-08-11 16:43:06 +02:00
Lars Jung
940608d02a Fix selector field. 2016-08-11 00:53:43 +02:00
Lars Jung
b6b8d9f144 Clean some PHP code. 2016-08-11 00:33:06 +02:00
Lars Jung
c559edc208 Update changelog. 2016-08-10 23:59:27 +02:00
Lars Jung
4a41994556 Update changelog. 2016-08-10 23:49:41 +02:00
Lars Jung
d763d6b20a Fix safari language selection. 2016-08-10 16:35:57 +02:00
Lars Jung
dc2a74d251 Fix xhr check for safari. 2016-08-10 15:58:05 +02:00
Lars Jung
fe5ce111af Clean fallback mode topbar style. 2016-08-10 15:54:03 +02:00
Lars Jung
a930f4ce1b Clean info page styles. 2016-08-10 00:43:18 +02:00
Lars Jung
dae89ba5d8 Fix emtpy selection issues. 2016-08-10 00:20:40 +02:00
Lars Jung
78df81266c Another fix for download-all. 2016-08-09 23:26:16 +02:00
Lars Jung
b261c7e937 Docs. 2016-08-09 23:06:12 +02:00
Lars Jung
f9a7a217f8 Dereference sym links when using du. 2016-08-09 22:46:28 +02:00
Lars Jung
4d96cb47ad Fix drag-select on scrollable content. 2016-08-09 22:28:01 +02:00
Lars Jung
0f4fe15195 Fix always visible download button. 2016-08-09 19:27:43 +02:00
Lars Jung
d20d1e8b2c Lighter sidebars. 2016-08-09 03:06:50 +02:00
Lars Jung
4130f7a6fd Center icon labels. 2016-08-09 02:49:51 +02:00
Lars Jung
4ccd4bb030 Back to a cleaner GUI. 2016-08-07 18:15:22 +02:00
Lars Jung
16926f821d Update deps. 2016-08-03 11:52:45 +02:00
Lars Jung
7b5599e9d1 Merge pull request #561 from edmundlaugasson/master
added Estonian translation
2016-08-03 11:42:54 +02:00
Lars Jung
834f3b5425 Clean some tests. 2016-08-03 11:40:53 +02:00
Lars Jung
f0bee58869 Update piwik-analytics code. 2016-08-03 10:28:17 +02:00
edmundlaugasson
03e89dab5e added Estonian translation 2016-08-03 09:38:24 +03:00
Lars Jung
b7f25c45f2 Add unload funcs to audio and video previews. 2016-08-01 14:34:52 +02:00
Lars Jung
e5966bc610 Merge pull request #557 from Sirgue/patch-1
Update fr.json
2016-08-01 13:42:30 +02:00
Sirgue
78bc1e2a1e Update fr.json
Some translates for french language
2016-07-28 05:01:53 +02:00
Lars Jung
0315e29b44 Update deps. 2016-07-26 00:10:00 +02:00
Lars Jung
152dcb9b46 Revert. 2016-07-25 21:38:44 +02:00
Lars Jung
3a87b594a6 Update deps. 2016-07-25 20:15:35 +02:00
Lars Jung
631a0f7aa3 Merge pull request #556 from unix4you2/patch-2
Update es.json
2016-07-25 02:46:51 +02:00
Lars Jung
5564559b7c Merge pull request #555 from unix4you2/patch-1
Update es.json
2016-07-25 02:46:19 +02:00
Lars Jung
0e0f06d634 Add some tests. 2016-07-24 01:23:10 +02:00
Lars Jung
e52b3dd440 Width hack. 2016-07-23 22:30:26 +02:00
Lars Jung
c486962ff8 Minor. 2016-07-23 11:18:18 +02:00
Lars Jung
3fe1b2d6f8 Add tests. 2016-07-23 03:03:35 +02:00
Lars Jung
691cbce10f Replace regularCmp with cmp. 2016-07-23 02:36:16 +02:00
Lars Jung
4ccab28253 Update preview code. 2016-07-23 02:15:59 +02:00
Lars Jung
a6994150ca Add jsdom for headless testing. 2016-07-22 21:19:10 +02:00
Lars Jung
1d4b4b8a02 Update dom. 2016-07-22 20:15:14 +02:00
Lars Jung
20e080751d Update preview code. 2016-07-22 19:43:44 +02:00
Lars Jung
8a4ccd098c Clean preview code. 2016-07-22 03:59:50 +02:00
Lars Jung
9e0b1698fc Replace prism with lolight. 2016-07-21 16:31:14 +02:00
Lars Jung
18dfa1e09f Move some deps to package.json. 2016-07-21 14:26:48 +02:00
Lars Jung
83aad78ab0 Fix preview. 2016-07-21 13:48:54 +02:00
Lars Jung
9b88cdeb9b Update deps. 2016-07-21 13:44:31 +02:00
John Arroyave
11030a17af Update es.json 2016-07-11 08:02:25 -05:00
John Arroyave
aa7df50402 Update es.json 2016-07-11 07:44:35 -05:00
Lars Jung
2008d0755c Clean code. 2016-07-06 16:15:13 +02:00
Lars Jung
c7fdfc27a1 Update normalize to 4.2.0. 2016-07-02 15:11:11 +02:00
Lars Jung
717e046bb9 Update deps. 2016-07-02 13:41:01 +02:00
Lars Jung
5bbc88b8e2 Update tests. 2016-07-02 02:40:34 +02:00
Lars Jung
babb952485 Remove peer5 options. 2016-07-02 01:39:27 +02:00
Lars Jung
22b2db8daf Clean some code. 2016-07-02 00:38:52 +02:00
Lars Jung
8485905901 Clean sort code. 2016-07-01 19:26:17 +02:00
Lars Jung
73e74bb887 Update eslintrc. 2016-07-01 15:00:39 +02:00
Lars Jung
a893cb7534 Update readme. 2016-07-01 14:48:41 +02:00
Lars Jung
87e5472d42 Minor. 2016-07-01 14:44:51 +02:00
Lars Jung
05194167e1 Update prism. 2016-07-01 14:38:23 +02:00
Lars Jung
6dbffb8be1 Minor. 2016-07-01 03:55:27 +02:00
Lars Jung
24945faded Remove last jQuery refs and jQuery itself. 2016-07-01 03:27:38 +02:00
Lars Jung
3761a40e50 Clean code. 2016-06-30 02:19:49 +02:00
Lars Jung
f547d95f30 Minor. 2016-06-29 22:06:43 +02:00
Lars Jung
4a3e8c6734 Minor. 2016-06-29 19:03:54 +02:00
Lars Jung
07ccdbd734 Remove peer5. 2016-06-29 17:42:01 +02:00
Lars Jung
47b46813db Clean select code. 2016-06-29 16:59:39 +02:00
Lars Jung
82c0ae88f8 Clean select code. 2016-06-29 16:57:32 +02:00
Lars Jung
749c8b29c9 Clean select code. 2016-06-29 01:55:28 +02:00
Lars Jung
d0b6197aec Clean custom code. 2016-06-28 21:34:55 +02:00
Lars Jung
3b8edf9ad8 Clean tree code. 2016-06-28 19:44:52 +02:00
Lars Jung
9c4f3111ba Remove jq from tree. 2016-06-28 03:01:07 +02:00
Lars Jung
901d8c407d Bundle utils. 2016-06-26 17:57:25 +02:00
Lars Jung
6b3ba18da1 Update dom. 2016-06-26 17:07:43 +02:00
Lars Jung
cfbae4c5d5 Update. 2016-06-26 14:08:18 +02:00
Lars Jung
7320592dc2 Start to replace jQuery with dom. 2016-06-26 01:03:24 +02:00
Lars Jung
9234e3f287 Clean code. 2016-06-25 00:39:57 +02:00
Lars Jung
95c473a7c7 Clean code. 2016-06-24 23:06:00 +02:00
Lars Jung
3e14d7bed4 Clean code. 2016-06-24 21:26:59 +02:00
Lars Jung
aebfdeb1cd Remove all lodash deps. 2016-06-24 20:31:40 +02:00
Lars Jung
131d153cf5 More changes from jq.data to pure props. 2016-06-24 19:37:57 +02:00
Lars Jung
a3c9bc9db0 Initial switch from jq.data to pure props. 2016-06-24 18:59:16 +02:00
Lars Jung
06b4d81a61 Clean code. 2016-06-24 18:18:44 +02:00
Lars Jung
d8d7b997b5 Remove some more lodash refs. 2016-06-24 16:59:31 +02:00
Lars Jung
26c4d569aa Merge pull request #544 from PeterDaveHelloKitchen/image-optimize
optimize png images losslessly using zopflipng
2016-06-24 13:19:04 +02:00
Lars Jung
67d9e9794b Merge pull request #542 from kuoruan/translate
Update Chinese Translate
2016-06-24 13:15:23 +02:00
Lars Jung
0b8d7e5343 Minor. 2016-06-24 01:11:26 +02:00
Lars Jung
c3cd171785 Refactor. 2016-06-23 13:15:12 +02:00
Lars Jung
171f1c12eb Overlay sidebar. 2016-06-23 00:27:24 +02:00
Lars Jung
50644c84dc Overlay sidebar on small screens. 2016-06-23 00:19:23 +02:00
Lars Jung
92e8e34a66 Improve 64-bit hint. 2016-06-22 23:14:25 +02:00
Lars Jung
804df4c0fb Refactor PHP. 2016-06-22 22:07:57 +02:00
Lars Jung
41bb7d76b5 Refactor PHP. 2016-06-22 22:04:35 +02:00
Lars Jung
35df02984b Clean code. 2016-06-22 21:15:50 +02:00
Lars Jung
e0fc7043b5 Add PHP arch check. 2016-06-22 18:15:55 +02:00
Lars Jung
628836a201 PHP filesize. 2016-06-22 16:54:32 +02:00
Lars Jung
00f9ee09d3 Minor. 2016-06-22 11:36:36 +02:00
Lars Jung
029d4ed5af Minor. 2016-06-22 11:36:16 +02:00
Lars Jung
cd7c3c3dd4 Update editorconfig. 2016-06-21 03:25:20 +02:00
Lars Jung
d5c9668013 Update eslint. 2016-06-21 03:20:04 +02:00
Lars Jung
2fb7f9129e Add source check. 2016-06-21 03:16:35 +02:00
Lars Jung
f6150c58f4 Clean code. 2016-06-20 01:37:18 +02:00
Lars Jung
3246525d78 Remove some lodash deps. 2016-06-20 00:13:52 +02:00
Lars Jung
fe9cdbc46b Clean code. 2016-06-19 23:05:31 +02:00
Lars Jung
324fceb5c3 Move server to root dir. 2016-06-19 19:21:32 +02:00
Lars Jung
8656bdd74e Update styles. 2016-06-19 16:50:23 +02:00
Lars Jung
8ef9575e51 Replace jQuery.qrcode with kjua 0.1.1. 2016-06-19 14:47:39 +02:00
Lars Jung
1fc72d8473 Update ghu.js. 2016-06-19 14:08:26 +02:00
Lars Jung
2153056266 Rename global.js to pre.js. 2016-06-19 13:57:10 +02:00
Lars Jung
2240bd3ca1 Update deps. 2016-06-18 12:22:29 +02:00
Peter Dave Hello
127eaf9aac optimize png images losslessly using zopflipng 2016-06-11 10:21:37 +08:00
Lars Jung
7d5945d45b Minor changes. 2016-06-04 16:26:08 +02:00
Lars Jung
1d2c45dc68 Refactor view files. Add option to disable sidebar. 2016-06-04 16:09:35 +02:00
Lars Jung
2ee4a18e1c Clean build file. 2016-06-04 14:36:08 +02:00
Lars Jung
f0a9937dc6 Switch file names from jade to pug. 2016-06-04 02:43:48 +02:00
Lars Jung
3a2e61b163 Clean up tests. 2016-06-04 01:06:25 +02:00
Lars Jung
c4fa90a747 Add scar tests. 2016-06-03 23:08:30 +02:00
Lars Jung
1cba9290b6 Refactor win.js into globals.js. 2016-06-03 22:40:05 +02:00
Lars Jung
58cbad2bfd Disable filter. 2016-06-03 17:56:50 +02:00
Lars Jung
da9d027fed Remove custom modernizr. 2016-06-03 17:46:01 +02:00
Lars Jung
70d6528190 Test some module designs. 2016-06-03 17:38:00 +02:00
Lars Jung
f7187fb14b Stricter browser checks. Drop IE support. 2016-06-03 17:36:42 +02:00
Lars Jung
7ec2bdf16a Begin to move all src javascript to es6. Add search/filter ignore case option. 2016-06-02 23:16:23 +02:00
Hsing-Wang Liao
c7433b0d14 Update Traditional Chinese translation
Signed-off-by: Hsing-Wang Liao <kuoruan@gmail.com>
2016-06-01 14:20:47 +08:00
Hsing-Wang Liao
0179a5044b Update Simplified Chinese translation
Signed-off-by: Hsing-Wang Liao <kuoruan@gmail.com>
2016-06-01 14:08:08 +08:00
Lars Jung
f37e8e7b89 Update sinon to 1.17.3. 2016-05-31 02:00:19 +02:00
Lars Jung
ba670be7d8 Update ghu. Switch from jade to pug. 2016-05-31 01:21:44 +02:00
Lars Jung
93487de085 Remove sharpen arg from pdf convert. 2016-05-29 20:47:17 +02:00
Lars Jung
a2fb3d952d Replace getenv with SERVER lookups. 2016-05-29 19:05:50 +02:00
Lars Jung
fada3c1e36 Release custom head tags. 2016-05-29 18:21:32 +02:00
Lars Jung
aa87ec15b0 Add fallback mode. 2016-05-29 17:35:15 +02:00
Lars Jung
a0db0e0ac3 Update htaccess. 2016-05-29 14:52:39 +02:00
Lars Jung
a790c34a24 Readd some apache config. 2016-05-28 22:23:27 +02:00
Lars Jung
38daa4aa1f Update readme. 2016-05-28 21:34:23 +02:00
Lars Jung
c92822ba7d Update readme. 2016-05-28 19:58:17 +02:00
Lars Jung
18f2c72fd1 Change svg from text to image format. 2016-05-28 19:57:11 +02:00
Lars Jung
d03dc990fa Update readme and changelog. 2016-05-28 16:21:09 +02:00
Lars Jung
882abd1972 Merge pull request #510 from SushiDude/htaccess
Use mod_authz_core when available. Otherwise, fallback to mod_authz_host or mod_access_compat.
2016-05-28 00:04:37 +02:00
Lars Jung
2dd594ba13 Clean code. 2016-05-27 23:49:27 +02:00
Lars Jung
8d5473903e Merge pull request #534 from thezbyg/master
Fix incorrect tree item display.
2016-05-27 23:47:22 +02:00
Lars Jung
69c1ffd92f Fix and clean code from broken pull request. 2016-05-27 23:06:50 +02:00
Lars Jung
808e37d034 Merge pull request #526 from cygmris/master
Add commands support for Windows
2016-05-27 23:00:26 +02:00
Lars Jung
60ef5ff983 Merge pull request #492 from Joery/master
h5ai: fix typo & nl translation
2016-05-27 22:47:54 +02:00
Lars Jung
171539643e Merge pull request #537 from Monter/master
Update pl.json
2016-05-27 22:43:15 +02:00
Lars Jung
793bfce202 Minor change. 2016-05-27 22:42:11 +02:00
Lars Jung
10d6d2c3c1 Remove babel for now. 2016-05-27 20:35:43 +02:00
Lars Jung
51a161eede Minor tweaks. 2016-05-27 18:23:29 +02:00
Lars Jung
57b3ee6c2f Update deps: jquery, lodash, qrcode, modulejs. Minor fixes. 2016-05-27 17:56:32 +02:00
Lars Jung
641d9b3cfa Update deps. Fix lint issues. 2016-05-27 16:31:27 +02:00
Mark eM
5c2d84aaa9 Update pl.json 2016-05-22 20:25:50 +02:00
Albertas Vyšniauskas
8157ada8fc Fix incorrect tree item display.
Issues #533 and #499.
2016-05-17 17:04:24 +03:00
Lars Jung
8e143a4607 Update deps. 2016-05-16 16:10:37 +02:00
Lars Jung
e021862acf Minor tweaks. 2016-05-05 23:51:47 +02:00
Chr1sh3ng
ed9f04a372 Add commands support for Windows 2016-04-15 19:17:43 +08:00
Wyatt J. Brown
ca86993091 Use mod_authz_core when available. Otherwise, fallback to mod_authz_host or mod_access_compat.
https://github.com/lrsjng/h5ai/pull/489
https://github.com/lrsjng/h5ai/issues/504
2016-02-27 03:12:37 -05:00
Joery
85bd0abd8d Merge pull request #1 from lrsjng/master
h5ai: downstream 20160121
2016-01-21 10:09:53 +01:00
Lars Jung
ed1ab4053c Update apk icon. Add rust type and icon. 2016-01-19 01:18:08 +01:00
Lars Jung
6aed4455d3 Update deps. 2016-01-14 00:44:10 +01:00
Lars Jung
5f265672ae Remove blank lines from PHP sources. 2016-01-14 00:36:25 +01:00
Joery
1653306440 h5ai: update dutch translation 2015-12-25 22:03:03 +01:00
Joery
d0fe566f8f h5ai: fix typo 2015-12-25 22:02:30 +01:00
196 changed files with 11502 additions and 27139 deletions

View File

@@ -1,5 +0,0 @@
{
"presets": [
"es2015"
]
}

View File

@@ -12,11 +12,11 @@ insert_final_newline = true
trim_trailing_whitespace = true
[{package.json,.travis.yml,.eslintrc,.babelrc}]
[{package.json,.travis.yml,.eslintrc}]
indent_size = 2
[{*.md,*.jade}]
[{*.md,*.pug}]
trim_trailing_whitespace = false

View File

@@ -1,3 +1,3 @@
**/build/**
**/node_modules/**
**/vendor/**
/build/
/node_modules/
/**/vendor/

View File

@@ -1,36 +1,10 @@
---
root: true
parser: babel-eslint
env:
es6: true
node: true
ecmaFeatures:
arrowFunctions: true
binaryLiterals: true
blockBindings: true
classes: false
defaultParams: true
destructuring: true
forOf: true
generators: true
globalReturn: true
jsx: false
modules: true
objectLiteralComputedProperties: true
objectLiteralDuplicateProperties: true
objectLiteralShorthandMethods: true
objectLiteralShorthandProperties: true
octalLiterals: true
regexUFlag: true
regexYFlag: true
spread: true
superInFunctions: false
templateStrings: true
unicodeCodePointEscapes: true
rules:
array-bracket-spacing: [2, never]
arrow-parens: [2, as-needed]
@@ -41,7 +15,7 @@
comma-dangle: [2, never]
comma-spacing: [2, {before: false, after: true}]
comma-style: [2, last]
complexity: [1, 25] ###
complexity: [1, 10] ###
computed-property-spacing: [2, never]
consistent-return: 2
consistent-this: [2, self]
@@ -59,12 +33,13 @@
handle-callback-err: 2
indent: [2, 4]
key-spacing: [2, {beforeColon: false, afterColon: true}]
keyword-spacing: [2, {before: true, after: true}]
linebreak-style: [2, unix]
max-depth: [1, 4]
max-len: [0, 80, 4]
max-nested-callbacks: [1, 3]
max-params: [1, 5] ###
max-statements: [1, 80] ###
max-params: [1, 4] ###
max-statements: [1, 30] ###
new-cap: 0
new-parens: 2
newline-after-var: 0
@@ -90,7 +65,6 @@
no-else-return: 1
no-empty: 2
no-empty-character-class: 2
no-empty-label: 2
no-empty-pattern: 2
no-eq-null: 2
no-eval: 2
@@ -181,7 +155,7 @@
prefer-const: 1
prefer-reflect: 1
prefer-spread: 2
prefer-template: 0 ###
prefer-template: 0
quote-props: [2, as-needed]
quotes: [2, single, avoid-escape]
radix: 2
@@ -189,12 +163,10 @@
semi: 2
semi-spacing: [2, {before: false, after: true}]
sort-vars: 0
space-after-keywords: [2, always]
space-before-blocks: [2, always]
space-before-function-paren: [2, {anonymous: always, named: never}]
space-in-parens: [2, never]
space-infix-ops: 2
space-return-throw-case: 2
space-unary-ops: [2, {words: true, nonwords: false}]
spaced-comment: [2, always]
strict: [2, never]

8
.gitignore vendored
View File

@@ -1,4 +1,4 @@
build
local
node_modules
npm-debug.log
/build/
/local/
/node_modules/
/npm-debug.log

View File

@@ -1,141 +1,198 @@
# Changelog
## v0.29.2 - *2019-03-22*
* update `babel-loader` to 7.1.1
* update `eslint` to 5.15.3
* update `ghu` to 0.13.0
* update `jsdom` to 14.0.0
* update `kjua` to 0.2.0
* update `lolight` to 1.0.0
* update `scar` to 1.2.0
## v0.29.1 - *2019-01-20*
* replace `babel-preset-es2015` with `babel-preset-env`
* update `eslint` to 5.14.1
* update `ghu` to 0.12.0
* update `jsdom` to 9.2.0
* update `kjua` to 0.1.2
* update `lolight` to 0.6.0
* update `marked` to 0.6.1
* update `normalize.css` to 8.0.1
* update `scar` to 1.0.0
## v0.29.0 - *2016-08-12*
* back to cleaner visual experience
* add option to disable sidebar
* add options to filter/search ignore case
* replace PHP `getenv` calls with `$_SERVER` lookups
* add `view.fallbackMode` option to generally serve only fallback mode
* serve fallback mode for text browsers (`curl`, `links`, `lynx`, `w3m`)
* change type `txt-svg` to `img-svg`, no thumbs but preview
* fix a tree indentation glitch
* fix shell command detection on Windows
* fix Piwik anayltics
* fix `.htaccess` auth issues
* fix drag-select on scrollable content
* fix download-all function
* fix audio and video preview loading
* fix thumbnail request issues
* add `rust` type and icon
* add `autoplay` option to audio and video preview
* add `--dereference` to `shell-du` to follow sym links
* remove *Install* section from `README.md`, causes too much trouble
* remove peer5 support
* update build process to use `node 6.0+`, no need for babel now
* replace `jquery-qrcode` with [`kjua`](https://larsjung.de/kjua/)
* replace `prism` with [`lolight`](https://larsjung.de/lolight/)
* move deps to `package.json` (`normalize.css`, `kjua`, `lolight` and `marked`)
* remove `jQuery`
* remove `lodash`
* remove [`modulejs`](https://larsjung.de/modulejs/) for now
* reduce JS code by 60% (~250kb -> ~100kb)
* update languages (`et`, `nl`, `pl`)
## v0.28.0 - *2015-12-19*
* now requires PHP 5.5.0+
* changes index path to `/_h5ai/public/index.php`
* now only `/_h5ai/public/` needs to be accessable from web
* adds support for custom script and style additions
* adds options to set font families
* adds search
* adds ignorecase sorting option to tree
* adds wide links in tree view
* adds IE edge mode
* adds frontend tests
* fixes some styles in IE10
* fixes preview bottom bar for small screen widths
* now require PHP 5.5.0+
* change index path to `/_h5ai/public/index.php`
* now only `/_h5ai/public/` needs to be web-accessible
* add support for custom script and style additions
* add options to set font families
* add search
* add ignorecase sorting option to tree
* add wide links in tree view
* add IE edge mode
* add frontend tests
* fix some styles in IE10
* fix preview bottom bar for small screen widths
* lots of code cleanup and refactorings
* changes API
* updates build process, now uses [ghu](https://larsjung.de/ghu/)
* switches from jshint and jscs to [eslint](http://eslint.org/)
* updates `jQuery` to 2.1.4
* updates `lodash` to 3.9.3 (adds debounce and trim)
* updates `marked` to 0.3.5
* updates `modulejs` to 1.13.0
* updates `prism` to 2015-12-19
* updates h5bp styles to 5.2.0
* updates `normalize.css` to 3.0.3
* removes `Moment.js`
* change API
* update build process, now uses [`ghu`](https://larsjung.de/ghu/)
* switch from jshint and jscs to [`eslint`](http://eslint.org/)
* update `jQuery` to 2.1.4
* update `lodash` to 3.9.3 (add debounce and trim)
* update `marked` to 0.3.5
* update `modulejs` to 1.13.0
* update `prism` to 2015-12-19
* update h5bp styles to 5.2.0
* update `normalize.css` to 3.0.3
* remove `Moment.js`
## v0.27.0 - *2015-04-06*
* new layout
* adds editorconfig
* drops support for IE9 (gets fallback)
* updates sidebar settings
* adds info sidebar
* adds opt-out for click'n'drag selection
* adds package name option for single selections
* adds initial support for Peer5
* adds option to down-sample images for preview
* adds option for natural sorting in tree sidebar
* fixes problems with files/folders named `0`
* changes font from `Ubuntu` to `Roboto` (smaller footprint, clearer for small sizes)
* switches back to Google Fonts
* improves PDF thumbnail quality
* improves drag-select
* improves image preview
* prevents listing `_h5ai` folder and subfolders
* updates build process, now uses [mkr](https://larsjung.de/mkr/) and [fQuery](https://larsjung.de/fquery/)
* updates `jQuery` to 2.1.3
* updates `jQuery.qrcode` to 0.11.0
* updates `Lo-Dash` to 3.6.0
* updates `Modernizr` to 2.8.3
* updates `modulejs` to 1.4.0
* updates `Moment.js` to 2.9.0
* updates `Prism` to 2015-04-05
* removes deprecated Google Analytics code
* removes `jQuery.fracs`
* removes `jQuery.scrollpanel`
* removes `jQuery.mousewheel`
* language updates and additions (`af`, `es`, `ja`, `ko`, `ru`, `zh-cn`)
* add editorconfig
* drop support for IE9 (gets fallback)
* update sidebar settings
* add info sidebar
* add opt-out for click'n'drag selection
* add package name option for single selections
* add initial support for Peer5
* add option to down-sample images for preview
* add option for natural sorting in tree sidebar
* fix problems with files/folders named `0`
* change font from `Ubuntu` to `Roboto` (smaller footprint, clearer for small sizes)
* switch back to Google Fonts
* improve PDF thumbnail quality
* improve drag-select
* improve image preview
* prevent listing `_h5ai` folder and subfolders
* update build process, now uses [`mkr`](https://larsjung.de/mkr/) and [`fQuery`](https://larsjung.de/fquery/)
* update `jQuery` to 2.1.3
* update `jQuery.qrcode` to 0.11.0
* update `Lo-Dash` to 3.6.0
* update `Modernizr` to 2.8.3
* update `modulejs` to 1.4.0
* update `Moment.js` to 2.9.0
* update `Prism` to 2015-04-05
* remove deprecated Google Analytics code
* remove `jQuery.fracs`
* remove `jQuery.scrollpanel`
* remove `jQuery.mousewheel`
* update languages (`af`, `es`, `ja`, `ko`, `ru`, `zh-cn`)
## v0.26.1 - *2014-08-17*
* fixes links
* fix links
## v0.26.0 - *2014-08-16*
* removes True Type fonts
* outsources themes to [h5ai-themes](https://github.com/lrsjng/h5ai-themes)
* adds filesize fallback for large files and 32bit PHP
* fixes server detection
* adds config file tests to info page
* removes JSON shim
* adds caching of command checks
* updates `jQuery.mousewheel` to 3.1.12
* updates `jQuery.qrcode` to 0.8.0
* replaces `markdown` with [`marked`](https://github.com/chjj/marked) 0.3.2
* updates `modulejs` to 0.4.5
* updates `Moment.js` to 2.8.1
* replaces `underscore` with [`Lo-Dash`](https://github.com/lodash/lodash) 2.4.1
* replaces `SyntaxHighlighter` with [`Prism`](http://prismjs.com) 2014-08-04
* remove True Type fonts
* outsource themes to [h5ai-themes](https://github.com/lrsjng/h5ai-themes)
* add filesize fallback for large files and 32bit PHP
* fix server detection
* add config file tests to info page
* remove JSON shim
* add caching of command checks
* update `jQuery.mousewheel` to 3.1.12
* update `jQuery.qrcode` to 0.8.0
* replace `markdown` with [`marked`](https://github.com/chjj/marked) 0.3.2
* update `modulejs` to 0.4.5
* update `Moment.js` to 2.8.1
* replace `underscore` with [`Lo-Dash`](https://github.com/lodash/lodash) 2.4.1
* replace `SyntaxHighlighter` with [`Prism`](http://prismjs.com) 2014-08-04
## v0.25.2 - *2014-07-01*
* adds optional info page protection
* fixes `short_open_tag` issues for PHP < 5.4.0
* fixes default folder download (`alwaysVisible` option)
* add optional info page protection
* fix `short_open_tag` issues for PHP < 5.4.0
* fix default folder download (`alwaysVisible` option)
* minor fixes
## v0.25.1 - *2014-06-25*
* fixes broken paths for filenames containing '+' characters
* fixes Google Universal Analytics
* fixes file type check
* fix broken paths for filenames containing '+' characters
* fix Google Universal Analytics
* fix file type check
## v0.25.0 - *2014-06-22*
* adds sidebar
* adds initial theme support
* adds icons from [Evolvere Icon Theme](http://franksouza183.deviantart.com/art/Evolvere-Icon-theme-440718295)
* adds PHP variant to calc folder sizes
* adds scroll position reset on location change (issue [#279](https://github.com/lrsjng/h5ai/issues/279))
* adds option to hide unreadable files
* adds option where to place folders (top, inplace, bottom)
* adds markdown support for custom header and footer files
* adds video and audio preview via HTML5 elements (no fallback, works best in Chrome)
* adds filter reset on location change
* adds option to make download button always visible
* adds Google UA support
* extends selectable icon sizes (adds 128px, 192px, 256px, 384px)
* improves preview GUI
* add sidebar
* add initial theme support
* add icons from [Evolvere Icon Theme](http://franksouza183.deviantart.com/art/Evolvere-Icon-theme-440718295)
* add PHP variant to calc folder sizes
* add scroll position reset on location change (issue [#279](https://github.com/lrsjng/h5ai/issues/279))
* add option to hide unreadable files
* add option where to place folders (top, inplace, bottom)
* add markdown support for custom header and footer files
* add video and audio preview via HTML5 elements (no fallback, works best in Chrome)
* add filter reset on location change
* add option to make download button always visible
* add Google UA support
* extend selectable icon sizes (add 128px, 192px, 256px, 384px)
* improve preview GUI
* disable thumbs in `cache` folder
* fixes QR code URI origin (issue [#287](https://github.com/lrsjng/h5ai/issues/287))
* replaces PHP backtick operator with `exec`
* removes server side file manipulation extensions `dropbox`, `delete` and `rename`
* updates `H5BP` to 4.3.0
* updates `jQuery` to 2.1.1
* updates `json2.js` to 2014-02-04
* updates `markdown-js` to 0.5.0
* updates `Modernizr` to 2.8.2
* updates `Moment.js` to 2.6.0
* updates `Underscore.js` to 1.6.0
* language updates (`bg`, `ko`, `pt`, `sl`, `sv`, `zh-cn`)
* fix QR code URI origin (issue [#287](https://github.com/lrsjng/h5ai/issues/287))
* replace PHP backtick operator with `exec`
* remove server side file manipulation extensions `dropbox`, `delete` and `rename`
* update `H5BP` to 4.3.0
* update `jQuery` to 2.1.1
* update `json2.js` to 2014-02-04
* update `markdown-js` to 0.5.0
* update `Modernizr` to 2.8.2
* update `Moment.js` to 2.6.0
* update `Underscore.js` to 1.6.0
* update languages (`bg`, `ko`, `pt`, `sl`, `sv`, `zh-cn`)
## v0.24.1 - *2014-04-09*
* security fixes! (issues [#268](https://github.com/lrsjng/h5ai/issues/268), [#269](https://github.com/lrsjng/h5ai/issues/269))
* language updates (`fi`, `fr`, `hi`, `it`, `zh-tw`)
* fixes WinOS command detection
* fix WinOS command detection
* update languages (`fi`, `fr`, `hi`, `it`, `zh-tw`)
## v0.24.0 - *2013-09-04*

View File

@@ -3,22 +3,15 @@
[![license][license-img]][github] [![web][web-img]][web] [![github][github-img]][github]
A modern HTTP web server index for Apache httpd, lighttpd, nginx and Cherokee.
For bug reports and feature requests please use [issues][github-issues].
There was a [security flaw][cve] in versions 0.22.0 - 0.24.1 that was fixed in
0.25.0. If you are still using one of these versions you are advised to
upgrade.
## Install
## Important
Do **not** install any files from the `src` folder, they need to be
preprocessed to work correctly! Find a preprocessed package and detailed
install instructions on the [project page][web].
In short you have to take the following two steps:
* place folder `_h5ai` in the document root folder of the web server
* append `/_h5ai/public/index.php` to the end of the default index-file list
* Do **not** install any files from the `src` folder, they need to be
preprocessed to work correctly!
* Find a preprocessed package and detailed install instructions on the
[project page][web].
* For bug reports and feature requests please use [issues][github-issues].
## Build
@@ -27,7 +20,7 @@ There are installation ready packages for the latest [releases][release] and
[dev builds][develop]. But to build **h5ai** yourself either `git clone` or
download the repository. From within the root folder run the following
commands to find a fresh zipball in folder `build` (tested on linux only,
requires [`node 4.0+`][node] to be installed).
requires [`node 6.0+`][node] to be installed).
~~~sh
> npm install
@@ -39,7 +32,7 @@ requires [`node 4.0+`][node] to be installed).
The MIT License (MIT)
Copyright (c) 2015 Lars Jung (https://larsjung.de)
Copyright (c) 2019 Lars Jung (https://larsjung.de)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -77,5 +70,3 @@ too. Exceptions are some [Material Design icons][material-design-icons] (CC BY 4
[license-img]: https://img.shields.io/badge/license-MIT-a0a060.svg?style=flat-square
[web-img]: https://img.shields.io/badge/web-larsjung.de/h5ai-a0a060.svg?style=flat-square
[github-img]: https://img.shields.io/badge/github-lrsjng/h5ai-a0a060.svg?style=flat-square
[cve]: https://larsjung.de/h5ai/cve-2015-3203.txt

2
ghu
View File

@@ -1,2 +0,0 @@
#!/usr/bin/env sh
node -r babel-core/register ghu.js "$@"

80
ghu.js
View File

@@ -1,8 +1,7 @@
const {resolve, join} = require('path');
const {
ghu,
autoprefixer, cssmin, each, ife, includeit, jade, jszip,
less, mapfn, newerThan, read, remove, run, uglify, watch, wrap, write
ghu, autoprefixer, cssmin, each, ife, includeit, jszip, less, mapfn,
newerThan, pug, read, remove, run, uglify, watch, webpack, wrap, write
} = require('ghu');
const ROOT = resolve(__dirname);
@@ -10,7 +9,25 @@ const SRC = join(ROOT, 'src');
const TEST = join(ROOT, 'test');
const BUILD = join(ROOT, 'build');
const mapper = mapfn.p(SRC, BUILD).s('.less', '.css').s('.jade', '');
const mapper = mapfn.p(SRC, BUILD).s('.less', '.css').s('.pug', '');
const webpackCfg = include => ({
module: {
loaders: [
{
include,
loader: 'babel-loader',
query: {
cacheDirectory: true,
presets: ['babel-preset-env']
}
},
{
test: /jsdom/,
loader: 'null-loader'
}
]
}
});
ghu.defaults('release');
@@ -45,15 +62,13 @@ ghu.task('clean', 'delete build folder', () => {
return remove(BUILD);
});
ghu.task('lint', 'lint all JavaScript files with eslint', () => {
return run('eslint .', {stdio: 'inherit'});
});
ghu.task('build:scripts', runtime => {
return read(`${SRC}/_h5ai/public/js/*.js`)
return read(`${SRC}/_h5ai/public/js/scripts.js`)
.then(newerThan(mapper, `${SRC}/_h5ai/public/js/**`))
.then(webpack(webpackCfg([SRC]), {showStats: false}))
.then(wrap('\n\n// @include "pre.js"\n\n'))
.then(includeit())
.then(ife(() => runtime.args.production, uglify()))
.then(ife(() => runtime.args.production, uglify({compressor: {warnings: false}})))
.then(wrap(runtime.commentJs))
.then(write(mapper, {overwrite: true}));
});
@@ -70,9 +85,9 @@ ghu.task('build:styles', runtime => {
});
ghu.task('build:pages', runtime => {
return read(`${SRC}: **/*.jade, ! **/*.tpl.jade`)
.then(newerThan(mapper, `${SRC}/**/*.tpl.jade`))
.then(jade({pkg: runtime.pkg}))
return read(`${SRC}: **/*.pug, ! **/*.tpl.pug`)
.then(newerThan(mapper, `${SRC}/**/*.tpl.pug`))
.then(pug({pkg: runtime.pkg}))
.then(wrap('', runtime.commentHtml))
.then(write(mapper, {overwrite: true}));
});
@@ -86,10 +101,10 @@ ghu.task('build:copy', runtime => {
.then(wrap(runtime.commentJs))
.then(write(mapper, {overwrite: true, cluster: true})),
read(`${SRC}: **, ! **/*.js, ! **/*.less, ! **/*.jade, ! **/conf/*.json`)
read(`${SRC}: **, ! **/*.js, ! **/*.less, ! **/*.pug, ! **/conf/*.json`)
.then(newerThan(mapper))
.then(each(obj => {
if (/index\.php$/.test(obj.source)) {
if ((/index\.php$/).test(obj.source)) {
obj.content = obj.content.replace('{{VERSION}}', runtime.pkg.version);
}
}))
@@ -101,32 +116,21 @@ ghu.task('build:copy', runtime => {
]);
});
ghu.task('build:tests', ['build:scripts', 'build:styles'], 'build the test suite', runtime => {
ghu.task('build:tests', ['build:styles'], 'build the test suite', () => {
return Promise.all([
read(`${TEST}/scripts.js`)
.then(newerThan(`${BUILD}/test/scripts.js`))
.then(includeit())
.then(write(`${BUILD}/test/scripts.js`, {overwrite: true})),
read(`${TEST}/styles.less`)
.then(newerThan(`${BUILD}/test/styles.css`))
.then(includeit())
.then(less())
.then(autoprefixer())
.then(write(`${BUILD}/test/styles.css`, {overwrite: true})),
read(`${TEST}/index.html.jade`)
.then(newerThan(`${BUILD}/test/index.html`))
.then(jade({pkg: runtime.pkg}))
.then(write(`${BUILD}/test/index.html`, {overwrite: true})),
read(`${BUILD}/_h5ai/public/js/scripts.js`)
.then(newerThan(`${BUILD}/test/h5ai-scripts.js`))
.then(write(`${BUILD}/test/h5ai-scripts.js`, {overwrite: true})),
read(`${BUILD}/_h5ai/public/css/styles.css`)
.then(newerThan(`${BUILD}/test/h5ai-styles.css`))
.then(write(`${BUILD}/test/h5ai-styles.css`, {overwrite: true}))
.then(write(`${BUILD}/test/h5ai-styles.css`, {overwrite: true})),
read(`${TEST}/index.html`)
.then(newerThan(`${BUILD}/test/index.html`))
.then(write(`${BUILD}/test/index.html`, {overwrite: true})),
read(`${TEST}: index.js`)
.then(webpack(webpackCfg([SRC, TEST]), {showStats: false}))
.then(wrap(`\n\n// @include "${SRC}/**/js/pre.js"\n\n`))
.then(includeit())
.then(write(mapfn.p(TEST, `${BUILD}/test`), {overwrite: true}))
]).then(() => {
console.log(`browse to file://${BUILD}/test/index.html to run the test suite`);
});

6930
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "h5ai",
"version": "0.28.1",
"version": "0.29.2",
"description": "Modern HTTP web server index.",
"homepage": "https://larsjung.de/h5ai/",
"bugs": "https://github.com/lrsjng/h5ai/issues",
@@ -12,17 +12,24 @@
},
"scripts": {
"lint": "eslint .",
"ghu": "node -r babel-core/register ghu.js",
"build": "npm run -s ghu release"
"test": "node test",
"build": "node ghu release",
"precommit": "npm run lint && npm run test"
},
"devDependencies": {
"babel-core": "6.3.21",
"babel-eslint": "5.0.0-beta6",
"babel-preset-es2015": "6.3.13",
"eslint": "1.10.3",
"ghu": "0.4.0"
"babel-loader": "7.1.1",
"babel-preset-env": "1.7.0",
"eslint": "5.15.3",
"ghu": "0.13.0",
"jsdom": "14.0.0",
"kjua": "0.2.0",
"lolight": "1.0.0",
"marked": "0.6.1",
"normalize.css": "8.0.1",
"null-loader": "0.1.1",
"scar": "1.2.0"
},
"engines": {
"node": ">=4.0.0"
"node": ">=10.0.0"
}
}

View File

@@ -1,43 +1,4 @@
---
env:
es6: false
node: false
browser: true
mocha: false
globals:
modulejs: false
ecmaFeatures:
arrowFunctions: false
binaryLiterals: false
blockBindings: false
classes: false
defaultParams: false
destructuring: false
forOf: false
generators: false
globalReturn: false
jsx: false
modules: false
objectLiteralComputedProperties: false
objectLiteralDuplicateProperties: false
objectLiteralShorthandMethods: false
objectLiteralShorthandProperties: false
octalLiterals: false
regexUFlag: false
regexYFlag: false
spread: false
superInFunctions: false
templateStrings: false
unicodeCodePointEscapes: false
rules:
consistent-this: 0
func-names: 0
max-params: [1, 10]
no-invalid-this: 0
no-var: 0
object-shorthand: 0
prefer-arrow-callback: 0
no-console: 1
prefer-reflect: 0

View File

@@ -1,3 +1,165 @@
Satisfy all
Order deny,allow
## details here: https://github.com/h5bp/server-configs-apache
## SECURITY ###################################################################
DirectoryIndex disabled
FileETag None
ServerSignature Off
# Apache < 2.3
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
Satisfy All
</IfModule>
# Apache ≥ 2.3
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header unset ETag
Header unset X-Powered-By
</IfModule>
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
## COMPAT #####################################################################
AddDefaultCharset utf-8
<IfModule mod_mime.c>
AddCharset utf-8 .css .html .js .json .php .svg
AddType application/font-woff woff
AddType application/font-woff2 woff2
AddType application/json json
AddType application/javascript js
AddType application/vnd.ms-fontobject eot
AddType application/x-font-ttf ttc ttf
AddType image/jpeg jpeg jpg
AddType image/png png
AddType image/svg+xml svg svgz
AddType image/x-icon ico
AddType font/opentype otf
AddType text/css css
AddType text/html html
</IfModule>
## SPEED ######################################################################
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType text/html "access plus 1 minute"
ExpiresByType image/x-icon "access plus 1 week"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
</IfModule>
<IfModule mod_deflate.c>
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# Apache ≥ 2.3
<IfModule mod_authz_core.c>
# mod_filter as module only available for Apache ≥ 2.3.7
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
</IfModule>
# Apache < 2.3
<IfModule !mod_authz_core.c>
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
</IfModule>
<IfModule mod_mime.c>
AddEncoding gzip gz
AddEncoding gzip svgz
</IfModule>
</IfModule>

View File

@@ -1,3 +0,0 @@
Satisfy all
Order deny,allow
Deny from all

View File

@@ -6,13 +6,17 @@
"download": "Descargar",
"empty": "vacío",
"files": "Archivos",
"filter": "Filtar",
"filter": "Filtrar",
"folders": "Directorios",
"grid": "Cuadrícula",
"icons": "Íconos",
"language": "Idioma",
"lastModified": "Última modificación",
"name": "Nombre",
"noMatch": "Sin coincidencias",
"parentDirectory": "Directorio superior",
"size": "Tamaño"
"search": "buscar",
"size": "Tamaño",
"tree": "Arbol",
"view": "Vista"
}

View File

@@ -0,0 +1,22 @@
{
"lang": "estonian",
"dateFormat": "DD-MM-YYYY HH.mm",
"details": "täpsem info",
"download": "laadi alla",
"empty": "tühi",
"files": "failid",
"filter": "filter",
"folders": "kataloogid",
"grid": "võre",
"icons": "ikoonid",
"language": "Keel",
"lastModified": "Viimati muudetud",
"name": "Nimi",
"noMatch": "ei leitud sobivat",
"parentDirectory": "Emakataloog",
"search": "otsi",
"size": "Suurus",
"tree": "Puu",
"view": "Vaade"
}

View File

@@ -6,13 +6,17 @@
"download": "télécharger",
"empty": "vide",
"files": "Fichiers",
"filter": "filtre",
"filter": "filtrer",
"folders": "Répertoires",
"grid": "grille",
"icons": "icônes",
"language": "Langue",
"lastModified": "Dernière modification",
"name": "Nom",
"noMatch": "rien trouvé",
"parentDirectory": "Dossier parent",
"size": "Taille"
"search": "rechercher",
"size": "Taille",
"tree": "Arborescence",
"view": "Disposition"
}

View File

@@ -1,11 +1,22 @@
{
"lang": "nederlands",
"dateFormat": "YYYY-MM-DD HH:mm",
"details": "details",
"empty": "lege",
"download": "download",
"empty": "leeg",
"files": "bestanden",
"filter": "filter",
"folders": "mappen",
"grid": "grid",
"icons": "iconen",
"language": "Taal",
"lastModified": "Laatste wijziging",
"name": "Naam",
"noMatch": "geen overeenkomst",
"parentDirectory": "Bovenliggende map",
"size": "Grootte"
"search": "zoeken",
"size": "Grootte",
"tree": "Boom",
"view": "Bekijk"
}

View File

@@ -10,9 +10,13 @@
"folders": "folderów",
"grid": "kafelki",
"icons": "ikony",
"language": "Język",
"lastModified": "Ostatnia modyfikacja",
"name": "Nazwa",
"noMatch": "nie znaleziono",
"parentDirectory": "Katalog nadrzędny",
"size": "Rozmiar"
"search": "szukaj",
"size": "Rozmiar",
"tree": "Drzewo",
"view": "Układ"
}

View File

@@ -6,7 +6,7 @@
"download": "下载",
"empty": "空文件夹",
"files": "文件",
"filter": "查找",
"filter": "过滤",
"folders": "文件夹",
"grid": "网格",
"icons": "图标",
@@ -15,6 +15,9 @@
"name": "文件名",
"noMatch": "无匹配项",
"parentDirectory": "父文件夹",
"search": "搜索",
"size": "大小",
"view": "视图"
"tree": "树形目录",
"view": "视图",
"info": "信息"
}

View File

@@ -10,9 +10,14 @@
"folders": "資料夾",
"grid": "網格",
"icons": "圖示",
"language": "語言",
"lastModified": "上次修改",
"name": "檔名",
"noMatch": "沒有符合的檔案",
"parentDirectory": "上層目錄",
"size": "大小"
"search": "搜尋",
"size": "大小",
"tree": "樹形目錄",
"view": "檢視",
"info": "資訊"
}

View File

@@ -32,6 +32,8 @@
General view options.
- binaryPrefix: boolean, set to true uses 1024B=1KiB when formatting file sizes (see http://en.wikipedia.org/wiki/Binary_prefix)
- disableSidebar: boolean, hides sidebar and toggle button
- fallbackMode: boolean, serve fallback mode
- fastBrowsing: boolean, use History API if available (no need to reload the whole page)
- fonts: array of strings, fonts to use in regular context
- fontsMono: array of strings, fonts to use in monopspaced context
@@ -58,6 +60,8 @@
*/
"view": {
"binaryPrefix": false,
"disableSidebar": false,
"fallbackMode": false,
"fastBrowsing": true,
"fonts": ["Ubuntu", "Roboto", "Helvetica", "Arial", "sans-serif"],
"fontsMono": ["Ubuntu Mono", "Monaco", "Lucida Sans Typewriter", "monospace"],
@@ -89,13 +93,6 @@
"interval": 5000
},
/*
Enable a context menu (right-click) on some elements.
*/
"contextmenu": {
"enabled": false
},
/*
Show a clickable breadcrumb.
*/
@@ -142,11 +139,13 @@
- advanced: boolean, use advanced pattern parsing
- debounceTime: number, debounce wait time in milliseconds
- ignorecase: boolean, ignore case
*/
"filter": {
"enabled": false,
"advanced": true,
"debounceTime": 100
"debounceTime": 100,
"ignorecase": true
},
/*
@@ -158,7 +157,7 @@
- type: string, "php" (sloooow) or "shell-du" (sloow)
*/
"foldersize": {
"enabled": false,
"enabled": true,
"type": "php"
},
@@ -184,7 +183,8 @@
"enabled": true,
"show": false,
"qrcode": true,
"qrColor": "#999"
"qrFill": "#999",
"qrBack": "#fff"
},
/*
@@ -201,16 +201,6 @@
"useBrowserLang": true
},
/*
Adds peer5 p2p downloader which is based on webrtc (see peer5.com).
- id: string, the API key
*/
"peer5": {
"enabled": false,
"id": "z142i5n5qypq4cxr"
},
/*
Adds Piwik tracker javascript code.
@@ -226,10 +216,12 @@
/*
Play a audio preview on click.
- autoplay: start playing as soon as ready
- types: array of strings
*/
"preview-aud": {
"enabled": true,
"autoplay": true,
"types": ["aud"]
},
@@ -242,59 +234,59 @@
"preview-img": {
"enabled": true,
"size": false,
"types": ["img", "img-bmp", "img-gif", "img-ico", "img-jpg", "img-png", "img-raw"]
"types": ["img", "img-bmp", "img-gif", "img-ico", "img-jpg", "img-png", "img-raw", "img-svg"]
},
/*
Show text file preview on click.
"types" maps file types to http://prismjs.com languages.
Additional type are:
- "markdown" to render Markdown text
- "none" for floating text
- "fixed" for fixed width text
Available styles are:
0: floating text
1: fixed width text
2: markdown
3: syntax highlighting
- types: dict string to string, maps types to languages
- styles: dict string to int, maps types to styles
*/
"preview-txt": {
"enabled": true,
"types": {
"txt": "fixed",
"txt-authors": "fixed",
"txt-c": "c",
"txt-cpp": "cpp",
"txt-css": "css",
"txt-diff": "fixed",
"txt-go": "go",
"txt-h": "c",
"txt-hpp": "cpp",
"txt-install": "fixed",
"txt-java": "java",
"txt-js": "javascript",
"txt-json": "javascript",
"txt-less": "css",
"txt-license": "fixed",
"txt-log": "fixed",
"txt-makefile": "fixed",
"txt-md": "markdown",
// "txt-php": "php",
"txt-py": "python",
"txt-rb": "ruby",
"txt-readme": "fixed",
"txt-rtf": "fixed",
"txt-scala": "scala",
"txt-script": "bash",
"txt-xml": "fixed"
"styles": {
"txt": 1,
"txt-authors": 1,
"txt-c": 3,
"txt-cpp": 3,
"txt-css": 3,
"txt-diff": 1,
"txt-go": 3,
"txt-h": 3,
"txt-hpp": 3,
"txt-install": 1,
"txt-js": 3,
"txt-json": 3,
"txt-less": 3,
"txt-license": 1,
"txt-log": 1,
"txt-makefile": 1,
"txt-md": 2,
"txt-py": 3,
"txt-rb": 3,
"txt-readme": 1,
"txt-rtf": 1,
"txt-rust": 3,
"txt-script": 3,
"txt-xml": 1
}
},
/*
Play a video preview on click.
- autoplay: start playing as soon as ready
- types: array of strings
*/
"preview-vid": {
"enabled": true,
"autoplay": true,
"types": ["vid-avi", "vid-flv", "vid-mkv", "vid-mov", "vid-mp4", "vid-mpg", "vid-webm"]
},
@@ -309,11 +301,13 @@
- advanced: boolean, use advanced pattern parsing
- debounceTime: number, debounce wait time in milliseconds
- ignorecase: boolean, ignore case
*/
"search": {
"enabled": true,
"enabled": false,
"advanced": true,
"debounceTime": 300
"debounceTime": 300,
"ignorecase": true
},
/*
@@ -344,7 +338,7 @@
"column": 0,
"reverse": false,
"ignorecase": true,
"natural": false,
"natural": true,
"folders": 0
},
@@ -358,6 +352,7 @@
- delay: number, delay in milliseconds after "dom-ready" before thumb-requesting starts
- size: number, size in pixel of the generated thumbnails
- exif: boolean, use included EXIF thumbs if possible
- chunksize: int, number of thumbs per request
*/
"thumbnails": {
"enabled": true,
@@ -366,7 +361,8 @@
"doc": ["x-pdf", "x-ps"],
"delay": 1,
"size": 240,
"exif": false
"exif": false,
"chunksize": 20
},
/*
@@ -389,7 +385,7 @@
"enabled": true,
"show": true,
"maxSubfolders": 50,
"naturalSort": false,
"naturalSort": true,
"ignorecase": true
}
}

View File

@@ -18,6 +18,7 @@
"img-jpg": ["*.jpg", "*.jpeg"],
"img-png": ["*.png"],
"img-raw": ["*.cr2", "*.nef"],
"img-svg": ["*.svg"],
"img-tiff": ["*.tiff"],
"txt": ["*.text", "*.txt"],
"txt-build": ["*.pom", "build.xml", "pom.xml"],
@@ -41,9 +42,9 @@
"txt-rb": ["*.rb"],
"txt-rss": ["*.rss"],
"txt-rtf": ["*.rtf"],
"txt-rust": ["*.rs", "*.rlib"],
"txt-script": ["*.conf", "*.bsh", "*.csh", "*.ini", "*.ksh", "*.sh", "*.shar", "*.tcl", "*.zsh"],
"txt-source": [],
"txt-svg": ["*.svg"],
"txt-tex": ["*.tex"],
"txt-vcal": ["*.vcal"],
"txt-xml": ["*.xml"],

View File

@@ -1,11 +1,9 @@
<?php
class Bootstrap {
private static $autopaths = ['core', 'ext'];
public static function run() {
spl_autoload_register(['Bootstrap', 'autoload']);
putenv('LANG=en_US.UTF-8');
setlocale(LC_CTYPE, 'en_US.UTF-8');
@@ -13,7 +11,7 @@ class Bootstrap {
session_start();
$session = new Session($_SESSION);
$request = new Request($_REQUEST);
$request = new Request($_REQUEST, file_get_contents('php://input'));
$setup = new Setup($request->query_boolean('refresh', false));
$context = new Context($session, $request, $setup);
@@ -22,17 +20,18 @@ class Bootstrap {
} elseif ($context->is_info_request()) {
$public_href = $setup->get('PUBLIC_HREF');
$x_head_tags = $context->get_x_head_html();
$fallback_mode = false;
require __DIR__ . '/pages/info.php';
} else {
$public_href = $setup->get('PUBLIC_HREF');
$x_head_tags = $context->get_x_head_html();
$fallback_mode = $context->is_fallback_mode();
$fallback_html = (new Fallback($context))->get_html();
require __DIR__ . '/pages/index.php';
}
}
public static function autoload($class_name) {
$filename = 'class-' . strtolower($class_name) . '.php';
foreach (Bootstrap::$autopaths as $path) {

View File

@@ -1,20 +1,17 @@
<?php
class Api {
private $context;
private $request;
private $setup;
public function __construct($context) {
$this->context = $context;
$this->request = $context->get_request();
$this->setup = $context->get_setup();
}
public function apply() {
$action = $this->request->query('action');
$supported = ['download', 'get', 'login', 'logout'];
Util::json_fail(Util::ERR_UNSUPPORTED, 'unsupported action', !in_array($action, $supported));
@@ -24,13 +21,12 @@ class Api {
}
private function on_download() {
Util::json_fail(Util::ERR_DISABLED, 'download disabled', !$this->context->query_option('download.enabled', false));
$as = $this->request->query('as');
$type = $this->request->query('type');
$base_href = $this->request->query('baseHref');
$hrefs = $this->request->query('hrefs');
$hrefs = $this->request->query('hrefs', '');
$archive = new Archive($this->context);
@@ -45,70 +41,57 @@ class Api {
}
private function on_get() {
$response = [];
foreach (['langs', 'options', 'types'] as $name) {
if ($this->request->query_boolean($name, false)) {
$methodname = 'get_' . $name;
$response[$name] = $this->context->$methodname();
}
}
if ($this->request->query_boolean('setup', false)) {
$response['setup'] = $this->setup->to_jsono($this->context->is_admin());
}
if ($this->request->query_boolean('theme', false)) {
$theme = new Theme($this->context);
$response['theme'] = $theme->get_icons();
}
if ($this->request->query('items', false)) {
$href = $this->request->query('items.href');
$what = $this->request->query_numeric('items.what');
$response['items'] = $this->context->get_items($href, $what);
}
if ($this->request->query('custom', false)) {
Util::json_fail(Util::ERR_DISABLED, 'custom disabled', !$this->context->query_option('custom.enabled', false));
$href = $this->request->query('custom');
$custom = new Custom($this->context);
$response['custom'] = $custom->get_customizations($href);
}
if ($this->request->query('l10n', false)) {
Util::json_fail(Util::ERR_DISABLED, 'l10n disabled', !$this->context->query_option('l10n.enabled', false));
$iso_codes = $this->request->query_array('l10n');
$iso_codes = array_filter($iso_codes);
$response['l10n'] = $this->context->get_l10n($iso_codes);
}
if ($this->request->query('search', false)) {
Util::json_fail(Util::ERR_DISABLED, 'search disabled', !$this->context->query_option('search.enabled', false));
$href = $this->request->query('search.href');
$pattern = $this->request->query('search.pattern');
$ignorecase = $this->request->query_boolean('search.ignorecase', false);
$search = new Search($this->context);
$response['search'] = $search->get_items($href, $pattern);
$response['search'] = $search->get_items($href, $pattern, $ignorecase);
}
if ($this->request->query('thumbs', false)) {
Util::json_fail(Util::ERR_DISABLED, 'thumbnails disabled', !$this->context->query_option('thumbnails.enabled', false));
Util::json_fail(Util::ERR_UNSUPPORTED, 'thumbnails not supported', !$this->setup->get('HAS_PHP_JPEG'));
$thumbs = $this->request->query_array('thumbs');
$response['thumbs'] = $this->context->get_thumbs($thumbs);
}
@@ -116,13 +99,11 @@ class Api {
}
private function on_login() {
$pass = $this->request->query('pass');
Util::json_exit(['asAdmin' => $this->context->login_admin($pass)]);
}
private function on_logout() {
Util::json_exit(['asAdmin' => $this->context->logout_admin()]);
}
}

View File

@@ -1,7 +1,6 @@
<?php
class Context {
private static $DEFAULT_PASSHASH = 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e';
private static $AS_ADMIN_SESSION_KEY = 'AS_ADMIN';
@@ -12,7 +11,6 @@ class Context {
private $passhash;
public function __construct($session, $request, $setup) {
$this->session = $session;
$this->request = $request;
$this->setup = $setup;
@@ -25,64 +23,60 @@ class Context {
}
public function get_session() {
return $this->session;
}
public function get_request() {
return $this->request;
}
public function get_setup() {
return $this->setup;
}
public function get_options() {
return $this->options;
}
public function query_option($keypath = '', $default = null) {
return Util::array_query($this->options, $keypath, $default);
}
public function get_types() {
return Json::load($this->setup->get('CONF_PATH') . '/types.json');
}
public function login_admin($pass) {
$this->session->set(Context::$AS_ADMIN_SESSION_KEY, strcasecmp(hash('sha512', $pass), $this->passhash) === 0);
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
}
public function logout_admin() {
$this->session->set(Context::$AS_ADMIN_SESSION_KEY, false);
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
}
public function is_admin() {
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
}
public function is_api_request() {
return strtolower($this->setup->get('REQUEST_METHOD')) === 'post';
}
public function is_info_request() {
return Util::starts_with($this->setup->get('REQUEST_HREF') . '/', $this->setup->get('PUBLIC_HREF'));
}
public function to_href($path, $trailing_slash = true) {
public function is_text_browser() {
return preg_match('/curl|links|lynx|w3m/i', $this->setup->get('HTTP_USER_AGENT')) === 1;
}
public function is_fallback_mode() {
return $this->query_option('view.fallbackMode', false) || $this->is_text_browser();
}
public function to_href($path, $trailing_slash = true) {
$rel_path = substr($path, strlen($this->setup->get('ROOT_PATH')));
$parts = explode('/', $rel_path);
$encoded_parts = [];
@@ -96,13 +90,11 @@ class Context {
}
public function to_path($href) {
$rel_href = substr($href, strlen($this->setup->get('ROOT_HREF')));
return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' . rawurldecode($rel_href));
}
public function is_hidden($name) {
// always hide
if ($name === '.' || $name === '..') {
return true;
@@ -119,7 +111,6 @@ class Context {
}
public function read_dir($path) {
$names = [];
if (is_dir($path)) {
foreach (scandir($path) as $name) {
@@ -137,12 +128,10 @@ class Context {
}
public function is_managed_href($href) {
return $this->is_managed_path($this->to_path($href));
}
public function is_managed_path($path) {
if (!is_dir($path) || strpos($path, '../') !== false || strpos($path, '/..') !== false || $path === '..') {
return false;
}
@@ -175,7 +164,6 @@ class Context {
}
public function get_current_path() {
$current_href = Util::normalize_path($this->setup->get('REQUEST_HREF'), true);
$current_path = $this->to_path($current_href);
@@ -187,7 +175,6 @@ class Context {
}
public function get_items($href, $what) {
if (!$this->is_managed_href($href)) {
return [];
}
@@ -219,7 +206,6 @@ class Context {
}
public function get_langs() {
$langs = [];
$l10n_path = $this->setup->get('CONF_PATH') . '/l10n';
if (is_dir($l10n_path)) {
@@ -238,7 +224,6 @@ class Context {
}
public function get_l10n($iso_codes) {
$results = [];
foreach ($iso_codes as $iso_code) {
@@ -251,7 +236,6 @@ class Context {
}
public function get_thumbs($requests) {
$hrefs = [];
foreach ($requests as $req) {
@@ -263,7 +247,6 @@ class Context {
}
private function prefix_x_head_href($href) {
if (preg_match('@^(https?://|/)@i', $href)) {
return $href;
}
@@ -272,7 +255,6 @@ class Context {
}
private function get_fonts_html() {
$fonts = $this->query_option('view.fonts', []);
$fonts_mono = $this->query_option('view.fontsMono', []);
@@ -292,7 +274,6 @@ class Context {
}
public function get_x_head_html() {
$scripts = $this->query_option('resources.scripts', []);
$styles = $this->query_option('resources.styles', []);

View File

@@ -1,16 +1,13 @@
<?php
class Fallback {
private $context;
public function __construct($context) {
$this->context = $context;
}
public function get_html($path = null) {
if (!$path) {
$path = $this->context->get_current_path();
}

View File

@@ -1,47 +1,28 @@
<?php
class Filesize {
private static $cache = [];
private $cache = [];
public function __construct() {
public static function getSize($path, $withFoldersize, $withDu) {
$fs = new Filesize();
return $fs->size($path, $withFoldersize, $withDu);
}
public function fseek($path) {
$size = 0;
$step = 1073741824;
$handle = fopen($path, 'r');
fseek($handle, 0, SEEK_SET);
while ($step > 1) {
fseek($handle, $step, SEEK_CUR);
if (fgetc($handle) !== false) {
$size += $step + 1;
} else {
fseek($handle, -$step, SEEK_CUR);
$step = intval($step / 2, 10);
}
public static function getCachedSize($path, $withFoldersize, $withDu) {
if (array_key_exists($path, Filesize::$cache)) {
return Filesize::$cache[$path];
}
while (fgetc($handle) !== false) {
$size += 1;
}
fclose($handle);
$size = Filesize::getSize($path, $withFoldersize, $withDu);
Filesize::$cache[$path] = $size;
return $size;
}
public function filesize($path) {
return @filesize($path);
}
private function __construct() {}
private function read_dir($path) {
$paths = [];
if (is_dir($path)) {
foreach (scandir($path) as $name) {
@@ -53,8 +34,23 @@ class Filesize {
return $paths;
}
private function exec($cmdv) {
private function php_filesize($path, $recursive = false) {
// if (PHP_INT_SIZE < 8) {
// }
$size = @filesize($path);
if (!is_dir($path) || !$recursive) {
return $size;
}
foreach ($this->read_dir($path) as $p) {
$size += $this->php_filesize($p, true);
}
return $size;
}
private function exec($cmdv) {
$cmd = implode(' ', array_map('escapeshellarg', $cmdv));
$lines = [];
$rc = null;
@@ -62,38 +58,39 @@ class Filesize {
return $lines;
}
public function du_paths($paths) {
$cmdv = array_merge(['du', '-sk'], $paths);
private function exec_du_all($paths) {
$cmdv = array_merge(['du', '-sbL'], $paths);
$lines = $this->exec($cmdv);
$sizes = [];
foreach ($lines as $line) {
$parts = preg_split('/[\s]+/', $line, 2);
$size = intval($parts[0], 10) * 1024;
$size = intval($parts[0], 10);
$path = $parts[1];
$sizes[$path] = $size;
}
return $sizes;
}
public function du_dir($path) {
return $this->du_paths($this->read_dir($path));
}
public function du_path($path) {
$sizes = $this->du_paths([$path]);
private function exec_du($path) {
$sizes = $this->exec_du_all([$path]);
return $sizes[$path];
}
public function add($path) {
$size = 0;
foreach ($this->read_dir($path) as $p) {
$size += $this->filesize($p);
private function size($path, $withFoldersize = false, $withDu = false) {
if (is_file($path)) {
return $this->php_filesize($path);
}
return $size;
if (is_dir($path) && $withFoldersize) {
if ($withDu) {
return $this->exec_du($path);
}
return $this->php_filesize($path, true);
}
return null;
}
}

View File

@@ -1,9 +1,7 @@
<?php
class Item {
public static function cmp($item1, $item2) {
if ($item1->is_folder && !$item2->is_folder) {
return -1;
}
@@ -15,7 +13,6 @@ class Item {
}
public static function get($context, $path, &$cache) {
if (!Util::starts_with($path, $context->get_setup()->get('ROOT_PATH'))) {
return null;
}
@@ -41,7 +38,6 @@ class Item {
public $is_content_fetched;
private function __construct($context, $path) {
$this->context = $context;
$this->path = Util::normalize_path($path, false);
@@ -53,7 +49,6 @@ class Item {
}
public function to_json_object() {
$obj = [
'href' => $this->href,
'time' => $this->date * 1000, // seconds (PHP) to milliseconds (JavaScript)
@@ -69,7 +64,6 @@ class Item {
}
public function get_parent(&$cache) {
$parent_path = Util::normalize_path(dirname($this->path), false);
if ($parent_path !== $this->path && Util::starts_with($parent_path, $this->context->get_setup()->get('ROOT_PATH'))) {
return Item::get($this->context, $parent_path, $cache);
@@ -78,7 +72,6 @@ class Item {
}
public function get_content(&$cache) {
$items = [];
if (!$this->context->is_managed_href($this->href)) {

View File

@@ -1,12 +1,10 @@
<?php
class Json {
const SINGLE = 1;
const MULTI = 2;
public static function load($path) {
if (!is_readable($path)) {
return [];
}
@@ -16,25 +14,21 @@ class Json {
}
public static function save($path, $obj) {
$json = json_encode($obj);
return file_put_contents($path, $json) !== false;
}
public static function decode($json) {
private static function decode($json) {
$json = Json::strip($json);
return json_decode($json, true);
}
public static function strip($commented_json) {
private static function strip($commented_json) {
$insideString = false;
$insideComment = false;
$json = '';
for ($i = 0; $i < strlen($commented_json); $i += 1) {
for ($i = 0, $len = strlen($commented_json); $i < $len; $i += 1) {
$char = $commented_json[$i];
$charchar = $char . @$commented_json[$i + 1];
$prevChar = @$commented_json[$i - 1];

View File

@@ -1,25 +1,21 @@
<?php
class Logger {
private static $start;
private static $prev;
public static function init() {
private static function time() {
return microtime(true) * 1000; // sec * 1000 = ms
}
public static function init() {
self::$start = self::time();
self::$prev = self::$start;
register_shutdown_function(function () { Logger::log('shutdown'); });
Logger::log('--------------------------------');
}
private static function time() {
return microtime(true) * 1000; // sec * 1000 = ms
}
public static function log($message=null, $obj=null) {
$now = self::time();
$message = number_format($now - self::$start, 3) . ' ' . number_format($now - self::$prev, 3) . ' ' . $message;
@@ -28,4 +24,5 @@ class Logger {
self::$prev = $now;
}
}
Logger::init();

View File

@@ -1,16 +1,14 @@
<?php
class Request {
private $params;
public function __construct($params) {
$this->params = $params;
public function __construct($params, $body) {
$data = json_decode($body, true);
$this->params = $data !== null ? $data : $params;
}
public function query($keypath = '', $default = Util::NO_DEFAULT) {
$value = Util::array_query($this->params, $keypath, Util::NO_DEFAULT);
if ($value === Util::NO_DEFAULT) {
@@ -22,20 +20,17 @@ class Request {
}
public function query_boolean($keypath = '', $default = Util::NO_DEFAULT) {
$value = $this->query($keypath, $default);
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}
public function query_numeric($keypath = '', $default = Util::NO_DEFAULT) {
$value = $this->query($keypath, $default);
Util::json_fail(Util::ERR_ILLIGAL_PARAM, 'parameter \'' . $keypath . '\' is not numeric', !is_numeric($value));
return intval($value, 10);
}
public function query_array($keypath = '', $default = Util::NO_DEFAULT) {
$value = $this->query($keypath, $default);
Util::json_fail(Util::ERR_ILLIGAL_PARAM, 'parameter \'' . $keypath . '\' is no array', !is_array($value));
return $value;

View File

@@ -1,24 +1,19 @@
<?php
class Session {
private static $KEY_PREFIX = '__H5AI__';
private $store;
public function __construct(&$store) {
$this->store = &$store;
}
public function set($key, $value) {
$key = Session::$KEY_PREFIX . $key;
$this->store[$key] = $value;
}
public function get($key, $default = null) {
$key = Session::$KEY_PREFIX . $key;
return array_key_exists($key, $this->store) ? $this->store[$key] : $default;
}

View File

@@ -1,12 +1,10 @@
<?php
class Setup {
private $store;
private $refresh;
public function __construct($refresh = false) {
$this->store = [];
$this->refresh = $refresh;
@@ -19,7 +17,6 @@ class Setup {
}
private function set($key, $value) {
if (array_key_exists($key, $this->store)) {
Logger::log('setup key already taken', [
'key' => $key,
@@ -40,7 +37,6 @@ class Setup {
}
public function get($key) {
if (!array_key_exists($key, $this->store)) {
Logger::log('setup key not found', ['key' => $key]);
exit;
@@ -50,18 +46,18 @@ class Setup {
}
private function add_globals_and_envs() {
$this->set('PHP_VERSION', PHP_VERSION);
$this->set('MIN_PHP_VERSION', MIN_PHP_VERSION);
$this->set('PHP_ARCH', (PHP_INT_SIZE * 8) . '-bit');
$this->set('REQUEST_METHOD', getenv('REQUEST_METHOD'));
$this->set('REQUEST_HREF', parse_url(getenv('REQUEST_URI'), PHP_URL_PATH));
$this->set('SCRIPT_NAME', getenv('SCRIPT_NAME'));
$this->set('SERVER_SOFTWARE', getenv('SERVER_SOFTWARE'));
$this->set('REQUEST_METHOD', $_SERVER['REQUEST_METHOD']);
$this->set('REQUEST_HREF', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$this->set('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
$this->set('SERVER_SOFTWARE', $_SERVER['SERVER_SOFTWARE']);
$this->set('HTTP_USER_AGENT', $_SERVER['HTTP_USER_AGENT']);
}
private function add_php_checks() {
$this->set('HAS_PHP_EXIF', function_exists('exif_thumbnail'));
$has_php_jpeg = false;
@@ -73,14 +69,12 @@ class Setup {
}
private function add_app_metadata() {
$this->set('NAME', 'h5ai');
$this->set('VERSION', H5AI_VERSION);
$this->set('FILE_PREFIX', '_h5ai');
}
private function add_server_metadata_and_check() {
$server_software = $this->get('SERVER_SOFTWARE');
$server_name = null;
$server_version = null;
@@ -96,7 +90,6 @@ class Setup {
}
private function add_paths() {
$script_name = $this->get('SCRIPT_NAME');
if ($this->get('SERVER_NAME') === 'lighttpd') {
$script_name = preg_replace('#^.*?//#', '/', $script_name);
@@ -123,13 +116,12 @@ class Setup {
}
private function add_sys_cmd_checks() {
$cmds_cache_path = Util::normalize_path($this->get('CACHE_PRV_PATH') . '/cmds.json', false);
$cmds = Json::load($cmds_cache_path);
if (sizeof($cmds) === 0 || $this->refresh) {
$cmds['command'] = Util::exec_0('command -v command');
$cmds['which'] = Util::exec_0('which which');
$cmds['which'] = Util::exec_0('which which') || Util::exec_0('which which.exe');
$cmd = false;
if ($cmds['command']) {
@@ -139,7 +131,7 @@ class Setup {
}
foreach (['avconv', 'convert', 'du', 'ffmpeg', 'gm', 'tar', 'zip'] as $c) {
$cmds[$c] = ($cmd !== false) && Util::exec_0($cmd . ' ' . $c);
$cmds[$c] = ($cmd !== false) && (Util::exec_0($cmd . ' ' . $c) || Util::exec_0($cmd . ' ' . $c . '.exe'));
}
Json::save($cmds_cache_path, $cmds);
@@ -150,7 +142,6 @@ class Setup {
}
public function to_jsono($as_admin = false) {
$keys = [
'PUBLIC_HREF',
'ROOT_HREF'
@@ -162,6 +153,7 @@ class Setup {
'PHP_VERSION',
'MIN_PHP_VERSION',
'PHP_ARCH',
'HAS_PHP_EXIF',
'HAS_PHP_JPEG',

View File

@@ -1,18 +1,14 @@
<?php
class Theme {
private static $EXTENSIONS = ['svg', 'png', 'jpg'];
private $context;
public function __construct($context) {
$this->context = $context;
}
public function get_icons() {
$public_path = $this->context->get_setup()->get('PUBLIC_PATH');
$theme = $this->context->query_option('view.theme', '-NONE-');
$theme_path = $public_path . '/images/themes/' . $theme;

View File

@@ -1,7 +1,6 @@
<?php
class Util {
const ERR_MISSING_PARAM = 'ERR_MISSING_PARAM';
const ERR_ILLIGAL_PARAM = 'ERR_ILLIGAL_PARAM';
const ERR_FAILED = 'ERR_FAILED';
@@ -11,27 +10,23 @@ class Util {
const RE_DELIMITER = '@';
public static function normalize_path($path, $trailing_slash = false) {
$path = preg_replace('#[\\\\/]+#', '/', $path);
return preg_match('#^(\w:)?/$#', $path) ? $path : (rtrim($path, '/') . ($trailing_slash ? '/' : ''));
}
public static function json_exit($obj = []) {
header('Content-type: application/json;charset=utf-8');
echo json_encode($obj);
exit;
}
public static function json_fail($err, $msg = '', $cond = true) {
if ($cond) {
Util::json_exit(['err' => $err, 'msg' => $msg]);
}
}
public static function array_query($array, $keypath = '', $default = Util::NO_DEFAULT) {
$value = $array;
$keys = array_filter(explode('.', $keypath));
@@ -46,30 +41,25 @@ class Util {
}
public static function starts_with($sequence, $head) {
return substr($sequence, 0, strlen($head)) === $head;
}
public static function ends_with($sequence, $tail) {
$len = strlen($tail);
return $len === 0 ? true : substr($sequence, -$len) === $tail;
}
public static function wrap_pattern($pattern) {
return Util::RE_DELIMITER . str_replace(Util::RE_DELIMITER, '\\' . Util::RE_DELIMITER, $pattern) . Util::RE_DELIMITER;
}
public static function passthru_cmd($cmd) {
$rc = null;
passthru($cmd, $rc);
return $rc;
}
public static function exec_cmdv($cmdv) {
if (!is_array($cmdv)) {
$cmdv = func_get_args();
}
@@ -82,7 +72,6 @@ class Util {
}
public static function exec_0($cmd) {
$lines = [];
$rc = null;
try {
@@ -92,32 +81,9 @@ class Util {
return false;
}
private static $size_cache = [];
public static function filesize($context, $path) {
if (array_key_exists($path, Util::$size_cache)) {
return Util::$size_cache[$path];
}
$fs = new Filesize();
$size = null;
if (is_file($path)) {
if (PHP_INT_SIZE < 8) {
$size = $fs->fseek($path);
} else {
$size = $fs->filesize($path);
}
} else if (is_dir($path) && $context->query_option('foldersize.enabled', false)) {
if ($context->get_setup()->get('HAS_CMD_DU') && $context->query_option('foldersize.type', null) === 'shell-du') {
$size = $fs->du_path($path);
} else {
$size = $fs->add($path);
}
}
Util::$size_cache[$path] = $size;
return $size;
$withFoldersize = $context->query_option('foldersize.enabled', false);
$withDu = $context->get_setup()->get('HAS_CMD_DU') && $context->query_option('foldersize.type', null) === 'shell-du';
return Filesize::getCachedSize($path, $withFoldersize, $withDu);
}
}

View File

@@ -1,7 +1,6 @@
<?php
class Archive {
const NULL_BYTE = "\0";
private static $SEGMENT_SIZE = 16777216; // 1024 * 1024 * 16 = 16MiB
@@ -14,12 +13,10 @@ class Archive {
private $files;
public function __construct($context) {
$this->context = $context;
}
public function output($type, $base_href, $hrefs) {
$this->base_path = $this->context->to_path($base_href);
if (!$this->context->is_managed_path($this->base_path)) {
return false;
@@ -39,22 +36,16 @@ class Archive {
}
if ($type === 'php-tar') {
return $this->php_tar($this->dirs, $this->files);
} elseif ($type === 'shell-tar') {
return $this->shell_cmd(Archive::$TAR_PASSTHRU_CMD);
} elseif ($type === 'shell-zip') {
return $this->shell_cmd(Archive::$ZIP_PASSTHRU_CMD);
}
return false;
}
private function shell_cmd($cmd) {
$cmd = str_replace('[ROOTDIR]', escapeshellarg($this->base_path), $cmd);
$cmd = str_replace('[DIRS]', count($this->dirs) ? implode(' ', array_map('escapeshellarg', $this->dirs)) : '', $cmd);
$cmd = str_replace('[FILES]', count($this->files) ? implode(' ', array_map('escapeshellarg', $this->files)) : '', $cmd);
@@ -67,11 +58,9 @@ class Archive {
}
private function php_tar($dirs, $files) {
$filesizes = [];
$total_size = 512 * count($dirs);
foreach (array_keys($files) as $real_file) {
$size = filesize($real_file);
$filesizes[$real_file] = $size;
@@ -84,11 +73,10 @@ class Archive {
header('Content-Length: ' . $total_size);
foreach ($dirs as $real_dir => $archived_dir) {
echo $this->php_tar_header($archived_dir, 0, @filemtime($real_dir . DIRECTORY_SEPARATOR . "."), 5);
echo $this->php_tar_header($archived_dir, 0, @filemtime($real_dir . DIRECTORY_SEPARATOR . '.'), 5);
}
foreach ($files as $real_file => $archived_file) {
foreach ($files as $real_file => $archived_file) {
$size = $filesizes[$real_file];
echo $this->php_tar_header($archived_file, $size, @filemtime($real_file), 0);
@@ -103,7 +91,6 @@ class Archive {
}
private function php_tar_header($filename, $size, $mtime, $type) {
$name = substr(basename($filename), -99);
$prefix = substr(Util::normalize_path(dirname($filename)), -154);
if ($prefix === '.') {
@@ -136,7 +123,6 @@ class Archive {
}
private function print_file($file) {
// Send file content in segments to not hit PHP's memory limit (default: 128M)
if ($fd = fopen($file, 'rb')) {
while (!feof($fd)) {
@@ -149,9 +135,7 @@ class Archive {
}
private function add_hrefs($hrefs) {
foreach ($hrefs as $href) {
if (trim($href) === '') {
continue;
}
@@ -174,20 +158,17 @@ class Archive {
}
private function add_file($real_file, $archived_file) {
if (is_readable($real_file)) {
$this->files[$real_file] = $archived_file;
}
}
private function add_dir($real_dir, $archived_dir) {
if ($this->context->is_managed_path($real_dir)) {
$this->dirs[$real_dir] = $archived_dir;
$files = $this->context->read_dir($real_dir);
foreach ($files as $file) {
$real_file = $real_dir . '/' . $file;
$archived_file = $archived_dir . '/' . $file;

View File

@@ -1,18 +1,14 @@
<?php
class Custom {
private static $EXTENSIONS = ['html', 'md'];
private $context;
public function __construct($context) {
$this->context = $context;
}
private function read_custom_file($path, $name, &$content, &$type) {
$file_prefix = $this->context->get_setup()->get('FILE_PREFIX');
foreach (Custom::$EXTENSIONS as $ext) {
@@ -26,7 +22,6 @@ class Custom {
}
public function get_customizations($href) {
if (!$this->context->query_option('custom.enabled', false)) {
return [
'header' => ['content' => null, 'type' => null],
@@ -46,14 +41,12 @@ class Custom {
$this->read_custom_file($path, 'footer', $footer, $footer_type);
while ($header === null || $footer === null) {
if ($header === null) {
$this->read_custom_file($path, 'headers', $header, $header_type);
}
if ($footer === null) {
$this->read_custom_file($path, 'footers', $footer, $footer_type);
}
if ($path === $root_path) {
break;
}

View File

@@ -1,19 +1,19 @@
<?php
class Search {
private $context;
public function __construct($context) {
$this->context = $context;
}
public function get_paths($root, $pattern = null) {
public function get_paths($root, $pattern = null, $ignorecase = false) {
$paths = [];
if ($pattern && $this->context->is_managed_path($root)) {
$re = Util::wrap_pattern($pattern);
if ($ignorecase) {
$re .= 'i';
}
$names = $this->context->read_dir($root);
foreach ($names as $name) {
$path = $root . '/' . $name;
@@ -21,20 +21,18 @@ class Search {
$paths[] = $path;
}
if (@is_dir($path)) {
$paths = array_merge($paths, $this->get_paths($path, $pattern));
$paths = array_merge($paths, $this->get_paths($path, $pattern, $ignorecase));
}
}
}
return $paths;
}
public function get_items($href, $pattern = null) {
public function get_items($href, $pattern = null, $ignorecase = false) {
$cache = [];
$root = $this->context->to_path($href);
$paths = $this->get_paths($root, $pattern);
$paths = $this->get_paths($root, $pattern, $ignorecase);
$items = array_map(function ($path) {
return Item::get($this->context, $path, $cache)->to_json_object();
}, $paths);
return $items;

View File

@@ -1,11 +1,10 @@
<?php
class Thumb {
private static $FFMPEG_CMDV = ['ffmpeg', '-ss', '0:00:10', '-i', '[SRC]', '-an', '-vframes', '1', '[DEST]'];
private static $AVCONV_CMDV = ['avconv', '-ss', '0:00:10', '-i', '[SRC]', '-an', '-vframes', '1', '[DEST]'];
private static $CONVERT_CMDV = ['convert', '-density', '200', '-quality', '100', '-sharpen', '0x1.0', '-strip', '[SRC][0]', '[DEST]'];
private static $GM_CONVERT_CMDV = ['gm', 'convert', '-density', '200', '-quality', '100', '-sharpen', '0x1.0', '[SRC][0]', '[DEST]'];
private static $CONVERT_CMDV = ['convert', '-density', '200', '-quality', '100', '-strip', '[SRC][0]', '[DEST]'];
private static $GM_CONVERT_CMDV = ['gm', 'convert', '-density', '200', '-quality', '100', '[SRC][0]', '[DEST]'];
private static $THUMB_CACHE = 'thumbs';
private $context;
@@ -14,7 +13,6 @@ class Thumb {
private $thumbs_href;
public function __construct($context) {
$this->context = $context;
$this->setup = $context->get_setup();
$this->thumbs_path = $this->setup->get('CACHE_PUB_PATH') . '/' . Thumb::$THUMB_CACHE;
@@ -26,7 +24,6 @@ class Thumb {
}
public function thumb($type, $source_href, $width, $height) {
$source_path = $this->context->to_path($source_href);
if (!file_exists($source_path) || Util::starts_with($source_path, $this->setup->get('CACHE_PUB_PATH'))) {
return null;
@@ -53,7 +50,6 @@ class Thumb {
}
private function thumb_href($source_path, $width, $height) {
if (!file_exists($source_path)) {
return null;
}
@@ -63,7 +59,6 @@ class Thumb {
$thumb_href = $this->thumbs_href . '/' . $name;
if (!file_exists($thumb_path) || filemtime($source_path) >= filemtime($thumb_path)) {
$image = new Image();
$et = false;
@@ -86,7 +81,6 @@ class Thumb {
}
private function capture($cmdv, $source_path) {
if (!file_exists($source_path)) {
return null;
}
@@ -94,7 +88,6 @@ class Thumb {
$capture_path = $this->thumbs_path . '/capture-' . sha1($source_path) . '.jpg';
if (!file_exists($capture_path) || filemtime($source_path) >= filemtime($capture_path)) {
foreach ($cmdv as &$arg) {
$arg = str_replace('[SRC]', $source_path, $arg);
$arg = str_replace('[DEST]', $capture_path, $arg);
@@ -108,7 +101,6 @@ class Thumb {
}
class Image {
private $source_file;
private $source;
private $width;
@@ -117,7 +109,6 @@ class Image {
private $dest;
public function __construct($filename = null) {
$this->source_file = null;
$this->source = null;
$this->width = null;
@@ -130,13 +121,11 @@ class Image {
}
public function __destruct() {
$this->release_source();
$this->release_dest();
}
public function set_source($filename) {
$this->release_source();
$this->release_dest();
@@ -160,7 +149,6 @@ class Image {
}
public function save_dest_jpeg($filename, $quality = 80) {
if (!is_null($this->dest)) {
@imagejpeg($this->dest, $filename, $quality);
@chmod($filename, 0775);
@@ -168,7 +156,6 @@ class Image {
}
public function release_dest() {
if (!is_null($this->dest)) {
@imagedestroy($this->dest);
$this->dest = null;
@@ -176,7 +163,6 @@ class Image {
}
public function release_source() {
if (!is_null($this->source)) {
@imagedestroy($this->source);
$this->source_file = null;
@@ -188,7 +174,6 @@ class Image {
}
public function thumb($width, $height) {
if (is_null($this->source)) {
return;
}
@@ -233,7 +218,6 @@ class Image {
}
public function rotate($angle) {
if (is_null($this->source) || ($angle !== 90 && $angle !== 180 && $angle !== 270)) {
return;
}
@@ -245,7 +229,6 @@ class Image {
}
public function normalize_exif_orientation($exif_source_file = null) {
if (is_null($this->source) || !function_exists('exif_read_data')) {
return;
}

View File

@@ -1,8 +0,0 @@
extends ./page.tpl.jade
block init
- var title = 'index - powered by h5ai v' + pkg.version + ' (' + pkg.homepage + ')'
- var module = 'index'
block body
div#fallback <?= $fallback_html; ?>

View File

@@ -0,0 +1,8 @@
extends ./page.tpl.pug
block init
- var title = `index - powered by h5ai v${pkg.version} (${pkg.homepage})`
- var module = 'index'
block body
div#fallback <?= $fallback_html; ?>

View File

@@ -1,10 +0,0 @@
extends ./page.tpl.jade
block init
- var title = 'h5ai info page - v' + pkg.version
- var module = 'info'
block body
div#content
h1#header
a(href='#{pkg.homepage}') h5ai

View File

@@ -0,0 +1,10 @@
extends ./page.tpl.pug
block init
- var title = `h5ai info page - v${pkg.version}`
- var module = 'info'
block body
div#content
h1#header
a(href=pkg.homepage) h5ai

View File

@@ -5,23 +5,26 @@ doctype html
html(class='no-js', lang='en')
head
<!--[if lt IE 10]><meta id='no-browser'><![endif]-->
meta(charset='utf-8')
meta(http-equiv='x-ua-compatible', content='ie=edge')
title #{title}
meta(name='description', content='#{title}')
meta(name='description', content=title)
meta(name='viewport', content='width=device-width, initial-scale=1')
link(rel='shortcut icon', href!='<?= $public_href; ?>images/favicon/favicon-16-32.ico')
link(rel='apple-touch-icon-precomposed', type='image/png', href!='<?= $public_href; ?>images/favicon/favicon-152.png')
link(rel='stylesheet', href!='<?= $public_href; ?>css/styles.css')
script(src!='<?= $public_href; ?>js/scripts.js', data-module='#{module}')
<?php if (!$fallback_mode) { ?>
script(src!='<?= $public_href; ?>js/scripts.js', data-module=module)
<?php } ?>
<?= $x_head_tags; ?>
body#root(class='#{module}')
body#root(class=module)
div#fallback-hints
<?php if (!$fallback_mode) { ?>
span.noJsMsg Works best with JavaScript enabled!
span.noBrowserMsg Works best in #[a(href='http://browsehappy.com') modern browsers]!
span.backlink #[a(href='#{pkg.homepage}', title='h5ai v#{pkg.version} - #{pkg.description}') powered by h5ai]
<?php } ?>
span.backlink #[a(href=pkg.homepage, title=`h5ai v${pkg.version} - ${pkg.description}`) powered by h5ai]
block body

View File

@@ -1,27 +1,13 @@
Satisfy all
## make this folder accessible
# Apache < 2.3
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
DirectoryIndex disabled
<IfModule mod_autoindex.c>
Options -Indexes
Satisfy All
</IfModule>
AddDefaultCharset utf-8
<IfModule mod_mime.c>
AddCharset utf-8 .css .html .js .json .php .svg
</IfModule>
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
ExpiresByType image/x-icon "access plus 1 week"
# Apache ≥ 2.3
<IfModule mod_authz_core.c>
Require all granted
</IfModule>

View File

@@ -27,7 +27,7 @@
@col-back-native-selection: @col-pink-a200;
@col-text: @col-text-primary-black;
@col-back: @col-grey-100;
@col-back: @col-white;
@col-back-paper: @col-white;
@col-back-panel: @col-grey-50;
@col-text-hover: @col-blue-400;

View File

@@ -1,5 +1,4 @@
#cm-overlay {
display: none;
position: fixed;
left: 0;
top: 0;

View File

@@ -3,7 +3,6 @@
input {
display: none;
border: none;
font-weight: lighter;
font-size: 16px;
color: @col-text;
background: transparent;

View File

@@ -1,12 +1,9 @@
#info {
display: none;
overflow: auto;
flex: 0 0 auto;
order: 99;
padding: 16px;
border-left: 1px solid @col-border;
padding: 32px 32px 32px 48px;
white-space: nowrap;
overflow-x: hidden;
width: 240px;
@@ -50,7 +47,7 @@
margin: 0 auto;
width: 200px;
canvas {
img {
display: block;
}
}

View File

@@ -1,4 +1,4 @@
#pv-aud-audio {
#pv-content-aud {
.raised;
position: absolute;

View File

@@ -1,4 +1,4 @@
#pv-img-image {
#pv-content-img {
.raised;
@check-white: #f8f8f8;

View File

@@ -1,6 +1,7 @@
#pv-txt-text {
#pv-content-txt {
.raised;
box-sizing: border-box;
max-width: 960px;
text-align: left;
background: @col-back-paper;
@@ -8,103 +9,28 @@
padding: 8px;
overflow: auto;
&.highlighted {
a, a:active, a:visited {
color: #2080FF;
text-decoration: none;
cursor: pointer;
&:hover {
color: #68A9FF;
}
}
}
pre#pv-content-txt {
code {
line-height: 1.2em;
}
a, a:active, a:visited {
color: #2080FF;
text-decoration: none;
cursor: pointer;
&:hover {
color: #68A9FF;
}
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #aaa;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.builtin {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: #a67f59;
background: hsla(0,0%,100%,.5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function {
color: #DD4A68;
}
.token.regex,
.token.important {
color: #e90;
}
.token.important {
font-weight: bold;
}
.token.entity {
cursor: help;
}
}
&.markdown {
div#pv-content-txt {
font-size: 1.1em;
padding: 8px 24px;
a, a:active, a:visited {
color: #2080FF;
text-decoration: none;
cursor: pointer;
&:hover {
color: #68A9FF;
}
}
code {
color: #008200;
}
}
}

View File

@@ -1,4 +1,4 @@
#pv-vid-video {
#pv-content-vid {
.raised;
position: absolute;
@@ -7,7 +7,7 @@
max-height: 100%;
}
#pv-vid-video:-webkit-full-screen {
#pv-content-vid:-webkit-full-screen {
top: auto !important;
left: auto !important;
}

View File

@@ -1,5 +1,4 @@
#pv-overlay {
display: none;
position: fixed;
left: 0;
top: 0;
@@ -17,7 +16,7 @@
background: @col-grey-900;
}
#pv-content {
#pv-container {
position: absolute;
}

View File

@@ -3,7 +3,6 @@
input {
display: none;
border: none;
font-weight: lighter;
font-size: 16px;
color: @col-text;
background: transparent;

View File

@@ -1,5 +1,4 @@
#selection-rect {
display: none;
position: absolute;
left: 0;
top: 0;

View File

@@ -1,16 +1,12 @@
#tree {
display: none;
overflow: auto;
flex: 0 0 auto;
order: 1;
padding: 16px 16px 16px 8px;
border-right: 1px solid @col-border;
padding: 32px 32px 32px 16px;
white-space: nowrap;
max-width: 250px;
overflow-x: hidden;
font-weight: lighter;
a, a:active, a.visited {
display: block;
@@ -37,23 +33,29 @@
cursor: pointer;
img {
.eased-transition;
// .eased-transition;
width: 20px;
height: 20px;
}
&.open {
img {
transform: rotate(90deg);
zoom: 1;
}
}
&.unknown {
.item {
clear: left;
&.open > .indicator img {
transform: rotate(90deg);
}
&.unknown > .indicator {
opacity: 0.3;
}
&.none {
&.none > .indicator {
opacity: 0;
cursor: inherit;
}
&.unknown > .content, &.none > .content, &.closed > .content {
display: none;
}
}
.icon {
@@ -71,8 +73,12 @@
}
.content {
list-style: none;
margin: 0;
padding: 0 0 0 20px;
}
.summary {
color: @col-text-disabled-black;
padding: 0 0 0 8px;
}
}

View File

@@ -5,7 +5,6 @@
order: 50;
color: @col-text;
text-align: center;
font-weight: lighter;
}
code {
@@ -67,7 +66,7 @@
#hint {
margin: 12px auto;
width: 300px;
width: 320px;
}
#tests {
@@ -78,11 +77,10 @@
padding: 0;
.test {
.card;
.rounded;
background: @col-back-paper;
margin: 12px 0 0 0;
padding: 8px 12px 12px 12px;
border-bottom: 1px solid @col-border;
}
.label {
display: inline-block;

View File

@@ -12,3 +12,18 @@
*:focus {
outline: none;
}
code, pre {
font-family: @font-family-mono;
font-size: @font-size-mono;
font-weight: @font-weight;
color: @col-text;
}
audio, canvas, iframe, img, svg, video {
vertical-align: middle;
}
textarea {
resize: vertical;
}

View File

@@ -1,5 +1,18 @@
.card {
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.2);
.hidden {
display: none !important;
}
.invisible {
visibility: hidden;
}
.clearfix:before,
.clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.raised {
@@ -43,7 +56,6 @@
}
.el-button {
.card;
.rounded;
.eased-transition;
color: @col-text-primary-white;
@@ -57,10 +69,11 @@
}
.el-input {
.card;
.rounded;
.clear-appearance;
background: @col-back-paper;
border: none;
outline: none;
background: @col-back-panel;
border: 1px solid @col-border;
}

View File

@@ -8,12 +8,12 @@
}
}
#view.view-details {
.header .label, .item .label {
margin-right: 80px !important;
}
.header .date, .item .date {
display: none;
}
// .header .label, .item .label {
// margin-right: 80px !important;
// }
// .header .date, .item .date {
// display: none;
// }
}
#tree, #info {
display: none !important;
@@ -21,8 +21,15 @@
}
@media print {
a[href]:after {
content: "" !important;
*,
*:before,
*:after,
*:first-letter,
*:first-line {
background: transparent !important;
color: #000 !important;
box-shadow: none !important;
text-shadow: none !important;
}
#toolbar, #sidebar, #tree, #info {
display: none !important;

View File

@@ -2,4 +2,5 @@
overflow: auto;
flex: 1 1 auto;
order: 50;
position: relative;
}

View File

@@ -5,7 +5,6 @@
padding: 32px 16px;
table {
.card;
display: block;
width: 100%;
border-collapse: collapse;
@@ -15,13 +14,12 @@
padding: 6px;
text-align: left;
border: none;
border-bottom: 1px solid #eee;
border-bottom: 1px solid #f0f0f0;
}
th {
color: #aaa;
font-weight: lighter;
font-weight: normal;
line-height: 36px;
background: @col-back-panel;
}
td {
overflow: hidden;
@@ -70,7 +68,7 @@
overflow: hidden;
text-align: right;
background: @col-back-panel;
box-shadow: 0 0 8px 0 rgba(0,0,0,0.2);
border-bottom: 1px solid @col-border;
a, a:active, a:visited {
.eased-transition;

View File

@@ -7,6 +7,7 @@
bottom: 0;
overflow: hidden;
background: @col-back;
line-height: 1.4;
}
#root, input, select {
@@ -15,10 +16,3 @@
font-weight: @font-weight;
color: @col-text;
}
pre, code {
font-family: @font-family-mono;
font-size: @font-size-mono;
font-weight: @font-weight;
color: @col-text;
}

View File

@@ -1,13 +1,17 @@
#sidebar {
display: none;
overflow-x: hidden;
overflow-y: auto;
flex: 0 0 auto;
order: 0;
background: @col-back-panel;
border-right: 1px solid rgba(0,0,0,0.08);
border-right: 1px solid @col-border;
padding: 16px;
position: absolute;
top: 48px;
min-height: 100%;
z-index: 1;
.block {
display: block;
margin: 0 0 24px 0;

View File

@@ -5,7 +5,7 @@
order: 1;
background: @col-back-panel;
box-shadow: 0 0 8px 0 rgba(0,0,0,0.2);
border-bottom: 1px solid @col-border;
z-index: 1;
}

View File

@@ -23,24 +23,19 @@
}
}
margin: 16px;
#items {
.rounded;
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.2);
}
margin: 32px;
.header {
position: relative;
white-space: nowrap;
display: list-item;
background: @col-back-panel;
border-bottom: 1px solid rgba(0,0,0,0.07);
border-radius: 2px 2px 0 0;
.label, .date, .size {
.eased-transition;
line-height: 46px;
line-height: 24px;
padding: 0px 8px 16px 8px;
opacity: 0.4;
outline: 0;
@@ -115,3 +110,26 @@
.view-details-sized(16px)
}
#view.view-details {
&.width-0 {
.label {
margin-right: 4px;
}
.date {
display: none;
}
.size {
display: none;
}
}
&.width-1 {
.label {
margin-right: 64px;
}
.date {
display: none;
}
}
}

View File

@@ -17,10 +17,9 @@
}
}
margin: 8px;
margin: 28px;
.item {
.card;
.rounded;
overflow: hidden;
float: left;
@@ -34,7 +33,6 @@
.square {
display: inline-block;
vertical-align: top;
background: @col-back-panel;
}
.label {

View File

@@ -21,10 +21,9 @@
}
}
margin: 8px;
margin: 28px;
.item {
.card;
.rounded;
overflow: hidden;
float: left;
@@ -43,6 +42,7 @@
.label {
padding: 0 6px;
line-height: 24px;
text-align: center;
}
.date, .size {

View File

@@ -1,7 +1,6 @@
@charset "utf-8";
// @include "vendor/normalize.less"
// @include "vendor/h5bp-pre.less"
// @include "../../../../node_modules/normalize.css/normalize.css"
// @include "lib/colors.less"
// @include "lib/fonts.less"
@@ -11,5 +10,3 @@
// @include "lib/*/*.less"
// @include "lib/responsive.less"
// @include "vendor/h5bp-post.less"

View File

@@ -1,169 +0,0 @@
/* ==========================================================================
Helper classes
========================================================================== */
/*
* Hide visually and from screen readers
*/
.hidden {
display: none !important;
}
/*
* Hide only visually, but have it available for screen readers:
* http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
*/
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/*
* Extends the .visuallyhidden class to allow the element
* to be focusable when navigated to via the keyboard:
* https://www.drupal.org/node/897638
*/
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
/*
* Hide visually and from screen readers, but maintain layout
*/
.invisible {
visibility: hidden;
}
/*
* Clearfix: contain floats
*
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* `contenteditable` attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that receive the `clearfix` class.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
.clearfix:before,
.clearfix:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.clearfix:after {
clear: both;
}
/* ==========================================================================
EXAMPLE Media Queries for Responsive Design.
These examples override the primary ('mobile first') styles.
Modify as content requires.
========================================================================== */
// @media only screen and (min-width: 35em) {
// /* Style adjustments for viewports that meet the condition */
// }
// @media print,
// (-webkit-min-device-pixel-ratio: 1.25),
// (min-resolution: 1.25dppx),
// (min-resolution: 120dpi) {
// /* Style adjustments for high resolution devices */
// }
/* ==========================================================================
Print styles.
Inlined to avoid the additional HTTP request:
http://www.phpied.com/delay-loading-your-print-css/
========================================================================== */
@media print {
*,
*:before,
*:after,
*:first-letter,
*:first-line {
background: transparent !important;
color: #000 !important; /* Black prints faster:
http://www.sanbeiji.com/archives/953 */
box-shadow: none !important;
text-shadow: none !important;
}
a,
a:visited {
text-decoration: underline;
}
a[href]:after {
content: " (" attr(href) ")";
}
abbr[title]:after {
content: " (" attr(title) ")";
}
/*
* Don't show links that are fragment identifiers,
* or use the `javascript:` pseudo protocol
*/
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
blockquote {
border: 1px solid #999;
page-break-inside: avoid;
}
/*
* Printing Tables:
* http://css-discuss.incutio.com/wiki/Printing_Tables
*/
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
img {
max-width: 100% !important;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
}

View File

@@ -1,96 +0,0 @@
/* HTML5 Boilerplate v5.2.0 | MIT License | https://html5boilerplate.com/ */
/*
* What follows is the result of much research on cross-browser styling.
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
* Kroc Camen, and the H5BP dev community and team.
*/
/* ==========================================================================
Base styles: opinionated defaults
========================================================================== */
html {
color: #222;
font-size: 1em;
line-height: 1.4;
}
/*
* Remove text-shadow in selection highlight:
* https://twitter.com/miketaylr/status/12228805301
*
* These selection rule sets have to be separate.
* Customize the background color to match your design.
*/
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
/*
* A better looking default horizontal rule
*/
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 1em 0;
padding: 0;
}
/*
* Remove the gap between audio, canvas, iframes,
* images, videos and the bottom of their containers:
* https://github.com/h5bp/html5-boilerplate/issues/440
*/
audio,
canvas,
iframe,
img,
svg,
video {
vertical-align: middle;
}
/*
* Remove default fieldset styles.
*/
fieldset {
border: 0;
margin: 0;
padding: 0;
}
/*
* Allow only vertical resizing of textareas.
*/
textarea {
resize: vertical;
}
/* ==========================================================================
Browser Upgrade Prompt
========================================================================== */
// .browserupgrade {
// margin: 0.2em 0;
// background: #ccc;
// color: #000;
// padding: 0.2em 0;
// }
/* ==========================================================================
Author's custom styles
========================================================================== */

View File

@@ -1,424 +0,0 @@
/* normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS and IE text size adjust after device orientation change,
* without disabling user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined for any HTML5 element in IE 8/9.
* Correct `block` display not defined for `details` or `summary` in IE 10/11
* and Firefox.
* Correct `block` display not defined for `main` in IE 11.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9/10.
* Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* Improve readability of focused elements when they are also in an
* active/hover state.
*/
a:active,
a:hover {
outline: 0;
}
/* Text-level semantics
========================================================================== */
/**
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9/10.
*/
img {
border: 0;
}
/**
* Correct overflow not hidden in IE 9/10/11.
*/
svg:not(:root) {
overflow: hidden;
}
/* Grouping content
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari.
*/
figure {
margin: 1em 40px;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
box-sizing: content-box;
height: 0;
}
/**
* Contain overflow in all browsers.
*/
pre {
overflow: auto;
}
/**
* Address odd `em`-unit font size rendering in all browsers.
*/
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
/* Forms
========================================================================== */
/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/
/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
/**
* Address `overflow` set to `hidden` in IE 8/9/10/11.
*/
button {
overflow: visible;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
* Correct `select` style inheritance in Firefox.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
input {
line-height: normal;
}
/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
box-sizing: content-box; /* 2 */
}
/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9/10/11.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* Remove default vertical scrollbar in IE 8/9/10/11.
*/
textarea {
overflow: auto;
}
/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/
optgroup {
font-weight: bold;
}
/* Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 B

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

After

Width:  |  Height:  |  Size: 120 B

View File

@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<path fill="#a4c639" d="m 5.78125,2 c -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.010339,-0.00155 -0.020911,-0.00155 -0.03125,0 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 L 6.625,3.625 C 5.9445396,4.3022596 5.5134919,5.1886446 5.5,6.15625 l 9,0 C 14.486508,5.1886446 14.05546,4.3022596 13.375,3.625 L 14.25,2.15625 c 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 -0.0081,-0.012465 -0.01878,-0.023194 -0.03125,-0.03125 C 14.210694,2.0187849 14.199965,2.0080563 14.1875,2 c -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.0016,0.010339 -0.0016,0.020911 0,0.03125 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.0016,0.010339 -0.0016,0.020911 0,0.03125 L 13.21875,3.5 C 12.508811,2.8579404 11.574169,2.4161295 10.5,2.3125 l -1,0 C 8.4258309,2.4161295 7.4911892,2.8579404 6.78125,3.5 L 5.9375,2.0625 c 0.00155,-0.010339 0.00155,-0.020911 0,-0.03125 -0.010339,-0.00155 -0.020911,-0.00155 -0.03125,0 C 5.8981937,2.0187849 5.8874651,2.0080563 5.875,2 5.8646606,1.9984471 5.8540894,1.9984471 5.84375,2 5.8334106,1.9984471 5.8228394,1.9984471 5.8125,2 5.8021606,1.9984471 5.7915894,1.9984471 5.78125,2 z M 8,3.84375 c 0.020808,-0.00123 0.041692,-0.00123 0.0625,0 0.2933398,-0.043249 0.5943541,0.2102369 0.59375,0.5 C 8.6738727,4.6179758 8.4219324,4.8799872 8.140625,4.8799872 7.8593176,4.8799872 7.6073773,4.6179758 7.625,4.34375 7.6183882,4.1213788 7.7809375,3.9046463 8,3.84375 z m 3.84375,0 c 0.02081,-0.00123 0.04169,-0.00123 0.0625,0 0.29334,-0.043249 0.594354,0.2102369 0.59375,0.5 0.01762,0.2742258 -0.234318,0.5362372 -0.515625,0.5362372 -0.281307,0 -0.533248,-0.2620114 -0.515625,-0.5362372 -0.0066,-0.2223712 0.155938,-0.4391037 0.375,-0.5 z m -6.375,2.71875 c -2.995e-4,2.2008535 0,4.418486 0,6.625 0,0.698086 0.5327963,1.25 1.21875,1.25 l 0.0625,0 0,2.5625 c 0,0.553265 0.4467345,1 1,1 0.5532655,0 1,-0.446735 1,-1 l 0,-2.5625 2.5,0 0,2.5625 c 0,0.553265 0.446735,1 1,1 0.553265,0 1,-0.446735 1,-1 l 0,-2.5625 0.0625,0 c 0.68596,0 1.21875,-0.551914 1.21875,-1.25 10e-7,-2.205262 0,-4.4258583 0,-6.625 z m -1.625,0.59375 c -0.5532655,0 -1,0.4467345 -1,1 l 0,4.28125 c 0,0.553265 0.4467345,1 1,1 0.5532655,0 1,-0.446735 1,-1 l 0,-4.28125 c 0,-0.5532655 -0.4467345,-1 -1,-1 z m 12.3125,0 c -0.553265,0 -1,0.4467345 -1,1 l 0,4.28125 c 0,0.553265 0.446735,1 1,1 0.553265,0 1,-0.446735 1,-1 l 0,-4.28125 c 0,-0.5532655 -0.446735,-1 -1,-1 z"/>
<path fill="#a4c639" d="M14.5 3.2C14.4 3.2 14.2 3.3 14.1 3.5L13.3 5C12.3 4.4 11.2 4 10 4 8.8 4 7.7 4.3 6.8 4.9L5.9 3.5C5.8 3.3 5.6 3.2 5.5 3.3 5.4 3.3 5.4 3.2 5.3 3.3L5.2 3.3C5 3.5 4.9 3.8 5.1 4L6 5.6C4.8 6.7 4 8.2 4 10L16 10C16 8.3 15.3 6.7 14.1 5.6L15 4C15.1 3.8 15 3.5 14.8 3.3L14.7 3.3C14.7 3.2 14.6 3.2 14.5 3.2zM7.3 7C7.8 7 8.2 7.4 8.2 7.9 8.2 8.4 7.8 8.8 7.3 8.8 6.8 8.8 6.4 8.4 6.4 7.9 6.4 7.4 6.8 7 7.3 7zM12.7 7C13.2 7 13.6 7.4 13.6 7.9 13.6 8.4 13.2 8.8 12.7 8.8 12.2 8.8 11.8 8.4 11.8 7.9 11.8 7.4 12.2 7 12.7 7zM4 10.5L4 16 16 16 16 10.5 4 10.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 656 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<path fill="#795548" d="M18 9.9 17.3 9.5c0 0 0-0.1 0-0.1L17.9 8.8C17.9 8.8 18 8.6 18 8.5 18 8.4 17.9 8.4 17.9 8.4L17.1 8.1c0 0 0-0.1 0-0.1l0.4-0.7c0 0 0-0.1 0-0.3 0-0.1-0.1-0.1-0.1-0.1L16.5 6.7c0 0 0-0.1-0.1-0.1l0.3-0.7c0-0.1 0-0.1 0-0.3 0 0-0.1-0.1-0.1-0.1l-0.8 0c0 0-0.1-0.1-0.1-0.1L15.7 4.6c0-0.1 0-0.1 0-0.3 0 0-0.1-0.1-0.3 0l-0.8 0.1c0 0-0.1-0.1-0.1-0.1l0-0.8c0-0.1 0-0.1-0.1-0.1 0 0-0.1 0-0.3 0l-0.7 0.3c0 0-0.1 0-0.1-0.1L13.1 2.7c0-0.1 0-0.1-0.1-0.1-0.1 0-0.1 0-0.3 0l-0.7 0.4c0 0-0.1 0-0.1 0L11.6 2.3c0-0.1-0.1-0.1-0.1-0.1-0.1 0-0.1 0-0.3 0.1l-0.5 0.5c0 0-0.1 0-0.1 0L10.1 2.1C10.1 2 10 2 10 2 9.9 2 9.9 2 9.9 2.1l-0.4 0.7c0 0-0.1 0-0.1 0L8.8 2.3c0 0-0.1-0.1-0.3-0.1-0.1 0-0.1 0.1-0.1 0.1L8.1 2.9c0 0-0.1 0-0.1 0L7.3 2.5c0 0-0.1 0-0.3 0-0.1 0-0.1 0.1-0.1 0.1L6.7 3.5c0 0-0.1 0-0.1 0.1L5.9 3.4c-0.1 0-0.1 0-0.3 0 0 0-0.1 0.1-0.1 0.1l0 0.8c0 0-0.1 0.1-0.1 0.1L4.6 4.3c-0.1 0-0.1 0-0.3 0 0 0-0.1 0.1 0 0.3l0.1 0.8c0 0-0.1 0.1-0.1 0.1l-0.8 0c-0.1 0-0.1 0-0.1 0.1 0 0 0 0.1 0 0.3l0.3 0.7c0 0 0 0.1-0.1 0.1L2.7 6.9c-0.1 0-0.1 0-0.1 0.1 0 0.1 0 0.1 0 0.3l0.4 0.7c0 0 0 0.1 0 0.1L2.3 8.4c-0.1 0-0.1 0.1-0.1 0.1 0 0.1 0 0.1 0.1 0.3l0.5 0.5c0 0 0 0.1 0 0.1L2.1 9.9C2 9.9 2 10 2 10c0 0.1 0 0.1 0.1 0.1l0.7 0.4c0 0 0 0.1 0 0.1l-0.5 0.5c0 0-0.1 0.1-0.1 0.3 0 0.1 0.1 0.1 0.1 0.1l0.7 0.3c0 0 0 0.1 0 0.1l-0.4 0.7c0 0 0 0.1 0 0.3 0 0.1 0.1 0.1 0.1 0.1l0.8 0.1c0 0 0 0.1 0.1 0.1l-0.3 0.7c0 0.1 0 0.1 0 0.3 0 0 0.1 0.1 0.1 0.1l0.8 0c0 0 0.1 0.1 0.1 0.1l-0.1 0.8c0 0.1 0 0.1 0 0.3 0 0 0.1 0.1 0.3 0l0.8-0.1c0 0 0.1 0.1 0.1 0.1l0 0.8c0 0.1 0 0.1 0.1 0.1 0 0 0.1 0 0.3 0l0.7-0.3c0 0 0.1 0 0.1 0.1l0.1 0.8c0 0.1 0 0.1 0.1 0.1 0.1 0 0.1 0 0.3 0l0.7-0.4c0 0 0.1 0 0.1 0l0.3 0.7c0 0.1 0.1 0.1 0.1 0.1 0.1 0 0.1 0 0.3-0.1l0.5-0.5c0 0 0.1 0 0.1 0l0.4 0.7C9.9 17.9 10 18 10 18c0.1 0 0.1 0 0.1-0.1l0.4-0.7c0 0 0.1 0 0.1 0l0.5 0.5c0 0 0.1 0.1 0.3 0.1 0.1 0 0.1-0.1 0.1-0.1l0.3-0.7c0 0 0.1 0 0.1 0l0.7 0.4c0 0 0.1 0 0.3 0 0.1 0 0.1-0.1 0.1-0.1l0.1-0.8c0 0 0.1 0 0.1-0.1l0.7 0.3c0.1 0 0.1 0 0.3 0 0 0 0.1-0.1 0.1-0.1l0-0.8c0 0 0.1-0.1 0.1-0.1l0.8 0.1c0.1 0 0.1 0 0.3 0 0 0 0.1-0.1 0-0.3l-0.1-0.8c0 0 0.1-0.1 0.1-0.1l0.8 0c0.1 0 0.1 0 0.1-0.1 0 0 0-0.1 0-0.3l-0.3-0.7c0 0 0-0.1 0.1-0.1l0.8-0.1c0.1 0 0.1 0 0.1-0.1 0-0.1 0-0.1 0-0.3l-0.4-0.7c0 0 0-0.1 0-0.1l0.7-0.3c0.1 0 0.1-0.1 0.1-0.1 0-0.1 0-0.1-0.1-0.3l-0.5-0.5c0 0 0-0.1 0-0.1l0.7-0.4C18 10.1 18 10 18 10 18 9.9 18 9.9 17.9 9.9zm-4.5 5.6c-0.3 0-0.4-0.3-0.4-0.5 0-0.3 0.3-0.4 0.5-0.4 0.3 0 0.4 0.3 0.4 0.5 0 0.3-0.3 0.4-0.5 0.4zm-0.3-1.5c-0.3 0-0.4 0.1-0.5 0.3l-0.3 1.1C11.8 15.6 10.9 15.8 10 15.8c-0.8 0-1.8-0.1-2.4-0.5L7.3 14.2c0-0.3-0.3-0.4-0.5-0.3L5.8 14.2C5.7 13.9 5.5 13.7 5.4 13.5l4.7 0c0 0 0.1 0 0.1 0l0-1.6c0 0 0 0-0.1 0l-1.4 0 0-1.1 1.5 0c0.1 0 0.7 0 0.9 0.8 0 0.3 0.1 0.9 0.3 1.2 0.1 0.3 0.4 0.8 0.8 0.8l2.4 0c0 0 0 0 0.1 0-0.1 0.3-0.4 0.4-0.5 0.7l-1.1-0.4zm-6.6 1.5c-0.3 0-0.5-0.1-0.5-0.4 0-0.3 0.1-0.5 0.4-0.5 0.3 0 0.5 0.1 0.5 0.4 0 0.3-0.1 0.5-0.4 0.5zM4.8 8.1c0.1 0.3 0 0.5-0.3 0.7-0.3 0.1-0.5 0-0.7-0.3-0.1-0.3 0-0.5 0.3-0.7 0.3-0.1 0.5 0 0.7 0.3zM4.3 9.5 5.4 9.1C5.7 8.9 5.7 8.6 5.7 8.5l-0.3-0.5 0.8 0 0 3.8-1.6 0C4.4 11.2 4.3 10.7 4.3 10.1c0-0.3 0-0.4 0-0.7zm4.5-0.4 0-1.1 2 0c0.1 0 0.7 0.1 0.7 0.5 0 0.4-0.4 0.5-0.8 0.5l-1.8 0zM16 10c0 0.1 0 0.3 0 0.4l-0.5 0c0 0-0.1 0-0.1 0.1l0 0.3c0 0.7-0.4 0.8-0.7 0.8-0.3 0-0.7-0.1-0.7-0.3-0.1-0.9-0.5-1.2-0.9-1.6 0.5-0.4 1.2-0.9 1.2-1.6 0-0.8-0.5-1.4-0.9-1.5C12.7 6.2 12.2 6.2 12 6.2l-6.2 0C6.6 5.3 7.8 4.6 9.1 4.3l0.7 0.8c0.1 0.1 0.4 0.1 0.7 0l0.8-0.8c1.8 0.3 3.1 1.4 3.9 2.8l-0.5 1.2c-0.1 0.3 0 0.4 0.3 0.5l1.1 0.5c0 0.1 0 0.4 0 0.5zM9.7 3.6c0.1-0.1 0.5-0.1 0.7 0 0.1 0.1 0.1 0.5 0 0.7-0.1 0.1-0.5 0.1-0.7 0-0.1-0.1-0.1-0.5 0-0.7zm5.6 4.5C15.4 7.8 15.7 7.7 16 7.8 16.2 8 16.4 8.2 16.2 8.5 16.1 8.8 15.8 8.9 15.6 8.8 15.3 8.6 15.2 8.4 15.3 8.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -5,8 +5,12 @@ define('MIN_PHP_VERSION', '5.5.0');
if (!function_exists('version_compare') || version_compare(PHP_VERSION, MIN_PHP_VERSION, '<')) {
header('Content-type: text/plain;charset=utf-8');
echo '[err] h5ai requires PHP ' . MIN_PHP_VERSION . ' or later, but found PHP ' . PHP_VERSION;
exit;
exit('[ERR] h5ai requires PHP ' . MIN_PHP_VERSION . ' or later, but found PHP ' . PHP_VERSION);
}
if (substr(H5AI_VERSION, 0, 1) === '{') {
header('Content-type: text/plain;charset=utf-8');
exit('[ERR] h5ai sources must be preprocessed to work correctly');
}
require_once __DIR__ . '/../private/php/class-bootstrap.php';

View File

@@ -1,25 +0,0 @@
modulejs.define('boot', ['$', 'core/server'], function ($, server) {
var module = $('script[data-module]').data('module');
var data = {
action: 'get',
setup: true,
options: true,
types: true
};
if (module === 'index') {
data.theme = true;
data.langs = true;
} else if (module === 'info') {
data.refresh = true;
} else {
return;
}
server.request(data, function (config) {
modulejs.define('config', config);
$(function () {
modulejs.require('main/' + module);
});
});
});

View File

@@ -0,0 +1,5 @@
const {request} = require('./server');
const config = module.exports = {
_update: query => request(query).then(resp => Object.assign(config, resp))
};

View File

@@ -1,36 +1,28 @@
modulejs.define('core/event', ['_'], function (_) {
var slice = Array.prototype.slice;
var subscriptions = {};
const {isStr, isFn, dom} = require('../util');
function sub(topic, callback) {
if (_.isString(topic) && _.isFunction(callback)) {
const subscriptions = {};
const sub = (topic, listener) => {
if (isStr(topic) && isFn(listener)) {
if (!subscriptions[topic]) {
subscriptions[topic] = [];
}
subscriptions[topic].push(callback);
subscriptions[topic].push(listener);
}
}
function unsub(topic, callback) {
if (_.isString(topic) && _.isFunction(callback) && subscriptions[topic]) {
subscriptions[topic] = _.without(subscriptions[topic], callback);
}
}
function pub(topic) {
var args = slice.call(arguments, 1);
if (_.isString(topic) && subscriptions[topic]) {
_.each(subscriptions[topic], function (callback) {
callback.apply(topic, args);
});
}
}
return {
sub: sub,
unsub: unsub,
pub: pub
};
const pub = (topic, ...args) => {
// console.log(topic, args);
if (isStr(topic) && subscriptions[topic]) {
subscriptions[topic].forEach(listener => {
listener.apply(topic, args);
});
}
};
dom(global.window).on('resize', () => pub('resize'));
module.exports = {
sub,
pub
};

View File

@@ -1,16 +1,18 @@
modulejs.define('core/format', ['_'], function (_) {
var decimalMetric = {
const {isNum} = require('../util');
const decimalMetric = {
t: 1000.0,
k: 1000.0,
u: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
};
var binaryMetric = {
const binaryMetric = {
t: 1024.0,
k: 1024.0,
u: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
};
var defaultMetric = decimalMetric;
var datePatterns = [
let defaultMetric = decimalMetric;
const datePatterns = [
[/YYYY/, 'Y', 4],
[/YY/, 'Y', 2],
[/Y/, 'Y', 0],
@@ -25,51 +27,51 @@ modulejs.define('core/format', ['_'], function (_) {
[/ss/, 's', 2],
[/s/, 's', 0]
];
var defaultDateFormat = 'YYYY-MM-DD HH:mm';
let defaultDateFormat = 'YYYY-MM-DD HH:mm';
function setDefaultMetric(useBinaryMetric) {
const setDefaultMetric = useBinaryMetric => {
defaultMetric = useBinaryMetric ? binaryMetric : decimalMetric;
}
};
function formatSize(size, metric) {
const formatSize = (size, metric) => {
metric = metric || defaultMetric;
if (!_.isNumber(size) || size < 0) {
if (!isNum(size) || size < 0) {
return '';
}
var i = 0;
var maxI = metric.u.length - 1;
let i = 0;
const maxI = metric.u.length - 1;
while (size >= metric.t && i < maxI) {
size /= metric.k;
i += 1;
}
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + metric.u[i];
}
};
function setDefaultDateFormat(dateFormat) {
const setDefaultDateFormat = dateFormat => {
defaultDateFormat = dateFormat;
}
};
function formatNumber(number, padding) {
var str = String(number);
const formatNumber = (number, padding) => {
let str = String(number);
if (padding) {
str = ('000' + str).substr(-padding);
}
return str;
}
};
function formatDate(millis, format) {
if (!millis || !_.isNumber(millis)) {
const formatDate = (millis, format) => {
if (!millis || !isNum(millis)) {
return '';
}
format = format || defaultDateFormat;
var date = new Date(millis);
var d = {
const date = new Date(millis);
const d = {
Y: date.getFullYear(),
M: date.getMonth() + 1,
D: date.getDate(),
@@ -78,18 +80,17 @@ modulejs.define('core/format', ['_'], function (_) {
s: date.getSeconds()
};
datePatterns.forEach(function (pattern) {
datePatterns.forEach(pattern => {
format = format.replace(pattern[0], formatNumber(d[pattern[1]], pattern[2]));
});
return format;
}
return {
setDefaultMetric: setDefaultMetric,
formatSize: formatSize,
setDefaultDateFormat: setDefaultDateFormat,
formatDate: formatDate
};
});
module.exports = {
setDefaultMetric,
formatSize,
setDefaultDateFormat,
formatDate
};

View File

@@ -1,3 +1,2 @@
modulejs.define('core/langs', ['_', 'config'], function (_, config) {
return _.extend({}, config.langs);
});
const {langs} = require('../config');
module.exports = Object.assign({}, langs);

View File

@@ -1,13 +1,18 @@
modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/settings', 'view/notification'], function (_, event, modernizr, allsettings, notification) {
var settings = _.extend({
const {each, values, difference} = require('../util');
const {request} = require('../server');
const allsettings = require('./settings');
const event = require('./event');
const notification = require('../view/notification');
const win = global.window;
const doc = win.document;
const settings = Object.assign({
fastBrowsing: true,
unmanagedInNewWindow: true
}, allsettings.view);
var doc = document;
var history = settings.fastBrowsing && modernizr.history ? window.history : null;
var reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
var absHref = null;
var reForceEncoding = [
const history = settings.fastBrowsing ? win.history : null;
const reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
const reForceEncoding = [
[/\/+/g, '/'],
[/ /g, '%20'],
[/!/g, '%21'],
@@ -29,27 +34,31 @@ modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/set
[/\]/g, '%5D']
];
function forceEncoding(href) {
return reForceEncoding.reduce(function (nuHref, data) {
let absHref = null;
const forceEncoding = href => {
return reForceEncoding.reduce((nuHref, data) => {
return nuHref.replace(data[0], data[1]);
}, href);
}
};
function uriToPathname(uri) {
const uriToPathname = uri => {
return uri.replace(reUriToPathname, '');
}
};
var hrefsAreDecoded = (function () {
var testpathname = '/a b';
var a = doc.createElement('a');
const hrefsAreDecoded = (() => {
const testpathname = '/a b';
const a = doc.createElement('a');
a.href = testpathname;
return uriToPathname(a.href) === testpathname;
}());
})();
function encodedHref(href) {
var a = doc.createElement('a');
var location;
const encodedHref = href => {
const a = doc.createElement('a');
let location;
a.href = href;
location = uriToPathname(a.href);
@@ -59,61 +68,52 @@ modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/set
}
return forceEncoding(location);
}
};
function getDomain() {
return doc.domain;
}
const getDomain = () => doc.domain;
const getAbsHref = () => absHref;
const getItem = () => require('../model/item').get(absHref);
function getAbsHref() {
return absHref;
}
function getItem() {
return modulejs.require('model/item').get(absHref);
}
function load(callback) {
modulejs.require('core/server').request({action: 'get', items: {href: absHref, what: 1}}, function (json) {
var Item = modulejs.require('model/item');
var item = Item.get(absHref);
const load = () => {
return request({action: 'get', items: {href: absHref, what: 1}}).then(json => {
const Item = require('../model/item');
const item = Item.get(absHref);
if (json) {
var found = {};
const found = {};
_.each(json.items, function (jsonItem) {
var e = Item.get(jsonItem);
each(json.items, jsonItem => {
const e = Item.get(jsonItem);
found[e.absHref] = true;
});
_.each(item.content, function (e) {
each(item.content, e => {
if (!found[e.absHref]) {
Item.remove(e.absHref);
}
});
}
if (_.isFunction(callback)) {
callback(item);
}
});
}
function refresh() {
var item = getItem();
var oldItems = _.values(item.content);
return item;
});
};
const refresh = () => {
const item = getItem();
const oldItems = values(item.content);
event.pub('location.beforeRefresh');
load(function () {
var newItems = _.values(item.content);
var added = _.difference(newItems, oldItems);
var removed = _.difference(oldItems, newItems);
load().then(() => {
const newItems = values(item.content);
const added = difference(newItems, oldItems);
const removed = difference(oldItems, newItems);
event.pub('location.refreshed', item, added, removed);
});
}
};
function setLocation(newAbsHref, keepBrowserUrl) {
const setLocation = (newAbsHref, keepBrowserUrl) => {
event.pub('location.beforeChange');
newAbsHref = encodedHref(newAbsHref);
@@ -123,33 +123,34 @@ modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/set
if (history) {
if (keepBrowserUrl) {
history.replaceState({absHref: absHref}, '', absHref);
history.replaceState({absHref}, '', absHref);
} else {
history.pushState({absHref: absHref}, '', absHref);
history.pushState({absHref}, '', absHref);
}
}
}
var item = getItem();
const item = getItem();
if (item.isLoaded) {
event.pub('location.changed', item);
refresh();
} else {
notification.set('loading...');
load(function () {
load().then(() => {
item.isLoaded = true;
notification.set();
event.pub('location.changed', item);
});
}
}
};
function setLink($el, item) {
const setLink = ($el, item) => {
$el.attr('href', item.absHref);
if (history && item.isFolder() && item.isManaged) {
$el.on('click', function () {
$el.on('click', ev => {
setLocation(item.absHref);
ev.preventDefault();
return false;
});
}
@@ -157,25 +158,24 @@ modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/set
if (settings.unmanagedInNewWindow && !item.isManaged) {
$el.attr('target', '_blank');
}
}
};
function onPopState(ev) {
const onPopState = ev => {
if (ev.state && ev.state.absHref) {
setLocation(ev.state.absHref, true);
}
}
window.onpopstate = history ? onPopState : null;
return {
forceEncoding: forceEncoding,
getDomain: getDomain,
getAbsHref: getAbsHref,
getItem: getItem,
setLocation: setLocation,
refresh: refresh,
setLink: setLink
};
});
win.onpopstate = history ? onPopState : null;
module.exports = {
forceEncoding,
getDomain,
getAbsHref,
getItem,
setLocation,
refresh,
setLink
};

View File

@@ -1,25 +0,0 @@
modulejs.define('core/modernizr', function () {
var hasCanvas = (function () {
var elem = document.createElement('canvas');
return Boolean(elem.getContext && elem.getContext('2d'));
}());
var hasHistory = Boolean(window.history && history.pushState);
var hasLocalStorage = (function () {
var key = '#test#';
try {
localStorage.setItem(key, key);
localStorage.removeItem(key);
return true;
} catch (e) {
return false;
}
}());
return {
canvas: hasCanvas,
history: hasHistory,
localstorage: hasLocalStorage
};
});

View File

@@ -1,37 +1,37 @@
modulejs.define('core/resource', ['_', 'config', 'core/settings'], function (_, config, settings) {
var imagesHref = settings.publicHref + 'images/';
var uiHref = imagesHref + 'ui/';
var themesHref = imagesHref + 'themes/';
var defaultThemeHref = themesHref + 'default/';
var defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
const {includes} = require('../util');
const config = require('../config');
const settings = require('./settings');
const imagesHref = settings.publicHref + 'images/';
const uiHref = imagesHref + 'ui/';
const themesHref = imagesHref + 'themes/';
const defaultThemeHref = themesHref + 'default/';
const defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
function image(id) {
return uiHref + id + '.svg';
}
const image = id => uiHref + id + '.svg';
function icon(id) {
var baseId = (id || '').split('-')[0];
var href = config.theme[id] || config.theme[baseId];
const icon = id => {
const baseId = (id || '').split('-')[0];
const href = config.theme[id] || config.theme[baseId];
if (href) {
return themesHref + href;
}
if (_.indexOf(defaultIcons, id) >= 0) {
if (includes(defaultIcons, id)) {
return defaultThemeHref + id + '.svg';
}
if (_.indexOf(defaultIcons, baseId) >= 0) {
if (includes(defaultIcons, baseId)) {
return defaultThemeHref + baseId + '.svg';
}
return defaultThemeHref + 'file.svg';
}
return {
image: image,
icon: icon
};
});
module.exports = {
image,
icon
};

View File

@@ -1,35 +0,0 @@
modulejs.define('core/server', ['_', '$'], function (_, $) {
function request(data, callback) {
$.ajax({
url: '?',
data: data,
type: 'post',
dataType: 'json'
})
.done(function (json) {
callback(json);
})
.fail(function () {
callback();
});
}
function formRequest(data) {
var $form = $('<form method="post" action="?" style="display:none;"/>');
_.each(data, function (val, key) {
$('<input type="hidden"/>')
.attr('name', key)
.attr('value', val)
.appendTo($form);
});
$form.appendTo('body').submit().remove();
}
return {
request: request,
formRequest: formRequest
};
});

View File

@@ -1,6 +1,6 @@
modulejs.define('core/settings', ['_', 'config'], function (_, config) {
return _.extend({}, config.options, {
const config = require('../config');
module.exports = Object.assign({}, config.options, {
publicHref: config.setup.PUBLIC_HREF,
rootHref: config.setup.ROOT_HREF
});
});

View File

@@ -1,32 +1,28 @@
modulejs.define('core/store', ['core/modernizr'], function (modernizr) {
var store = modernizr.localstorage ? window.localStorage : {};
var storekey = '_h5ai';
const store = global.window.localStorage;
const storekey = '_h5ai';
function load() {
const load = () => {
try {
return JSON.parse(store[storekey]);
} catch (e) {/* skip */}
return {};
}
};
function save(obj) {
const save = obj => {
store[storekey] = JSON.stringify(obj);
}
};
function put(key, value) {
var obj = load();
const put = (key, value) => {
const obj = load();
obj[key] = value;
save(obj);
}
function get(key) {
return load()[key];
}
return {
put: put,
get: get
};
});
const get = key => load()[key];
module.exports = {
put,
get
};

View File

@@ -1,43 +1,43 @@
modulejs.define('core/types', ['_', 'config'], function (_, config) {
var reEndsWithSlash = /\/$/;
var regexps = {};
const {each, map} = require('../util');
const config = require('../config');
const reEndsWithSlash = /\/$/;
const regexps = {};
function escapeRegExp(sequence) {
const escapeRegExp = sequence => {
return sequence.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$]/g, '\\$&');
// return sequence.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}
};
function parse(types) {
_.each(types, function (patterns, type) {
var pattern = '^(' + _.map(patterns, function (p) { return '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')'; }).join('|') + ')$';
const parse = types => {
each(types, (patterns, type) => {
const pattern = '^(' + map(patterns, p => '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')').join('|') + ')$';
regexps[type] = new RegExp(pattern, 'i');
});
}
};
function getType(sequence) {
const getType = sequence => {
if (reEndsWithSlash.test(sequence)) {
return 'folder';
}
var slashidx = sequence.lastIndexOf('/');
var name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
var result;
const slashidx = sequence.lastIndexOf('/');
const name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
let result;
_.each(regexps, function (regexp, type) {
each(regexps, (regexp, type) => {
if (regexps[type].test(name)) {
result = type;
return false;
}
});
return result ? result : 'file';
}
parse(_.extend({}, config.types));
return {
getType: getType
};
});
parse(Object.assign({}, config.types));
module.exports = {
getType
};

View File

@@ -1,93 +0,0 @@
modulejs.define('core/util', ['_'], function (_) {
function regularCmpFn(val1, val2) {
if (val1 < val2) {
return -1;
}
if (val1 > val2) {
return 1;
}
return 0;
}
// Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
// Author: Jim Palmer (based on chunking idea from Dave Koelle)
//
// Modified to make it work with h5ai
function naturalCmpFn(val1, val2) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
var sre = /(^[ ]*|[ ]*$)/g;
var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
var hre = /^0x[0-9a-f]+$/i;
var ore = /^0/;
// convert all to strings strip whitespace
var x = String(val1).replace(sre, '');
var y = String(val2).replace(sre, '');
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
var yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
// numeric, hex or date detection
var xD = parseInt(x.match(hre), 10) || xN.length !== 1 && x.match(dre) && Date.parse(x);
var yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
var oFxNcL;
var oFyNcL;
// first try and sort Hex codes or Dates
if (yD) {
if (xD < yD) {
return -1;
} else if (xD > yD) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
return isNaN(oFxNcL) ? 1 : -1;
} else if (typeof oFxNcL !== typeof oFyNcL) {
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
function escapePattern(sequence) {
return sequence.replace(/[\-\[\]{}()*+?.,\\$\^|#\s]/g, '\\$&');
}
function parsePattern(sequence, advanced) {
if (!advanced) {
return escapePattern(sequence);
}
if (sequence.substr(0, 3) === 're:') {
return sequence.substr(3);
}
sequence = _.map(_.trim(sequence).split(/\s+/), function (part) {
return _.map(part.split(''), function (character) {
return escapePattern(character);
}).join('.*?');
}).join('|');
return sequence;
}
return {
regularCmpFn: regularCmpFn,
naturalCmpFn: naturalCmpFn,
escapePattern: escapePattern,
parsePattern: parsePattern
};
});

View File

@@ -1,25 +1,29 @@
modulejs.define('ext/autorefresh', ['_', '$', 'core/event', 'core/location', 'core/settings'], function (_, $, event, location, allsettings) {
var settings = _.extend({
const event = require('../core/event');
const location = require('../core/location');
const allsettings = require('../core/settings');
const win = global.window;
const settings = Object.assign({
enabled: false,
interval: 5000
}, allsettings.autorefresh);
var timeoutId = null;
let timeoutId = null;
function heartbeat() {
const heartbeat = () => {
location.refresh();
}
};
function before() {
clearTimeout(timeoutId);
}
const before = () => {
win.clearTimeout(timeoutId);
};
function after() {
clearTimeout(timeoutId);
timeoutId = setTimeout(heartbeat, settings.interval);
}
const after = () => {
win.clearTimeout(timeoutId);
timeoutId = win.setTimeout(heartbeat, settings.interval);
};
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
@@ -30,8 +34,7 @@ modulejs.define('ext/autorefresh', ['_', '$', 'core/event', 'core/location', 'co
event.sub('location.beforeRefresh', before);
event.sub('location.changed', after);
event.sub('location.refreshed', after);
}
};
init();
});

View File

@@ -1,61 +1,72 @@
modulejs.define('ext/contextmenu', ['_', '$', 'core/resource', 'core/settings'], function (_, $, resource, allsettings) {
var settings = _.extend({
const {each, dom} = require('../util');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const settings = Object.assign({
enabled: false
}, allsettings.contextmenu);
var templateOverlay = '<div id="cm-overlay"/>';
var templatePanel = '<div class="cm-panel"><ul/></div>';
var templateSep = '<li class="cm-sep"/>';
var templateEntry = '<li class="cm-entry"><span class="cm-icon"><img/></span><span class="cm-text"/></li>';
var templateLabel = '<li class="cm-label"><span class="cm-text"/></li>';
const overlayTpl = '<div id="cm-overlay"></div>';
const panelTpl = '<div class="cm-panel"><ul></ul></div>';
const sepTpl = '<li class="cm-sep"></li>';
const entryTpl = '<li class="cm-entry"><span class="cm-icon"><img/></span><span class="cm-text"></span></li>';
const labelTpl = '<li class="cm-label"><span class="cm-text"></span></li>';
function createOverlay(callback) {
var $overlay = $(templateOverlay);
const closestId = el => {
while (!el._cmId && el.parentNode) {
el = el.parentNode;
}
return el._cmId;
};
$overlay
.on('click contextmenu', function (ev) {
const createOverlay = callback => {
const $overlay = dom(overlayTpl);
const handle = ev => {
ev.stopPropagation();
ev.preventDefault();
var cmId = $(ev.target).closest('.cm-entry').data('cm-id');
const cmId = closestId(ev.target);
if (ev.target === $overlay[0] || cmId !== undefined) {
$overlay.remove();
$overlay.rm();
callback(cmId);
}
});
};
return $overlay;
}
return $overlay
.on('contextmenu', handle)
.on('click', handle);
};
function createPanel(menu) {
var $panel = $(templatePanel);
var $ul = $panel.find('ul');
var $li;
const createPanel = menu => {
const $panel = dom(panelTpl);
const $ul = $panel.find('ul');
let $li;
_.each(menu, function (entry) {
each(menu, entry => {
if (entry.type === '-') {
$(templateSep).appendTo($ul);
dom(sepTpl).appTo($ul);
} else if (entry.type === 'l') {
$(templateLabel).appendTo($ul)
dom(labelTpl).appTo($ul)
.find('.cm-text').text(entry.text);
} else if (entry.type === 'e') {
$li = $(templateEntry).appendTo($ul);
$li.data('cm-id', entry.id);
$li = dom(entryTpl).appTo($ul);
$li[0]._cmId = entry.id;
$li.find('.cm-text').text(entry.text);
if (entry.icon) {
$li.find('.cm-icon img').attr('src', resource.icon(entry.icon));
} else {
$li.find('.cm-icon').addClass('no-icon');
$li.find('.cm-icon').addCls('no-icon');
}
}
});
return $panel;
}
};
function positionPanel($overlay, $panel, x, y) {
var margin = 4;
const positionPanel = ($overlay, $panel, x, y) => {
const margin = 4;
$panel.css({
left: 0,
@@ -64,20 +75,19 @@ modulejs.define('ext/contextmenu', ['_', '$', 'core/resource', 'core/settings'],
});
$overlay.show();
var overlayOffset = $overlay.offset();
var overlayLeft = overlayOffset.left;
var overlayTop = overlayOffset.top;
var overlayWidth = $overlay.outerWidth(true);
var overlayHeight = $overlay.outerHeight(true);
const or = $overlay[0].getBoundingClientRect();
const pr = $panel[0].getBoundingClientRect();
// var panelOffset = $panel.offset();
// var panelLeft = panelOffset.left;
// var panelTop = panelOffset.top;
var panelWidth = $panel.outerWidth(true);
var panelHeight = $panel.outerHeight(true);
const overlayLeft = or.left;
const overlayTop = or.top;
const overlayWidth = or.width;
const overlayHeight = or.height;
var posLeft = x;
var posTop = y;
let panelWidth = pr.width;
let panelHeight = pr.height;
let posLeft = x;
let posTop = y;
if (panelWidth > overlayWidth - 2 * margin) {
posLeft = margin;
@@ -106,58 +116,42 @@ modulejs.define('ext/contextmenu', ['_', '$', 'core/resource', 'core/settings'],
}
$panel.css({
left: posLeft,
top: posTop,
width: panelWidth,
height: panelHeight,
left: posLeft + 'px',
top: posTop + 'px',
width: panelWidth + 'px',
height: panelHeight + 'px',
opacity: 1
});
}
};
function showMenuAt(x, y, menu, callback) {
var $overlay = createOverlay(callback);
var $panel = createPanel(menu);
$overlay.append($panel).appendTo('body');
const showMenuAt = (x, y, menu, callback) => {
const $overlay = createOverlay(callback);
const $panel = createPanel(menu);
$overlay.hide().app($panel).appTo('body');
positionPanel($overlay, $panel, x, y);
}
};
function init() {
// settings.enabled = true;
const init = () => {
if (!settings.enabled) {
return;
}
$(document).on('contextmenu', function (ev) {
ev.stopPropagation();
const menu = [
{type: 'e', id: 'e1', text: 'testing context menus'},
{type: 'e', id: 'e2', text: 'another entry'},
{type: 'e', id: 'e3', text: 'one with icon', icon: 'folder'},
{type: '-'},
{type: 'e', id: 'e4', text: 'one with icon', icon: 'x'},
{type: 'e', id: 'e5', text: 'one with icon', icon: 'img'}
];
dom('#view').on('contextmenu', ev => {
ev.preventDefault();
$(ev.target).trigger($.Event('h5ai-contextmenu', {
originalEvent: ev,
showMenu: function (menu, callback) {
showMenuAt(ev.pageX, ev.pageY, menu, callback);
}
}));
// showMenuAt(ev.pageX, ev.pageY, menu, res => console.log('>> CB-RESULT >> ' + res));
showMenuAt(ev.pageX, ev.pageY, menu);
});
// var menu = [
// {type: 'e', id: 'e1', text: 'testing context menus'},
// {type: 'e', id: 'e2', text: 'another entry'},
// {type: 'e', id: 'e3', text: 'one with icon', icon: 'folder'},
// {type: '-'},
// {type: 'e', id: 'e4', text: 'one with icon', icon: 'x'},
// {type: 'e', id: 'e5', text: 'one with icon', icon: 'img'}
// ];
// var callback = function (res) {
// window.console.log('>> CB-RESULT >> ' + res);
// };
// $(document).on('h5ai-contextmenu', '#items .item.folder', function (ev) {
// window.console.log('CM', ev);
// ev.showMenu(menu, callback);
// });
}
};
init();
});

View File

@@ -1,58 +1,68 @@
modulejs.define('ext/crumb', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/settings', 'view/topbar'], function (_, $, event, location, resource, allsettings, topbar) {
var settings = _.extend({
const {each, dom} = require('../util');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const base = require('../view/base');
const settings = Object.assign({
enabled: false
}, allsettings.crumb);
var crumbTemplate =
'<a class="crumb">' +
'<img class="sep" src="' + resource.image('crumb') + '" alt=">"/>' +
'<span class="label"/>' +
'</a>';
var pageHintTemplate = '<img class="hint" src="' + resource.icon('folder-page') + '" alt="has index page"/>';
var $crumbbar;
const crumbbarTpl = '<div id="crumbbar"></div>';
const crumbTpl =
`<a class="crumb">
<img class="sep" src="${resource.image('crumb')}" alt=">"/>
<span class="label"></span>
</a>`;
const pageHintTpl =
`<img class="hint" src="${resource.icon('folder-page')}" alt="has index page"/>`;
function createHtml(item) {
var $html = $(crumbTemplate).data('item', item);
item.$crumb = $html;
const createHtml = item => {
const $html = dom(crumbTpl);
location.setLink($html, item);
$html.find('.label').text(item.label);
if (item.isCurrentFolder()) {
$html.addClass('active');
$html.addCls('active');
}
if (!item.isManaged) {
$html.append($(pageHintTemplate));
$html.app(dom(pageHintTpl));
}
item._$crumb = $html;
$html[0]._item = item;
return $html;
}
};
function onLocationChanged(item) {
var $crumb = item.$crumb;
const onLocationChanged = item => {
const $crumb = item._$crumb;
const $crumbbar = dom('#crumbbar');
if ($crumb && $crumb.parent()[0] === $crumbbar[0]) {
$crumbbar.children().removeClass('active');
$crumb.addClass('active');
$crumbbar.children().rmCls('active');
$crumb.addCls('active');
} else {
$crumbbar.empty();
_.each(item.getCrumb(), function (crumbItem) {
$crumbbar.append(createHtml(crumbItem));
$crumbbar.clr();
each(item.getCrumb(), crumbItem => {
$crumbbar.app(createHtml(crumbItem));
});
}
}
};
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
$crumbbar = $('<div id="crumbbar"/>').appendTo(topbar.$flowbar);
dom(crumbbarTpl).appTo(base.$flowbar);
event.sub('location.changed', onLocationChanged);
}
};
init();
});

View File

@@ -1,62 +1,45 @@
modulejs.define('ext/custom', ['_', '$', 'marked', 'core/event', 'core/server', 'core/settings'], function (_, $, marked, event, server, allsettings) {
var settings = _.extend({
const marked = require('marked');
const {each, dom} = require('../util');
const server = require('../server');
const event = require('../core/event');
const allsettings = require('../core/settings');
const settings = Object.assign({
enabled: false
}, allsettings.custom);
var $header;
var $footer;
var duration = 200;
const update = (data, key) => {
const $el = dom(`#content-${key}`);
function onLocationChanged(item) {
server.request({action: 'get', custom: item.absHref}, function (response) {
var custom = response && response.custom;
var hasHeader;
var hasFooter;
if (custom) {
var header = custom.header;
var footer = custom.footer;
var content;
if (header.content) {
content = header.content;
if (header.type === 'md') {
if (data && data[key].content) {
let content = data[key].content;
if (data[key].type === 'md') {
content = marked(content);
}
$header.html(content).stop().slideDown(duration);
hasHeader = true;
$el.html(content).show();
} else {
$el.hide();
}
};
if (footer.content) {
content = footer.content;
if (footer.type === 'md') {
content = marked(content);
}
$footer.html(content).stop().slideDown(duration);
hasFooter = true;
}
}
if (!hasHeader) {
$header.stop().slideUp(duration);
}
if (!hasFooter) {
$footer.stop().slideUp(duration);
}
const onLocationChanged = item => {
server.request({action: 'get', custom: item.absHref}).then(response => {
const data = response && response.custom;
each(['header', 'footer'], key => update(data, key));
});
}
};
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
$header = $('<div id="content-header"/>').hide().prependTo('#content');
$footer = $('<div id="content-footer"/>').hide().appendTo('#content');
dom('<div id="content-header"></div>').hide().preTo('#content');
dom('<div id="content-footer"></div>').hide().appTo('#content');
event.sub('location.changed', onLocationChanged);
}
};
init();
});

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