Version Description
(pre-released: 15 Nov 2021) * Changed names for preventing replacing image with webp. Use "?dontreplace" / ".dontreplace" instead of "?original" and ".do-not-convert". The old ones are deprecated, but will still work (for a while) * You can now convert images in the file manager and view conversion log * The new file manager UI is now available in multisite too * Changed names for the escape hatches that was introduced in 0.22. Use "?dontreplace" and ".dontreplace" rather than "?original" and ".do-not-convert". The old names still works * Added message to users that have the Elementor plugin installed on how to configure Elementor to inline CSS in order for Alter HTML to be able to replace image URLs (only displayed when relevant) * Added UI for "skip-these-precompiled-binaries" cwebp option. Thanks to @madmax4ever for posting code for this. * Bumped dom-util-for-webp library to 0.5 * Bugfix: In multisite, Alter HTML produced wrong webp urls when destination structure was set to "image roots". Thanks to John A. Huebner II (@hube2) who lives on a big hill in central NY, USA for reporting the issue. * Bugfix: One of the newly introduced escape hatches didn't work in Alter HTML.
For more info, see the closed issues on the webp-express 0.23 milestone
Release Info
Developer | rosell.dk |
Plugin | WebP Express |
Version | 0.23.0 |
Comparing to | |
See all releases |
Code changes from version 0.22.1 to 0.23.0
- README.md +2 -0
- README.txt +26 -4
- changelog.txt +14 -0
- composer.json +1 -1
- docs/development.md +70 -0
- docs/publishing.md +3 -3
- lib/classes/AdminInit.php +8 -3
- lib/classes/AdminUi.php +29 -0
- lib/classes/AlterHtmlHelper.php +34 -9
- lib/classes/Config.php +4 -0
- lib/classes/Convert.php +3 -1
- lib/classes/ConvertHelperIndependent.php +1 -1
- lib/classes/DestinationUrl.php +1 -1
- lib/classes/HTAccess.php +10 -2
- lib/classes/HTAccessRules.php +12 -2
- lib/classes/Paths.php +8 -36
- lib/classes/PluginActivate.php +0 -9
- lib/classes/TestRun.php +44 -1
- lib/classes/WCFMApi.php +79 -22
- lib/classes/WCFMPage.php +3 -8
- lib/dismissable-messages/0.23.0/elementor.php +34 -0
- lib/options/css/webp-express-options-page.css +8 -1
- lib/options/enqueue_scripts.php +6 -2
- lib/options/js/{0.19.0/authorized_sites_bak.js → authorized_sites_bak.js} +0 -0
- lib/options/js/{0.19.0/bulk-convert.js → bulk-convert.js} +0 -0
- lib/options/js/{0.19.0/converters.js → converters.js} +44 -14
- lib/options/js/{0.19.0/das-popup.js → das-popup.js} +0 -0
- lib/options/js/{0.19.0/escapeHTML.js → escapeHTML.js} +0 -0
- lib/options/js/{0.19.0/image-comparison-slider.js → image-comparison-slider.js} +0 -0
- lib/options/js/{0.19.0/page.js → page.js} +0 -0
- lib/options/js/{0.19.0/purge-cache.js → purge-cache.js} +0 -0
- lib/options/js/{0.19.0/purge-log.js → purge-log.js} +0 -0
- lib/options/js/{0.19.0/self-test.js → self-test.js} +0 -0
- lib/options/js/{0.19.0/sortable.min.js → sortable.min.js} +0 -0
- lib/options/js/{0.19.0/test-convert.js → test-convert.js} +0 -0
- lib/options/js/{0.19.0/whitelist.js → whitelist.js} +0 -0
- lib/options/options/conversion-options/converter-options/cwebp.php +7 -1
- lib/options/options/redirection-rules/redirection-rules.inc +1 -1
- lib/options/page-messages.php +16 -0
- lib/options/submit.php +2 -1
- lib/wcfm/index.659b742a.css +1 -0
- lib/wcfm/index.ab43bb2c.css +0 -1
- lib/wcfm/index.ee44cdbf.js +29 -0
- lib/wcfm/index.f8d1bd25.js +0 -27
- vendor/composer/autoload_classmap.php +1 -0
- vendor/composer/autoload_namespaces.php +1 -0
- vendor/composer/autoload_static.php +12 -0
- vendor/composer/installed.json +63 -7
- vendor/composer/installed.php +14 -5
- vendor/kub-at/php-simple-html-dom-parser/CONTRIBUTING.md +3 -0
- vendor/kub-at/php-simple-html-dom-parser/LICENSE +21 -0
- vendor/kub-at/php-simple-html-dom-parser/README.md +29 -0
- vendor/kub-at/php-simple-html-dom-parser/composer.json +24 -0
- vendor/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/HtmlDomParser.php +16 -0
- vendor/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/lib/simple_html_dom.php +2355 -0
- vendor/rosell-dk/dom-util-for-webp/README.md +1 -1
- vendor/rosell-dk/dom-util-for-webp/composer.json +3 -0
- vendor/rosell-dk/dom-util-for-webp/phpstan.neon +3 -0
- vendor/rosell-dk/dom-util-for-webp/src-vendor/simple_html_dom/simple_html_dom.inc +0 -2930
- vendor/rosell-dk/dom-util-for-webp/src/ImageUrlReplacer.php +6 -4
- vendor/rosell-dk/dom-util-for-webp/src/PictureTags.php +6 -4
- webp-express.php +1 -1
@@ -709,6 +709,8 @@ The current milestones, their subtasks and their progress can be viewed here: ht
|
|
709 |
|
710 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
711 |
|
|
|
|
|
712 |
|
713 |
## Changes in 0.21.1
|
714 |
*(released: 27 Oct 2021)*
|
709 |
|
710 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
711 |
|
712 |
+
### Beta testing
|
713 |
+
I generally create a pre-release before publishing. If you [follow me on ko-fi](https://ko-fi.com/rosell), you will get notified when a pre-release is available. I generally create a pre-release on fridays and mark it as stable on mondays. In order to download a pre-release, go to [the advanced page](https://wordpress.org/plugins/webp-express/advanced/) and scroll down to "Please select a specific version to download". I don't name the pre-releases different. You will just see the next version here before it is available the usual way.
|
714 |
|
715 |
## Changes in 0.21.1
|
716 |
*(released: 27 Oct 2021)*
|
@@ -4,7 +4,7 @@ Donate link: https://ko-fi.com/rosell
|
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.8
|
7 |
-
Stable tag: 0.
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
@@ -175,10 +175,10 @@ Bread on the table don't come for free, even though this plugin does, and always
|
|
175 |
* Ruben Solvang
|
176 |
|
177 |
**Persons who recently contributed with [ko-fi](https://ko-fi.com/rosell) - Thanks!**
|
|
|
178 |
* 9 Nov: @utrenkner
|
179 |
* 26 Oct: Anonymous
|
180 |
* 29 Aug: Pawa Tecnologia
|
181 |
-
* 29 Jul: Brian Laursen
|
182 |
|
183 |
**Persons who contributed with extra generously amounts of coffee / lifetime backing (>30$) - thanks!:**
|
184 |
|
@@ -722,11 +722,13 @@ I have only tested the above in *Varied image responses* mode, but it should als
|
|
722 |
There can be instances where you actually need to serve a jpeg or png. For example if you are demonstrating how a jpeg looks using some compression settings.
|
723 |
|
724 |
If you want an image to be served in the original format (jpeg og png), do one of the following things:
|
725 |
-
- Add "?
|
726 |
-
- Place an empty file in the same folder as the jpeg/png. The file name must be the same as the jpeg/png with ".
|
727 |
|
728 |
Doing this will bypass redirection to webp and also prevent Alter HTML to use the webp instead of the original.
|
729 |
|
|
|
|
|
730 |
*Bypassing for an entire folder*
|
731 |
To bypass redirection for an entire folder, you can put something like this into your root .htaccess:
|
732 |
`
|
@@ -764,6 +766,9 @@ The current milestones, their subtasks and their progress can be viewed here: ht
|
|
764 |
|
765 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
766 |
|
|
|
|
|
|
|
767 |
= Can I buy you a cup of coffee? =
|
768 |
You sure can! To do so, [go here!](https://ko-fi.com/rosell). If payment doesn't work for your country, [try here instead](https://buymeacoff.ee/rosell).
|
769 |
|
@@ -776,6 +781,20 @@ If you want to make sure that my coffee supplies don't run dry, you can even buy
|
|
776 |
|
777 |
== Changelog ==
|
778 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
779 |
= 0.22.1 =
|
780 |
*(released: 09 Nov 2021)*
|
781 |
* Bugfix: Old unupdated rewrite rules for redirecting to converter caused error (bug was introduced in 0.22.0). Thanks, @utrenkner for reacting quickly!
|
@@ -834,6 +853,9 @@ For older releases, check out changelog.txt
|
|
834 |
|
835 |
== Upgrade Notice ==
|
836 |
|
|
|
|
|
|
|
837 |
= 0.22.1 =
|
838 |
* Two bug fixes related to .htaccess files and redirecting to converter
|
839 |
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.8
|
7 |
+
Stable tag: 0.23.0
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
175 |
* Ruben Solvang
|
176 |
|
177 |
**Persons who recently contributed with [ko-fi](https://ko-fi.com/rosell) - Thanks!**
|
178 |
+
* 13 Nov: @sween
|
179 |
* 9 Nov: @utrenkner
|
180 |
* 26 Oct: Anonymous
|
181 |
* 29 Aug: Pawa Tecnologia
|
|
|
182 |
|
183 |
**Persons who contributed with extra generously amounts of coffee / lifetime backing (>30$) - thanks!:**
|
184 |
|
722 |
There can be instances where you actually need to serve a jpeg or png. For example if you are demonstrating how a jpeg looks using some compression settings.
|
723 |
|
724 |
If you want an image to be served in the original format (jpeg og png), do one of the following things:
|
725 |
+
- Add "?dontreplace" to the image url.
|
726 |
+
- Place an empty file in the same folder as the jpeg/png. The file name must be the same as the jpeg/png with ".dontreplace" appended
|
727 |
|
728 |
Doing this will bypass redirection to webp and also prevent Alter HTML to use the webp instead of the original.
|
729 |
|
730 |
+
NOTE: You may have to regenerate .htaccess rules (by clicking the button) in order for this to work. The feature was added in 0.23.0 and if you started using WebP Express before that, the necessary rules will not be there, unless you regenerate, that is.
|
731 |
+
|
732 |
*Bypassing for an entire folder*
|
733 |
To bypass redirection for an entire folder, you can put something like this into your root .htaccess:
|
734 |
`
|
766 |
|
767 |
If you wish to affect priorities, it is certainly possible. You can try to argue your case in the forum or you can simply let the money do the talking. By donating as little as a cup of coffee on [ko-fi.com/rosell](https://ko-fi.com/rosell), you can leave a wish. I shall take these wishes into account when prioritizing between new features.
|
768 |
|
769 |
+
= Beta testing =
|
770 |
+
I generally create a pre-release before publishing. If you [follow me on ko-fi](https://ko-fi.com/rosell), you will get notified when a pre-release is available. I generally create a pre-release on fridays and mark it as stable on mondays. In order to download a pre-release, go to [the advanced page](https://wordpress.org/plugins/webp-express/advanced/) and scroll down to "Please select a specific version to download". I don't name the pre-releases different. You will just see the next version here before it is available the usual way.
|
771 |
+
|
772 |
= Can I buy you a cup of coffee? =
|
773 |
You sure can! To do so, [go here!](https://ko-fi.com/rosell). If payment doesn't work for your country, [try here instead](https://buymeacoff.ee/rosell).
|
774 |
|
781 |
|
782 |
== Changelog ==
|
783 |
|
784 |
+
= 0.23.0 =
|
785 |
+
*(pre-released: 15 Nov 2021)*
|
786 |
+
* Changed names for preventing replacing image with webp. Use "?dontreplace" / ".dontreplace" instead of "?original" and ".do-not-convert". The old ones are deprecated, but will still work (for a while)
|
787 |
+
* You can now convert images in the file manager and view conversion log
|
788 |
+
* The new file manager UI is now available in multisite too
|
789 |
+
* Changed names for the escape hatches that was introduced in 0.22. Use "?dontreplace" and ".dontreplace" rather than "?original" and ".do-not-convert". The old names still works
|
790 |
+
* Added message to users that have the Elementor plugin installed on how to configure Elementor to inline CSS in order for Alter HTML to be able to replace image URLs (only displayed when relevant)
|
791 |
+
* Added UI for "skip-these-precompiled-binaries" cwebp option. Thanks to @madmax4ever for posting code for this.
|
792 |
+
* Bumped dom-util-for-webp library to 0.5
|
793 |
+
* Bugfix: In multisite, Alter HTML produced wrong webp urls when destination structure was set to "image roots". Thanks to John A. Huebner II (@hube2) who lives on a big hill in central NY, USA for reporting the issue.
|
794 |
+
* Bugfix: One of the newly introduced escape hatches didn't work in Alter HTML.
|
795 |
+
|
796 |
+
For more info, see the closed issues on the [webp-express 0.23 milestone](https://github.com/rosell-dk/webp-express/milestone/43?closed=1)
|
797 |
+
|
798 |
= 0.22.1 =
|
799 |
*(released: 09 Nov 2021)*
|
800 |
* Bugfix: Old unupdated rewrite rules for redirecting to converter caused error (bug was introduced in 0.22.0). Thanks, @utrenkner for reacting quickly!
|
853 |
|
854 |
== Upgrade Notice ==
|
855 |
|
856 |
+
= 0.23.0 =
|
857 |
+
* Various improvements and bug fixes
|
858 |
+
|
859 |
= 0.22.1 =
|
860 |
* Two bug fixes related to .htaccess files and redirecting to converter
|
861 |
|
@@ -1,3 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 0.22.1 =
|
2 |
*(released: 09 Nov 2021)*
|
3 |
* Bugfix: Old unupdated rewrite rules for redirecting to converter caused error (bug was introduced in 0.22.0). Thanks, @utrenkner for reacting quickly!
|
1 |
+
= 0.23.0 =
|
2 |
+
*(pre-released: 15 Nov 2021, scheduled for release 16 Nov 2021)*
|
3 |
+
* Changed names for preventing replacing image with webp. Use "?dontreplace" / ".dontreplace" instead of "?original" and ".do-not-convert". The old ones are deprecated, but will still work (for a while)
|
4 |
+
* You can now convert images in the file manager and view conversion log
|
5 |
+
* The new file manager UI is now available in multisite too
|
6 |
+
* Changed names for the escape hatches that was introduced in 0.22. Use "?dontreplace" and ".dontreplace" rather than "?original" and ".do-not-convert". The old names still works
|
7 |
+
* Added message to users that have the Elementor plugin installed on how to configure Elementor to inline CSS in order for Alter HTML to be able to replace image URLs (only displayed when relevant)
|
8 |
+
* Added UI for "skip-these-precompiled-binaries" cwebp option. Thanks to @madmax4ever for posting code for this.
|
9 |
+
* Bumped dom-util-for-webp library to 0.5
|
10 |
+
* Bugfix: In multisite, Alter HTML produced wrong webp urls when destination structure was set to "image roots". Thanks to John A. Huebner II (@hube2) who lives on a big hill in central NY, USA for reporting the issue.
|
11 |
+
* Bugfix: One of the newly introduced escape hatches didn't work in Alter HTML.
|
12 |
+
|
13 |
+
For more info, see the closed issues on the [webp-express 0.23 milestone](https://github.com/rosell-dk/webp-express/milestone/43?closed=1)
|
14 |
+
|
15 |
= 0.22.1 =
|
16 |
*(released: 09 Nov 2021)*
|
17 |
* Bugfix: Old unupdated rewrite rules for redirecting to converter caused error (bug was introduced in 0.22.0). Thanks, @utrenkner for reacting quickly!
|
@@ -7,7 +7,7 @@
|
|
7 |
"composer/installers": "^1.0.0",
|
8 |
"rosell-dk/webp-convert": "^2.7.0",
|
9 |
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
|
10 |
-
"rosell-dk/dom-util-for-webp": "^0.
|
11 |
"rosell-dk/htaccess-capability-tester": "^0.9.0"
|
12 |
},
|
13 |
"require-dev": {
|
7 |
"composer/installers": "^1.0.0",
|
8 |
"rosell-dk/webp-convert": "^2.7.0",
|
9 |
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
|
10 |
+
"rosell-dk/dom-util-for-webp": "^0.5.0",
|
11 |
"rosell-dk/htaccess-capability-tester": "^0.9.0"
|
12 |
},
|
13 |
"require-dev": {
|
@@ -19,3 +19,73 @@ rmdir vendor/bin
|
|
19 |
```
|
20 |
|
21 |
3. Commit on git
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
```
|
20 |
|
21 |
3. Commit on git
|
22 |
+
|
23 |
+
|
24 |
+
## Copying WCFM
|
25 |
+
I created the following script for copying WCFM build to webp-express:
|
26 |
+
```
|
27 |
+
#!/bin/bash
|
28 |
+
|
29 |
+
WCFM_PATH=/home/rosell/github/webp-convert-filemanager
|
30 |
+
WE_PATH=/home/rosell/github/webp-express/lib/wcfm
|
31 |
+
WCFMPage_PATH=/home/rosell/github/webp-express/lib/classes/WCFMPage.php
|
32 |
+
|
33 |
+
copyassets() {
|
34 |
+
# remove assets in WebP Express
|
35 |
+
rm -f $WE_PATH/index*.css
|
36 |
+
rm -f $WE_PATH/index*.js
|
37 |
+
rm -f $WE_PATH/vendor*.js
|
38 |
+
|
39 |
+
# copy assets from WCFM
|
40 |
+
cp $WCFM_PATH/dist/assets/index*.css $WE_PATH/
|
41 |
+
cp $WCFM_PATH/dist/assets/index*.js $WE_PATH/
|
42 |
+
cp $WCFM_PATH/dist/assets/vendor*.js $WE_PATH/
|
43 |
+
|
44 |
+
|
45 |
+
#CSS_FILE = $(ls /home/rosell/github/webp-express/lib/wcfm | grep 'index.*css' | tr '\n' ' ' | sed 's/\s//')
|
46 |
+
CSS_FILE=$(ls $WE_PATH | grep 'index.*css' | tr '\n' ' ' | sed 's/\s//')
|
47 |
+
JS_FILE=$(ls $WE_PATH | grep 'index.*js' | tr '\n' ' ' | sed 's/\s//')
|
48 |
+
|
49 |
+
|
50 |
+
if [ ! $CSS_FILE ]; then
|
51 |
+
echo "No CSS file! - aborting"
|
52 |
+
exit
|
53 |
+
fi
|
54 |
+
if [ ! $JS_FILE ]; then
|
55 |
+
echo "No JS file! - aborting"
|
56 |
+
exit
|
57 |
+
fi
|
58 |
+
|
59 |
+
echo "CSS file: $CSS_FILE"
|
60 |
+
echo "JS file: $JS_FILE"
|
61 |
+
|
62 |
+
# Update WCFMPage.PHP references
|
63 |
+
sed -i "s/index\..*\.css/$CSS_FILE/g" $WCFMPage_PATH
|
64 |
+
sed -i "s/index\..*\.js/$JS_FILE/g" $WCFMPage_PATH
|
65 |
+
}
|
66 |
+
|
67 |
+
if [ ! $1 ]; then
|
68 |
+
echo "Missing argument. Must be build, copy or build-copy"
|
69 |
+
exit
|
70 |
+
fi
|
71 |
+
|
72 |
+
buildwcfm() {
|
73 |
+
npm run build --prefix $WCFM_PATH
|
74 |
+
}
|
75 |
+
|
76 |
+
if [ $1 = "copy" ]; then
|
77 |
+
echo "copy"
|
78 |
+
copyassets
|
79 |
+
fi
|
80 |
+
|
81 |
+
if [ $1 = "build" ]; then
|
82 |
+
echo "build"
|
83 |
+
buildwcfm
|
84 |
+
fi
|
85 |
+
|
86 |
+
if [ $1 = "build-copy" ]; then
|
87 |
+
echo "build-copy"
|
88 |
+
buildwcfm
|
89 |
+
copyassets
|
90 |
+
fi
|
91 |
+
```
|
@@ -44,7 +44,7 @@ before rsync, do this:
|
|
44 |
1. the *webp-express.php* file
|
45 |
2. in `lib/options/enqueue_scripts.php`
|
46 |
3. in `lib/classes/ConverterHelperIndependent.php`
|
47 |
-
4. in `README.txt` (Stable tag)
|
48 |
- Perhaps make some final improvements of the readme.
|
49 |
Inspiration: https://www.smashingmagazine.com/2011/11/improve-wordpress-plugins-readme-txt/
|
50 |
https://pippinsplugins.com/how-to-properly-format-and-enhance-your-plugins-readme-txt-file-for-the-wordpress-org-repository/
|
@@ -114,12 +114,12 @@ svn status | grep '^!' | awk '{print $2}' | xargs svn delete --force (t
|
|
114 |
Then add a new tag
|
115 |
```
|
116 |
cd svn
|
117 |
-
svn cp trunk tags/0.22.
|
118 |
```
|
119 |
|
120 |
And commit!
|
121 |
```
|
122 |
-
svn ci -m '0.22.
|
123 |
```
|
124 |
|
125 |
|
44 |
1. the *webp-express.php* file
|
45 |
2. in `lib/options/enqueue_scripts.php`
|
46 |
3. in `lib/classes/ConverterHelperIndependent.php`
|
47 |
+
4. in `README.txt` (Stable tag) - UNLESS IT IS A PRE-RELEASE :)
|
48 |
- Perhaps make some final improvements of the readme.
|
49 |
Inspiration: https://www.smashingmagazine.com/2011/11/improve-wordpress-plugins-readme-txt/
|
50 |
https://pippinsplugins.com/how-to-properly-format-and-enhance-your-plugins-readme-txt-file-for-the-wordpress-org-repository/
|
114 |
Then add a new tag
|
115 |
```
|
116 |
cd svn
|
117 |
+
svn cp trunk tags/0.22.1 (this will copy trunk into a new tag)
|
118 |
```
|
119 |
|
120 |
And commit!
|
121 |
```
|
122 |
+
svn ci -m '0.22.1'
|
123 |
```
|
124 |
|
125 |
|
@@ -53,12 +53,12 @@ class AdminInit
|
|
53 |
if (current_user_can('manage_options')) {
|
54 |
|
55 |
// Hooks related to conversion page (in media)
|
56 |
-
if (self::pageNowIs('upload.php')) {
|
57 |
if (isset($_GET['page']) && ('webp_express_conversion_page' === $_GET['page'])) {
|
58 |
//add_action('admin_enqueue_scripts', array('\WebPExpress\WCFMPage', 'enqueueScripts'));
|
59 |
add_action('admin_head', array('\WebPExpress\WCFMPage', 'addToHead'));
|
60 |
}
|
61 |
-
}
|
62 |
|
63 |
// Hooks related to options page
|
64 |
if (self::pageNowIs('options-general.php') || self::pageNowIs('settings.php')) {
|
@@ -123,7 +123,12 @@ class AdminInit
|
|
123 |
add_action("admin_notices", array('\WebPExpress\DismissableGlobalMessages', 'printMessages'));
|
124 |
|
125 |
if (Multisite::isNetworkActivated()) {
|
126 |
-
|
|
|
|
|
|
|
|
|
|
|
127 |
} else {
|
128 |
add_action("admin_menu", array('\WebPExpress\AdminUi', 'adminMenuHook'));
|
129 |
}
|
53 |
if (current_user_can('manage_options')) {
|
54 |
|
55 |
// Hooks related to conversion page (in media)
|
56 |
+
//if (self::pageNowIs('upload.php')) {
|
57 |
if (isset($_GET['page']) && ('webp_express_conversion_page' === $_GET['page'])) {
|
58 |
//add_action('admin_enqueue_scripts', array('\WebPExpress\WCFMPage', 'enqueueScripts'));
|
59 |
add_action('admin_head', array('\WebPExpress\WCFMPage', 'addToHead'));
|
60 |
}
|
61 |
+
//}
|
62 |
|
63 |
// Hooks related to options page
|
64 |
if (self::pageNowIs('options-general.php') || self::pageNowIs('settings.php')) {
|
123 |
add_action("admin_notices", array('\WebPExpress\DismissableGlobalMessages', 'printMessages'));
|
124 |
|
125 |
if (Multisite::isNetworkActivated()) {
|
126 |
+
if (is_network_admin()) {
|
127 |
+
add_action("network_admin_menu", array('\WebPExpress\AdminUi', 'networAdminMenuHook'));
|
128 |
+
} else {
|
129 |
+
add_action("admin_menu", array('\WebPExpress\AdminUi', 'adminMenuHookMultisite'));
|
130 |
+
}
|
131 |
+
|
132 |
} else {
|
133 |
add_action("admin_menu", array('\WebPExpress\AdminUi', 'adminMenuHook'));
|
134 |
}
|
@@ -40,6 +40,7 @@ class AdminUi
|
|
40 |
return array_merge($links, $mylinks);
|
41 |
}
|
42 |
|
|
|
43 |
// callback for 'network_admin_menu' (registred in AdminInit)
|
44 |
public static function networAdminMenuHook()
|
45 |
{
|
@@ -51,6 +52,34 @@ class AdminUi
|
|
51 |
'webp_express_settings_page', // slug
|
52 |
array('\WebPExpress\OptionsPage', 'display') // Callback function which displays the page
|
53 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
|
56 |
public static function adminMenuHook()
|
40 |
return array_merge($links, $mylinks);
|
41 |
}
|
42 |
|
43 |
+
|
44 |
// callback for 'network_admin_menu' (registred in AdminInit)
|
45 |
public static function networAdminMenuHook()
|
46 |
{
|
52 |
'webp_express_settings_page', // slug
|
53 |
array('\WebPExpress\OptionsPage', 'display') // Callback function which displays the page
|
54 |
);
|
55 |
+
|
56 |
+
add_submenu_page(
|
57 |
+
'settings.php', // Parent element
|
58 |
+
'WebP Express File Manager', //Page Title
|
59 |
+
'WebP Express File Manager', //Menu Title
|
60 |
+
'manage_network_options', //capability
|
61 |
+
'webp_express_conversion_page', // slug
|
62 |
+
array('\WebPExpress\WCFMPage', 'display') //The function to be called to output the content for this page.
|
63 |
+
);
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
public static function adminMenuHookMultisite()
|
68 |
+
{
|
69 |
+
// Add Media page
|
70 |
+
/*
|
71 |
+
not ready - it should not display images for the other blogs!
|
72 |
+
|
73 |
+
add_submenu_page(
|
74 |
+
'upload.php', // Parent element
|
75 |
+
'WebP Express', //Page Title
|
76 |
+
'WebP Express', //Menu Title
|
77 |
+
'manage_network_options', //capability
|
78 |
+
'webp_express_conversion_page', // slug
|
79 |
+
array('\WebPExpress\WCFMPage', 'display') //The function to be called to output the content for this page.
|
80 |
+
);
|
81 |
+
*/
|
82 |
+
|
83 |
}
|
84 |
|
85 |
public static function adminMenuHook()
|
@@ -168,7 +168,6 @@ class AlterHtmlHelper
|
|
168 |
*/
|
169 |
public static function getWebPUrlInImageRoot($sourceUrl, $rootId, $baseUrl, $baseDir)
|
170 |
{
|
171 |
-
//error_log('getWebPUrlInImageRoot:' . $sourceUrl . ':' . $baseUrl . ':' . $baseDir);
|
172 |
|
173 |
|
174 |
$srcPathRel = self::getRelUrlPath($sourceUrl, $baseUrl);
|
@@ -185,6 +184,13 @@ class AlterHtmlHelper
|
|
185 |
return false;
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
// Calculate destination of webp (both path and url)
|
189 |
// ----------------------------------------
|
190 |
|
@@ -192,19 +198,21 @@ class AlterHtmlHelper
|
|
192 |
|
193 |
// Make sure the options are loaded (and fixed)
|
194 |
self::getOptions();
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
|
196 |
if (!isset(self::$options['scope']) || !in_array($rootId, self::$options['scope'])) {
|
197 |
return false;
|
198 |
}
|
199 |
|
200 |
-
$destinationRoot = Paths::destinationRoot(
|
201 |
-
$rootId,
|
202 |
-
self::$options['destination-folder'],
|
203 |
-
self::$options['destination-structure']
|
204 |
-
);
|
205 |
|
206 |
$relPathFromImageRootToSource = PathHelper::getRelDir(
|
207 |
-
realpath(Paths::getAbsDirById($rootId)),
|
208 |
realpath($srcPathAbs)
|
209 |
);
|
210 |
$relPathFromImageRootToDest = ConvertHelperIndependent::appendOrSetExtension(
|
@@ -239,7 +247,25 @@ class AlterHtmlHelper
|
|
239 |
$sourceUrlComponents = parse_url($sourceUrl);
|
240 |
$destUrlComponents = parse_url($destUrl);
|
241 |
$port = isset($sourceUrlComponents['port']) ? ":" . $sourceUrlComponents['port'] : "";
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
}
|
244 |
|
245 |
|
@@ -295,7 +321,6 @@ class AlterHtmlHelper
|
|
295 |
$baseDir = Paths::getAbsDirById($rootId);
|
296 |
$baseUrl = Paths::getUrlById($rootId);
|
297 |
|
298 |
-
//error_log('baseurl: ' . $baseUrl);
|
299 |
if (Multisite::isMultisite() && ($rootId == 'uploads')) {
|
300 |
$baseUrl = Paths::getUploadUrl();
|
301 |
$baseDir = Paths::getUploadDirAbs();
|
168 |
*/
|
169 |
public static function getWebPUrlInImageRoot($sourceUrl, $rootId, $baseUrl, $baseDir)
|
170 |
{
|
|
|
171 |
|
172 |
|
173 |
$srcPathRel = self::getRelUrlPath($sourceUrl, $baseUrl);
|
184 |
return false;
|
185 |
}
|
186 |
|
187 |
+
if (file_exists($srcPathAbs . '.do-not-convert')) {
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
if (file_exists($srcPathAbs . '.dontreplace')) {
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
// Calculate destination of webp (both path and url)
|
195 |
// ----------------------------------------
|
196 |
|
198 |
|
199 |
// Make sure the options are loaded (and fixed)
|
200 |
self::getOptions();
|
201 |
+
$destinationOptions = new DestinationOptions(
|
202 |
+
self::$options['destination-folder'] == 'mingled',
|
203 |
+
self::$options['destination-structure'] == 'doc-root',
|
204 |
+
self::$options['destination-extension'] == 'set',
|
205 |
+
self::$options['scope']
|
206 |
+
);
|
207 |
|
208 |
if (!isset(self::$options['scope']) || !in_array($rootId, self::$options['scope'])) {
|
209 |
return false;
|
210 |
}
|
211 |
|
212 |
+
$destinationRoot = Paths::destinationRoot($rootId, $destinationOptions);
|
|
|
|
|
|
|
|
|
213 |
|
214 |
$relPathFromImageRootToSource = PathHelper::getRelDir(
|
215 |
+
realpath(Paths::getAbsDirById($rootId)), // note: In multisite (subfolders), it contains ie "/site/2/"
|
216 |
realpath($srcPathAbs)
|
217 |
);
|
218 |
$relPathFromImageRootToDest = ConvertHelperIndependent::appendOrSetExtension(
|
247 |
$sourceUrlComponents = parse_url($sourceUrl);
|
248 |
$destUrlComponents = parse_url($destUrl);
|
249 |
$port = isset($sourceUrlComponents['port']) ? ":" . $sourceUrlComponents['port'] : "";
|
250 |
+
$result = $sourceUrlComponents['scheme'] . '://' . $sourceUrlComponents['host'] . $port . $destUrlComponents['path'];
|
251 |
+
|
252 |
+
/*
|
253 |
+
error_log(
|
254 |
+
"getWebPUrlInImageRoot:\n" .
|
255 |
+
"- url: " . $sourceUrl . "\n" .
|
256 |
+
"- baseUrl: " . $baseUrl . "\n" .
|
257 |
+
"- baseDir: " . $baseDir . "\n" .
|
258 |
+
"- root id: " . $rootId . "\n" .
|
259 |
+
"- root abs: " . Paths::getAbsDirById($rootId) . "\n" .
|
260 |
+
"- destination root (abs): " . $destinationRoot['abs-path'] . "\n" .
|
261 |
+
"- destination root (url): " . $destinationRoot['url'] . "\n" .
|
262 |
+
"- rel: " . $srcPathRel . "\n" .
|
263 |
+
"- srcPathAbs: " . $srcPathAbs . "\n" .
|
264 |
+
'- relPathFromImageRootToSource: ' . $relPathFromImageRootToSource . "\n" .
|
265 |
+
'- get_blog_details()->path: ' . get_blog_details()->path . "\n" .
|
266 |
+
"- result: " . $result . "\n"
|
267 |
+
);*/
|
268 |
+
return $result;
|
269 |
}
|
270 |
|
271 |
|
321 |
$baseDir = Paths::getAbsDirById($rootId);
|
322 |
$baseUrl = Paths::getUrlById($rootId);
|
323 |
|
|
|
324 |
if (Multisite::isMultisite() && ($rootId == 'uploads')) {
|
325 |
$baseUrl = Paths::getUploadUrl();
|
326 |
$baseDir = Paths::getUploadDirAbs();
|
@@ -301,6 +301,7 @@ class Config
|
|
301 |
foreach ($config['converters'] as &$converter) {
|
302 |
$converterId = $converter['converter'];
|
303 |
$hasError = isset($testResult['errors'][$converterId]);
|
|
|
304 |
$working = !$hasError;
|
305 |
|
306 |
/*
|
@@ -341,6 +342,9 @@ class Config
|
|
341 |
} else {
|
342 |
unset($converter['error']);
|
343 |
}
|
|
|
|
|
|
|
344 |
}
|
345 |
}
|
346 |
return $config;
|
301 |
foreach ($config['converters'] as &$converter) {
|
302 |
$converterId = $converter['converter'];
|
303 |
$hasError = isset($testResult['errors'][$converterId]);
|
304 |
+
$hasWarning = isset($testResult['warnings'][$converterId]);
|
305 |
$working = !$hasError;
|
306 |
|
307 |
/*
|
342 |
} else {
|
343 |
unset($converter['error']);
|
344 |
}
|
345 |
+
if ($hasWarning) {
|
346 |
+
$converter['warnings'] = $testResult['warnings'][$converterId];
|
347 |
+
}
|
348 |
}
|
349 |
}
|
350 |
return $config;
|
@@ -142,7 +142,9 @@ class Convert
|
|
142 |
$result['filesize-webp'] = @filesize($destination);
|
143 |
$result['destination-path'] = $destination;
|
144 |
|
145 |
-
$
|
|
|
|
|
146 |
|
147 |
$relPathFromImageRootToSource = PathHelper::getRelDir(
|
148 |
realpath(Paths::getAbsDirById($rootId)),
|
142 |
$result['filesize-webp'] = @filesize($destination);
|
143 |
$result['destination-path'] = $destination;
|
144 |
|
145 |
+
$destinationOptions = DestinationOptions::createFromConfig($config);
|
146 |
+
|
147 |
+
$rootOfDestination = Paths::destinationRoot($rootId, $destinationOptions);
|
148 |
|
149 |
$relPathFromImageRootToSource = PathHelper::getRelDir(
|
150 |
realpath(Paths::getAbsDirById($rootId)),
|
@@ -571,7 +571,7 @@ APACHE
|
|
571 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
572 |
|
573 |
// TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
|
574 |
-
$text = 'WebP Express 0.
|
575 |
|
576 |
$logFile = self::getLogFilename($source, $logDir);
|
577 |
|
571 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
572 |
|
573 |
// TODO: Put version number somewhere else. Ie \WebPExpress\VersionNumber::version
|
574 |
+
$text = 'WebP Express 0.23.0. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
|
575 |
|
576 |
$logFile = self::getLogFilename($source, $logDir);
|
577 |
|
@@ -90,7 +90,7 @@ class DestinationUrl
|
|
90 |
return false;
|
91 |
}
|
92 |
|
93 |
-
$destinationRoot = Paths::
|
94 |
$rootId,
|
95 |
$destinationOptions
|
96 |
);
|
90 |
return false;
|
91 |
}
|
92 |
|
93 |
+
$destinationRoot = Paths::destinationRoot(
|
94 |
$rootId,
|
95 |
$destinationOptions
|
96 |
);
|
@@ -387,14 +387,22 @@ class HTAccess
|
|
387 |
if (count($successfullWrites) > 0) {
|
388 |
$msg .= '<p>Rewrite rules were saved to the following files:</p>';
|
389 |
foreach ($successfullWrites as $rootId) {
|
390 |
-
$
|
|
|
|
|
|
|
|
|
391 |
}
|
392 |
}
|
393 |
|
394 |
if (count($successfulDeactivations) > 0) {
|
395 |
$msg .= '<p>Rewrite rules were removed from the following files:</p>';
|
396 |
foreach ($successfulDeactivations as $rootId) {
|
397 |
-
$
|
|
|
|
|
|
|
|
|
398 |
}
|
399 |
}
|
400 |
|
387 |
if (count($successfullWrites) > 0) {
|
388 |
$msg .= '<p>Rewrite rules were saved to the following files:</p>';
|
389 |
foreach ($successfullWrites as $rootId) {
|
390 |
+
$rootIdName = $rootId;
|
391 |
+
if ($rootIdName == 'cache') {
|
392 |
+
$rootIdName = 'webp folder';
|
393 |
+
}
|
394 |
+
$msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootIdName . ')<br>';
|
395 |
}
|
396 |
}
|
397 |
|
398 |
if (count($successfulDeactivations) > 0) {
|
399 |
$msg .= '<p>Rewrite rules were removed from the following files:</p>';
|
400 |
foreach ($successfulDeactivations as $rootId) {
|
401 |
+
$rootIdName = $rootId;
|
402 |
+
if ($rootIdName == 'cache') {
|
403 |
+
$rootIdName = 'webp folder';
|
404 |
+
}
|
405 |
+
$msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootIdName . ')<br>';
|
406 |
}
|
407 |
}
|
408 |
|
@@ -1055,12 +1055,22 @@ class HTAccessRules
|
|
1055 |
$rules .= "<IfModule mod_rewrite.c>\n" .
|
1056 |
" RewriteEngine On\n\n";
|
1057 |
|
1058 |
-
$rules .= " # Escape hatch #1: Adding ?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1059 |
$rules .= " RewriteCond %{QUERY_STRING} original$\n";
|
1060 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
1061 |
$rules .= " RewriteRule . - [L]\n\n";
|
1062 |
|
1063 |
-
$rules .= " #
|
1064 |
$rules .= " RewriteCond %{REQUEST_FILENAME} (?i)(.*)(\.jpe?g|\.png)$\n";
|
1065 |
$rules .= " RewriteCond %1%2\.do-not-convert -f\n";
|
1066 |
$rules .= " RewriteRule . - [L]\n\n";
|
1055 |
$rules .= "<IfModule mod_rewrite.c>\n" .
|
1056 |
" RewriteEngine On\n\n";
|
1057 |
|
1058 |
+
$rules .= " # Escape hatch #1: Adding ?dontreplace to an url can be used to bypass redirection\n";
|
1059 |
+
$rules .= " RewriteCond %{QUERY_STRING} dontreplace$\n";
|
1060 |
+
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
1061 |
+
$rules .= " RewriteRule . - [L]\n\n";
|
1062 |
+
|
1063 |
+
$rules .= " # Escape hatch #2: Placing an empty file in the same folder as the jpeg/png which has same file name, but \".dontreplace\" appended will bypass redirection\n";
|
1064 |
+
$rules .= " RewriteCond %{REQUEST_FILENAME} (?i)(.*)(\.jpe?g|\.png)$\n";
|
1065 |
+
$rules .= " RewriteCond %1%2\.dontreplace -f\n";
|
1066 |
+
$rules .= " RewriteRule . - [L]\n\n";
|
1067 |
+
|
1068 |
+
$rules .= " # Deprecated escape hatch: Adding ?original to an url can be used to bypass redirection\n";
|
1069 |
$rules .= " RewriteCond %{QUERY_STRING} original$\n";
|
1070 |
$rules .= " RewriteCond %{REQUEST_FILENAME} -f\n";
|
1071 |
$rules .= " RewriteRule . - [L]\n\n";
|
1072 |
|
1073 |
+
$rules .= " # Deprecated escape hatch: Placing an empty file in the same folder as the jpeg/png which has same file name, but \".do-not-convert\" appended will bypass redirection\n";
|
1074 |
$rules .= " RewriteCond %{REQUEST_FILENAME} (?i)(.*)(\.jpe?g|\.png)$\n";
|
1075 |
$rules .= " RewriteCond %1%2\.do-not-convert -f\n";
|
1076 |
$rules .= " RewriteRule . - [L]\n\n";
|
@@ -586,43 +586,11 @@ APACHE
|
|
586 |
* (but not quite, as the logic is also in ConverterHelperIndependent::getDestination).
|
587 |
*
|
588 |
* @param string $rootId
|
589 |
-
* @param
|
590 |
-
* @param string $destinationStructure ("doc-root" or "image-roots")
|
591 |
*
|
592 |
* @return array url and abs-path of destination root
|
593 |
*/
|
594 |
-
public static function destinationRoot($rootId, $
|
595 |
-
{
|
596 |
-
if (($destinationFolder == 'mingled') && ($rootId == 'uploads')) {
|
597 |
-
return [
|
598 |
-
'url' => self::getUrlById('uploads'),
|
599 |
-
'abs-path' => self::getUploadDirAbs()
|
600 |
-
];
|
601 |
-
} else {
|
602 |
-
|
603 |
-
// Its within these bases:
|
604 |
-
$destUrl = self::getUrlById('wp-content') . '/webp-express/webp-images';
|
605 |
-
$destPath = self::getAbsDirById('wp-content') . '/webp-express/webp-images';
|
606 |
-
|
607 |
-
if (($destinationStructure == 'doc-root') && self::canUseDocRootForStructuringCacheDir()) {
|
608 |
-
$relPathFromDocRootToSourceImageRoot = PathHelper::getRelPathFromDocRootToDirNoDirectoryTraversalAllowed(
|
609 |
-
self::getAbsDirById($rootId)
|
610 |
-
);
|
611 |
-
return [
|
612 |
-
'url' => $destUrl . '/doc-root/' . $relPathFromDocRootToSourceImageRoot,
|
613 |
-
'abs-path' => $destPath . '/doc-root/' . $relPathFromDocRootToSourceImageRoot
|
614 |
-
];
|
615 |
-
} else {
|
616 |
-
return [
|
617 |
-
'url' => $destUrl . '/' . $rootId,
|
618 |
-
'abs-path' => $destPath . '/' . $rootId
|
619 |
-
];
|
620 |
-
}
|
621 |
-
}
|
622 |
-
}
|
623 |
-
|
624 |
-
// this shall replace destinationRoot
|
625 |
-
public static function destinationRoot2($rootId, $destinationOptions)
|
626 |
{
|
627 |
if (($destinationOptions->mingled) && ($rootId == 'uploads')) {
|
628 |
return [
|
@@ -644,9 +612,13 @@ APACHE
|
|
644 |
'abs-path' => $destPath . '/doc-root/' . $relPathFromDocRootToSourceImageRoot
|
645 |
];
|
646 |
} else {
|
|
|
|
|
|
|
|
|
647 |
return [
|
648 |
-
'url' => $destUrl . '/' . $rootId,
|
649 |
-
'abs-path' => $destPath . '/' . $rootId
|
650 |
];
|
651 |
}
|
652 |
}
|
586 |
* (but not quite, as the logic is also in ConverterHelperIndependent::getDestination).
|
587 |
*
|
588 |
* @param string $rootId
|
589 |
+
* @param DestinationOptions $destinationOptions
|
|
|
590 |
*
|
591 |
* @return array url and abs-path of destination root
|
592 |
*/
|
593 |
+
public static function destinationRoot($rootId, $destinationOptions)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
594 |
{
|
595 |
if (($destinationOptions->mingled) && ($rootId == 'uploads')) {
|
596 |
return [
|
612 |
'abs-path' => $destPath . '/doc-root/' . $relPathFromDocRootToSourceImageRoot
|
613 |
];
|
614 |
} else {
|
615 |
+
$extraPath = '';
|
616 |
+
if (is_multisite() && (get_current_blog_id() != 1)) {
|
617 |
+
$extraPath = '/sites/' . get_current_blog_id(); // #510
|
618 |
+
}
|
619 |
return [
|
620 |
+
'url' => $destUrl . '/' . $rootId . $extraPath,
|
621 |
+
'abs-path' => $destPath . '/' . $rootId . $extraPath
|
622 |
];
|
623 |
}
|
624 |
}
|
@@ -78,15 +78,6 @@ class PluginActivate
|
|
78 |
);
|
79 |
}
|
80 |
|
81 |
-
|
82 |
-
if ( is_multisite() ) {
|
83 |
-
Messenger::addMessage(
|
84 |
-
'warning',
|
85 |
-
'Multisite functionality in still new in WebP Express (it was added in release 0.12.0). ' .
|
86 |
-
'While it has been tested on several setups, there might be a bug or two yet to be found.'
|
87 |
-
);
|
88 |
-
}
|
89 |
-
|
90 |
if (!version_compare(PHP_VERSION, '5.5.0', '>=')) {
|
91 |
Messenger::addMessage(
|
92 |
'warning',
|
78 |
);
|
79 |
}
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
if (!version_compare(PHP_VERSION, '5.5.0', '>=')) {
|
82 |
Messenger::addMessage(
|
83 |
'warning',
|
@@ -22,6 +22,30 @@ class TestRun
|
|
22 |
|
23 |
public static $converterStatus = null; // to cache the result
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
/**
|
26 |
* Get a test result object OR false, if tests cannot be made.
|
27 |
*
|
@@ -45,6 +69,7 @@ class TestRun
|
|
45 |
}
|
46 |
$workingConverters = [];
|
47 |
$errors = [];
|
|
|
48 |
|
49 |
// We need wod options.
|
50 |
// But we cannot simply use loadWodOptions - because that would leave out the deactivated
|
@@ -60,9 +85,16 @@ class TestRun
|
|
60 |
$options = Config::generateWodOptionsFromConfigObj($config);
|
61 |
$options['converters'] = ConvertersHelper::normalize($options['webp-convert']['convert']['converters']);
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
//echo '<pre>' . print_r($options, true) . '</pre>';
|
64 |
foreach ($options['converters'] as $converter) {
|
65 |
$converterId = $converter['converter'];
|
|
|
66 |
try {
|
67 |
$converterOptions = array_merge($options, $converter['options']);
|
68 |
unset($converterOptions['converters']);
|
@@ -74,19 +106,30 @@ class TestRun
|
|
74 |
$destination,
|
75 |
$converterOptions
|
76 |
);
|
|
|
|
|
|
|
|
|
77 |
$converterInstance->doConvert();
|
|
|
|
|
|
|
|
|
78 |
$workingConverters[] = $converterId;
|
79 |
} catch (\Exception $e) {
|
80 |
//echo $e->getMessage() . '<br>';
|
81 |
$errors[$converterId] = $e->getMessage();
|
82 |
}
|
83 |
}
|
|
|
|
|
84 |
//print_r($errors);
|
85 |
|
86 |
// cache the result
|
87 |
self::$converterStatus = [
|
88 |
'workingConverters' => $workingConverters,
|
89 |
-
'errors' => $errors
|
|
|
90 |
];
|
91 |
return self::$converterStatus;
|
92 |
}
|
22 |
|
23 |
public static $converterStatus = null; // to cache the result
|
24 |
|
25 |
+
private static $warnings;
|
26 |
+
|
27 |
+
public static function warningHandler($errno, $errstr, $errfile, $errline, $errcontext = null)
|
28 |
+
{
|
29 |
+
$errorTypes = [
|
30 |
+
E_WARNING => "Warning",
|
31 |
+
E_NOTICE => "Notice",
|
32 |
+
E_STRICT => "Strict Notice",
|
33 |
+
E_DEPRECATED => "Deprecated",
|
34 |
+
E_USER_DEPRECATED => "User Deprecated",
|
35 |
+
];
|
36 |
+
|
37 |
+
if (isset($errorTypes[$errno])) {
|
38 |
+
$errType = $errorTypes[$errno];
|
39 |
+
} else {
|
40 |
+
$errType = "Warning ($errno)";
|
41 |
+
}
|
42 |
+
|
43 |
+
$msg = $errType . ': ' . $errstr . ' in ' . $errfile . ', line ' . $errline;
|
44 |
+
self::$warnings[] = $msg;
|
45 |
+
|
46 |
+
// suppress!
|
47 |
+
return true;
|
48 |
+
}
|
49 |
/**
|
50 |
* Get a test result object OR false, if tests cannot be made.
|
51 |
*
|
69 |
}
|
70 |
$workingConverters = [];
|
71 |
$errors = [];
|
72 |
+
self::$warnings = [];
|
73 |
|
74 |
// We need wod options.
|
75 |
// But we cannot simply use loadWodOptions - because that would leave out the deactivated
|
85 |
$options = Config::generateWodOptionsFromConfigObj($config);
|
86 |
$options['converters'] = ConvertersHelper::normalize($options['webp-convert']['convert']['converters']);
|
87 |
|
88 |
+
$previousErrorHandler = set_error_handler(
|
89 |
+
array('\WebPExpress\TestRun', "warningHandler"),
|
90 |
+
E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE
|
91 |
+
);
|
92 |
+
|
93 |
+
$warnings = [];
|
94 |
//echo '<pre>' . print_r($options, true) . '</pre>';
|
95 |
foreach ($options['converters'] as $converter) {
|
96 |
$converterId = $converter['converter'];
|
97 |
+
self::$warnings = [];
|
98 |
try {
|
99 |
$converterOptions = array_merge($options, $converter['options']);
|
100 |
unset($converterOptions['converters']);
|
106 |
$destination,
|
107 |
$converterOptions
|
108 |
);
|
109 |
+
// Note: We now suppress warnings.
|
110 |
+
// WebPConvert logs warnings but purposefully does not stop them - warnings should generally not be
|
111 |
+
// stopped. However, as these warnings are logged in conversion log, it is preferable not to make them
|
112 |
+
// bubble here. #
|
113 |
$converterInstance->doConvert();
|
114 |
+
|
115 |
+
if (count(self::$warnings) > 0) {
|
116 |
+
$warnings[$converterId] = self::$warnings;
|
117 |
+
}
|
118 |
$workingConverters[] = $converterId;
|
119 |
} catch (\Exception $e) {
|
120 |
//echo $e->getMessage() . '<br>';
|
121 |
$errors[$converterId] = $e->getMessage();
|
122 |
}
|
123 |
}
|
124 |
+
|
125 |
+
restore_error_handler();
|
126 |
//print_r($errors);
|
127 |
|
128 |
// cache the result
|
129 |
self::$converterStatus = [
|
130 |
'workingConverters' => $workingConverters,
|
131 |
+
'errors' => $errors,
|
132 |
+
'warnings' => $warnings,
|
133 |
];
|
134 |
return self::$converterStatus;
|
135 |
}
|
@@ -223,7 +223,8 @@ class WCFMApi
|
|
223 |
//'filename' => $absPath,
|
224 |
//'abspath' => $absPath,
|
225 |
'size' => filesize($absPath),
|
226 |
-
|
|
|
227 |
]
|
228 |
];
|
229 |
|
@@ -246,15 +247,31 @@ class WCFMApi
|
|
246 |
$destinationUrl = Paths::getUrlById($rootId) . '/' . $destRelPath;
|
247 |
|
248 |
SanityCheck::absPath($absPathDest);
|
|
|
249 |
if (@file_exists($absPathDest)) {
|
250 |
$result['converted'] = [
|
251 |
-
'abspath' => $absPathDest,
|
252 |
'size' => filesize($absPathDest),
|
253 |
'url' => $destinationUrl . '?' . SelfTestHelper::randomDigitsAndLetters(8),
|
254 |
-
'log' => ''
|
255 |
];
|
256 |
}
|
257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
}
|
259 |
|
260 |
|
@@ -289,6 +306,42 @@ class WCFMApi
|
|
289 |
return $result;
|
290 |
}
|
291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
public static function processGetFolder() {
|
293 |
|
294 |
Validate::postHasKey('args');
|
@@ -328,23 +381,7 @@ class WCFMApi
|
|
328 |
}
|
329 |
return $result;
|
330 |
}
|
331 |
-
$
|
332 |
-
$path = ltrim($path, '/');
|
333 |
-
$pathTokens = explode('/', $path);
|
334 |
-
|
335 |
-
$rootId = array_shift($pathTokens);
|
336 |
-
$relPath = implode('/', $pathTokens);
|
337 |
-
|
338 |
-
if (!in_array($rootId, $rootIds)) {
|
339 |
-
throw new \Exception('Invalid rootId');
|
340 |
-
}
|
341 |
-
|
342 |
-
if ($relPath == '') {
|
343 |
-
$relPath = '.';
|
344 |
-
}
|
345 |
-
|
346 |
-
$absPath = Paths::getAbsDirById($rootId) . '/' . $relPath;
|
347 |
-
SanityCheck::absPathExists($absPath);
|
348 |
|
349 |
$listOptions = BulkConvert::defaultListOptions($config);
|
350 |
$listOptions['root'] = Paths::getAbsDirById($rootId);
|
@@ -404,11 +441,31 @@ class WCFMApi
|
|
404 |
if (!array_key_exists('path', $args)) {
|
405 |
throw new \Exception('"path" argument missing for command');
|
406 |
}
|
407 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
throw new \Exception('"convertOptions" argument missing for command');
|
409 |
}
|
|
|
|
|
410 |
|
411 |
-
return ['success' => true, 'optionsReceived' => $args['convertOptions']];
|
412 |
|
413 |
/*
|
414 |
$path = SanityCheck::pathWithoutDirectoryTraversal($args['path']);
|
223 |
//'filename' => $absPath,
|
224 |
//'abspath' => $absPath,
|
225 |
'size' => filesize($absPath),
|
226 |
+
// PS: I keep "&original" because some might have set up Nginx rules for ?original
|
227 |
+
'url' => Paths::getUrlById($rootId) . '/' . $relPath . '?' . SelfTestHelper::randomDigitsAndLetters(8) . '&dontreplace&original',
|
228 |
]
|
229 |
];
|
230 |
|
247 |
$destinationUrl = Paths::getUrlById($rootId) . '/' . $destRelPath;
|
248 |
|
249 |
SanityCheck::absPath($absPathDest);
|
250 |
+
|
251 |
if (@file_exists($absPathDest)) {
|
252 |
$result['converted'] = [
|
253 |
+
//'abspath' => $absPathDest,
|
254 |
'size' => filesize($absPathDest),
|
255 |
'url' => $destinationUrl . '?' . SelfTestHelper::randomDigitsAndLetters(8),
|
|
|
256 |
];
|
257 |
}
|
258 |
|
259 |
+
// Get log, if exists. Ignore errors.
|
260 |
+
$log = '';
|
261 |
+
try {
|
262 |
+
$logFile = ConvertHelperIndependent::getLogFilename($absPath, Paths::getLogDirAbs());
|
263 |
+
if (@file_exists($logFile)) {
|
264 |
+
$logContent = file_get_contents($logFile);
|
265 |
+
if ($log !== false) {
|
266 |
+
$log = $logContent;
|
267 |
+
}
|
268 |
+
}
|
269 |
+
}
|
270 |
+
catch (\Exception $e) {
|
271 |
+
//throw $e;
|
272 |
+
}
|
273 |
+
|
274 |
+
$result['log'] = $log;
|
275 |
}
|
276 |
|
277 |
|
306 |
return $result;
|
307 |
}
|
308 |
|
309 |
+
/**
|
310 |
+
* Translate path received (ie "/uploads/2021/...") to absolute path.
|
311 |
+
*
|
312 |
+
* @param string $path
|
313 |
+
*
|
314 |
+
* @return array [$absPath, $relPath, $rootId]
|
315 |
+
* @throws \Exception if root id is invalid or path doesn't pass sanity check
|
316 |
+
*/
|
317 |
+
private static function analyzePathReceived($path) {
|
318 |
+
try {
|
319 |
+
$path = SanityCheck::pathWithoutDirectoryTraversal($path);
|
320 |
+
$path = ltrim($path, '/');
|
321 |
+
$pathTokens = explode('/', $path);
|
322 |
+
|
323 |
+
$rootId = array_shift($pathTokens);
|
324 |
+
$relPath = implode('/', $pathTokens);
|
325 |
+
|
326 |
+
$rootIds = Paths::getImageRootIds();
|
327 |
+
if (!in_array($rootId, $rootIds)) {
|
328 |
+
throw new \Exception('Invalid rootId');
|
329 |
+
}
|
330 |
+
if ($relPath == '') {
|
331 |
+
$relPath = '.';
|
332 |
+
}
|
333 |
+
|
334 |
+
$absPath = PathHelper::canonicalize(Paths::getAbsDirById($rootId) . '/' . $relPath);
|
335 |
+
SanityCheck::absPathExists($absPath);
|
336 |
+
|
337 |
+
return [$absPath, $relPath, $rootId];
|
338 |
+
}
|
339 |
+
catch (\Exception $e) {
|
340 |
+
//throw new \Exception('Invalid path received (' . $e->getMessage() . ')');
|
341 |
+
throw new \Exception('Invalid path');
|
342 |
+
}
|
343 |
+
}
|
344 |
+
|
345 |
public static function processGetFolder() {
|
346 |
|
347 |
Validate::postHasKey('args');
|
381 |
}
|
382 |
return $result;
|
383 |
}
|
384 |
+
list($absPath, $relPath, $rootId) = self::analyzePathReceived($path);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
|
386 |
$listOptions = BulkConvert::defaultListOptions($config);
|
387 |
$listOptions['root'] = Paths::getAbsDirById($rootId);
|
441 |
if (!array_key_exists('path', $args)) {
|
442 |
throw new \Exception('"path" argument missing for command');
|
443 |
}
|
444 |
+
|
445 |
+
$path = SanityCheck::noStreamWrappers($args['path']);
|
446 |
+
list($absPath, $relPath, $rootId) = self::analyzePathReceived($path);
|
447 |
+
$convertResult = Convert::convertFile($absPath);
|
448 |
+
$result = [
|
449 |
+
'success' => $convertResult['success'],
|
450 |
+
'data' => $convertResult['msg'],
|
451 |
+
'log' => $convertResult['log'],
|
452 |
+
];
|
453 |
+
$info = [];
|
454 |
+
if (isset($convertResult['filesize-webp'])) {
|
455 |
+
$info['size'] = $convertResult['filesize-webp'];
|
456 |
+
}
|
457 |
+
if (isset($convertResult['destination-url'])) {
|
458 |
+
$info['url'] = $convertResult['destination-url'] . '?' . SelfTestHelper::randomDigitsAndLetters(8);
|
459 |
+
}
|
460 |
+
$result['converted'] = $info;
|
461 |
+
return $result;
|
462 |
+
|
463 |
+
/*if (!array_key_exists('convertOptions', $args)) {
|
464 |
throw new \Exception('"convertOptions" argument missing for command');
|
465 |
}
|
466 |
+
//return ['success' => true, 'optionsReceived' => $args['convertOptions']];
|
467 |
+
*/
|
468 |
|
|
|
469 |
|
470 |
/*
|
471 |
$path = SanityCheck::pathWithoutDirectoryTraversal($args['path']);
|
@@ -13,10 +13,6 @@ class WCFMPage
|
|
13 |
public static function display() {
|
14 |
echo '<div id="wcfmintro">' .
|
15 |
'<h1>WebP Express Conversion Browser</h1>' .
|
16 |
-
'<p>' .
|
17 |
-
'Note: To convert manually, you still need to use Bulk Convert on the settings page ' .
|
18 |
-
'(or you can use WP CLI)' .
|
19 |
-
'</p>' .
|
20 |
'</div>';
|
21 |
|
22 |
echo '<div id="webpconvert-filemanager" style="position:relative; min-height:400px">loading</div>';
|
@@ -43,7 +39,7 @@ class WCFMPage
|
|
43 |
|
44 |
public static function addToHead() {
|
45 |
$baseUrl = plugins_url('lib/wcfm', WEBPEXPRESS_PLUGIN);
|
46 |
-
//$url = plugins_url('js/conversion-manager/index.
|
47 |
|
48 |
$wcfmNonce = wp_create_nonce('webpexpress-wcfm-nonce');
|
49 |
echo '<scr' . 'ipt>window.webpExpressWCFMNonce = "' . $wcfmNonce . '";</scr' . 'ipt>';
|
@@ -51,9 +47,8 @@ class WCFMPage
|
|
51 |
echo '<scr' . 'ipt src="' . $baseUrl . '/wcfm-options.js?11"></scr' . 'ipt>';
|
52 |
//echo '<scr' . 'ipt type="module" src="' . $baseUrl . '/vendor.js?1"></scr' . 'ipt>';
|
53 |
|
54 |
-
|
55 |
-
echo '<
|
56 |
-
echo '<link rel="stylesheet" href="' . $baseUrl . '/index.ab43bb2c.css">';
|
57 |
}
|
58 |
|
59 |
}
|
13 |
public static function display() {
|
14 |
echo '<div id="wcfmintro">' .
|
15 |
'<h1>WebP Express Conversion Browser</h1>' .
|
|
|
|
|
|
|
|
|
16 |
'</div>';
|
17 |
|
18 |
echo '<div id="webpconvert-filemanager" style="position:relative; min-height:400px">loading</div>';
|
39 |
|
40 |
public static function addToHead() {
|
41 |
$baseUrl = plugins_url('lib/wcfm', WEBPEXPRESS_PLUGIN);
|
42 |
+
//$url = plugins_url('js/conversion-manager/index.ee44cdbf.js ', WEBPEXPRESS_PLUGIN);
|
43 |
|
44 |
$wcfmNonce = wp_create_nonce('webpexpress-wcfm-nonce');
|
45 |
echo '<scr' . 'ipt>window.webpExpressWCFMNonce = "' . $wcfmNonce . '";</scr' . 'ipt>';
|
47 |
echo '<scr' . 'ipt src="' . $baseUrl . '/wcfm-options.js?11"></scr' . 'ipt>';
|
48 |
//echo '<scr' . 'ipt type="module" src="' . $baseUrl . '/vendor.js?1"></scr' . 'ipt>';
|
49 |
|
50 |
+
echo '<scr' . 'ipt type="module" src="' . $baseUrl . '/index.ee44cdbf.js"></scr' . 'ipt>';
|
51 |
+
echo '<link rel="stylesheet" href="' . $baseUrl . '/index.659b742a.css">';
|
|
|
52 |
}
|
53 |
|
54 |
}
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebPExpress;
|
4 |
+
|
5 |
+
$elementorActivated = in_array('elementor/elementor.php', get_option('active_plugins', []));
|
6 |
+
$showMessage = false;
|
7 |
+
if ($elementorActivated) {
|
8 |
+
try {
|
9 |
+
// The following is wrapped in a try statement because it depends on Elementor classes which might be subject to change
|
10 |
+
if (\Elementor\Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_loading' ) === false) {
|
11 |
+
$showMessage = true;
|
12 |
+
}
|
13 |
+
} catch (\Exception $e) {
|
14 |
+
// Well, just bad luck.
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
if ($showMessage) {
|
19 |
+
DismissableMessages::printDismissableMessage(
|
20 |
+
'info',
|
21 |
+
'<p>' .
|
22 |
+
'You see this message because you using Elementor, you rely solely on Alter HTML for webp, and Elementor is currently set up to use external css. ' .
|
23 |
+
'You might want to reconfigure Elementor so it inlines the CSS. This will allow Alter HTML to replace the image urls of backgrounds. ' .
|
24 |
+
'To reconfigure, go to <i>Elementor > Settings > Experiments</i> and activate "Improved CSS Loading". ' .
|
25 |
+
'Note: This requires that Alter HTML is configured to "Replace image URLs". ' .
|
26 |
+
'For more information, <a target="_blank" href="https://wordpress.org/support/topic/background-images-not-working-as-webp-elementor/#post-15060686">' .
|
27 |
+
'head over here</a>' .
|
28 |
+
'</p>',
|
29 |
+
'0.23.0/elementor',
|
30 |
+
'Got it!'
|
31 |
+
);
|
32 |
+
} else {
|
33 |
+
DismissableMessages::dismissMessage('0.23.0/elementor');
|
34 |
+
}
|
@@ -166,10 +166,13 @@
|
|
166 |
#converters li svg#status_not_ok {
|
167 |
color: #b11010; /* 444444 */
|
168 |
}
|
|
|
|
|
|
|
|
|
169 |
#converters li.deactivated svg#status_not_ok {
|
170 |
color: #999999;
|
171 |
}
|
172 |
-
|
173 |
#converters li.deactivated .status {
|
174 |
bottom: unset;
|
175 |
}
|
@@ -255,6 +258,10 @@
|
|
255 |
#converters li.operational .popup {
|
256 |
background-color: #80ff80;
|
257 |
}
|
|
|
|
|
|
|
|
|
258 |
/* #converters li .status:hover .popup,*/
|
259 |
#converters li:hover .status .popup,
|
260 |
.help:hover .popup {
|
166 |
#converters li svg#status_not_ok {
|
167 |
color: #b11010; /* 444444 */
|
168 |
}
|
169 |
+
#converters li svg#status_warning {
|
170 |
+
color: #dc0;
|
171 |
+
}
|
172 |
+
|
173 |
#converters li.deactivated svg#status_not_ok {
|
174 |
color: #999999;
|
175 |
}
|
|
|
176 |
#converters li.deactivated .status {
|
177 |
bottom: unset;
|
178 |
}
|
258 |
#converters li.operational .popup {
|
259 |
background-color: #80ff80;
|
260 |
}
|
261 |
+
#converters li.has-warnings .popup {
|
262 |
+
background-color: #ff5;
|
263 |
+
}
|
264 |
+
|
265 |
/* #converters li .status:hover .popup,*/
|
266 |
#converters li:hover .status .popup,
|
267 |
.help:hover .popup {
|
@@ -5,8 +5,12 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
5 |
use \WebPExpress\Paths;
|
6 |
use \WebPExpress\Config;
|
7 |
|
8 |
-
$ver
|
9 |
-
|
|
|
|
|
|
|
|
|
10 |
|
11 |
if (!function_exists('webp_express_add_inline_script')) {
|
12 |
function webp_express_add_inline_script($id, $script, $position) {
|
5 |
use \WebPExpress\Paths;
|
6 |
use \WebPExpress\Config;
|
7 |
|
8 |
+
// Note: $ver is added to querystring. However, when it is is critical that no-one gets the cached version,
|
9 |
+
// a change of filename is neccessary, as there is a plugin that strips version strings out there...!
|
10 |
+
// If only one file update is critical: change the name of the file
|
11 |
+
// If several files are critical: rename the folder (ie "js2")
|
12 |
+
$ver = '3'; // note: Minimum 1.
|
13 |
+
$jsDir = 'js';
|
14 |
|
15 |
if (!function_exists('webp_express_add_inline_script')) {
|
16 |
function webp_express_add_inline_script($id, $script, $position) {
|
File without changes
|
File without changes
|
@@ -26,7 +26,7 @@ function getConversionMethodDescription(converterId) {
|
|
26 |
}
|
27 |
|
28 |
function generateConverterHTML(converter) {
|
29 |
-
html = '<li data-id="' + converter['id'] + '" class="' + (converter.deactivated ? 'deactivated' : '') + ' ' + (converter.working ? 'operational' : 'not-operational') + '">';
|
30 |
//html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
31 |
// html += '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>';
|
32 |
// html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#888888" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
@@ -45,23 +45,51 @@ function generateConverterHTML(converter) {
|
|
45 |
}
|
46 |
|
47 |
html += '<div class="status">';
|
48 |
-
if (converter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
html += '<svg id="status_ok" width="19" height="19" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.000000 256.000000" preserveAspectRatio="xMidYMid meet">';
|
50 |
html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"/></g></svg>';
|
51 |
//html += '<div class="popup">' + converter['id'] + ' is operational</div>';
|
52 |
html += '<div class="popup">Operational</div>';
|
53 |
-
} else {
|
54 |
-
// + converter['id'] + ' is not operational<br>';
|
55 |
-
//html += 'not operational. ';
|
56 |
-
if (converter['error']) {
|
57 |
-
html += '<svg id="status_not_ok" width="19" height="19" title="not operational" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet">';
|
58 |
-
html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"/></g></svg>';
|
59 |
-
html += '<div class="popup">';
|
60 |
-
|
61 |
-
html += webpexpress_escapeHTML(converter['error']);
|
62 |
-
|
63 |
-
html += '</div>';
|
64 |
-
}
|
65 |
}
|
66 |
html += '</div>';
|
67 |
|
@@ -292,6 +320,7 @@ function configureConverter(id) {
|
|
292 |
document.getElementById('cwebp_use_nice').checked = getConverterOption(converter, 'use-nice', true);
|
293 |
document.getElementById('cwebp_method').value = getConverterOption(converter, 'method', '');
|
294 |
document.getElementById('cwebp_try_common_system_paths').checked = getConverterOption(converter, 'try-common-system-paths', '');
|
|
|
295 |
document.getElementById('cwebp_try_supplied_binary').checked = getConverterOption(converter, 'try-supplied-binary-for-os', '');
|
296 |
document.getElementById('cwebp_set_size').checked = getConverterOption(converter, 'set-size', '');
|
297 |
document.getElementById('cwebp_size_in_percentage').value = getConverterOption(converter, 'size-in-percentage', '');
|
@@ -375,6 +404,7 @@ function updateConverterOptions() {
|
|
375 |
var methodString = document.getElementById('cwebp_method').value;
|
376 |
var methodNum = (methodString == '') ? 6 : parseInt(methodString, 10);
|
377 |
setConverterOption(converter, 'method', methodNum);
|
|
|
378 |
setConverterOption(converter, 'try-common-system-paths', document.getElementById('cwebp_try_common_system_paths').checked);
|
379 |
setConverterOption(converter, 'try-supplied-binary-for-os', document.getElementById('cwebp_try_supplied_binary').checked);
|
380 |
setConverterOption(converter, 'set-size', document.getElementById('cwebp_set_size').checked);
|
26 |
}
|
27 |
|
28 |
function generateConverterHTML(converter) {
|
29 |
+
html = '<li data-id="' + converter['id'] + '" class="' + (converter.deactivated ? 'deactivated' : '') + ' ' + (converter.working ? 'operational' : 'not-operational') + ' ' + (converter.warnings ? 'has-warnings' : '') + '">';
|
30 |
//html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="17px" height="17px" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#444444" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
31 |
// html += '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>';
|
32 |
// html += '<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 100.000000 100.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,100.000000) scale(0.100000,-0.100000)" fill="#888888" stroke="none"><path d="M415 920 l-80 -80 165 0 165 0 -80 80 c-44 44 -82 80 -85 80 -3 0 -41 -36 -85 -80z"/><path d="M0 695 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M0 500 l0 -40 500 0 500 0 0 40 0 40 -500 0 -500 0 0 -40z"/><path d="M0 305 l0 -45 500 0 500 0 0 45 0 45 -500 0 -500 0 0 -45z"/><path d="M418 78 l82 -83 82 83 83 82 -165 0 -165 0 83 -82z"/></g></svg>';
|
45 |
}
|
46 |
|
47 |
html += '<div class="status">';
|
48 |
+
if (converter['error']) {
|
49 |
+
html += '<svg id="status_not_ok" width="19" height="19" title="not operational" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet">';
|
50 |
+
html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"/></g></svg>';
|
51 |
+
html += '<div class="popup">';
|
52 |
+
|
53 |
+
html += webpexpress_escapeHTML(converter['error']);
|
54 |
+
|
55 |
+
html += '</div>';
|
56 |
+
} else if (converter['warnings']) {
|
57 |
+
/*html += '<svg id="status_warning" width="19" height="19" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 478.125 478.125">';
|
58 |
+
html += '<g fill="currentcolor"">';
|
59 |
+
html += '<circle cx="239.904" cy="314.721" r="35.878"/>';
|
60 |
+
html += '<path d="M256.657,127.525h-31.9c-10.557,0-19.125,8.645-19.125,19.125v101.975c0,10.48,8.645,19.125,19.125,19.125h31.9c10.48,0,19.125-8.645,19.125-19.125V146.65C275.782,136.17,267.138,127.525,256.657,127.525z"/>';
|
61 |
+
html += '<path d="M239.062,0C106.947,0,0,106.947,0,239.062s106.947,239.062,239.062,239.062c132.115,0,239.062-106.947,239.062-239.062S371.178,0,239.062,0z M239.292,409.734c-94.171,0-170.595-76.348-170.595-170.596c0-94.248,76.347-170.595,170.595-170.595s170.595,76.347,170.595,170.595C409.887,333.387,333.464,409.734,239.292,409.734z"/>';
|
62 |
+
html += '</g></svg>';*/
|
63 |
+
html += '<svg id="status_warning" width="19" height="19" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123.996 123.996">';
|
64 |
+
html += '<circle cx="62" cy="67" r="35" color="black"/>';
|
65 |
+
html += '<g fill="currentcolor">';
|
66 |
+
html += '<path d="M9.821,118.048h104.4c7.3,0,12-7.7,8.7-14.2l-52.2-92.5c-3.601-7.199-13.9-7.199-17.5,0l-52.2,92.5C-2.179,110.348,2.521,118.048,9.821,118.048z M70.222,96.548c0,4.8-3.5,8.5-8.5,8.5s-8.5-3.7-8.5-8.5v-0.2c0-4.8,3.5-8.5,8.5-8.5s8.5,3.7,8.5,8.5V96.548z M57.121,34.048h9.801c2.699,0,4.3,2.3,4,5.2l-4.301,37.6c-0.3,2.7-2.1,4.4-4.6,4.4s-4.3-1.7-4.6-4.4l-4.301-37.6C52.821,36.348,54.422,34.048,57.121,34.048z"/>';
|
67 |
+
html += '</g></svg>';
|
68 |
+
|
69 |
+
|
70 |
+
html += '<div class="popup">';
|
71 |
+
|
72 |
+
if (converter['warnings'].join) {
|
73 |
+
if (converter['warnings'].filter) {
|
74 |
+
// remove duplicate warnings
|
75 |
+
converter['warnings'] = converter['warnings'].filter(function(item, pos, self) {
|
76 |
+
return self.indexOf(item) == pos;
|
77 |
+
})
|
78 |
+
}
|
79 |
+
html += '<p>Warnings were issued:</p>';
|
80 |
+
for (var i = 0; i<converter['warnings'].length; i++) {
|
81 |
+
html += '<p>' + webpexpress_escapeHTML(converter['warnings'][i]) + '</p>';
|
82 |
+
}
|
83 |
+
// TODO: Tell him to deactivate the converter - or perhaps do it automatically?
|
84 |
+
html += '<p>check conversion log for more insight (ie by clicking the "test" link a little left of this warning triangle)</p>';
|
85 |
+
}
|
86 |
+
|
87 |
+
html += '</div>';
|
88 |
+
} else if (converter.working) {
|
89 |
html += '<svg id="status_ok" width="19" height="19" version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.000000 256.000000" preserveAspectRatio="xMidYMid meet">';
|
90 |
html += '<g fill="currentcolor" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"/></g></svg>';
|
91 |
//html += '<div class="popup">' + converter['id'] + ' is operational</div>';
|
92 |
html += '<div class="popup">Operational</div>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
}
|
94 |
html += '</div>';
|
95 |
|
320 |
document.getElementById('cwebp_use_nice').checked = getConverterOption(converter, 'use-nice', true);
|
321 |
document.getElementById('cwebp_method').value = getConverterOption(converter, 'method', '');
|
322 |
document.getElementById('cwebp_try_common_system_paths').checked = getConverterOption(converter, 'try-common-system-paths', '');
|
323 |
+
document.getElementById('cwebp_skip_these_precompiled_binaries').value = getConverterOption(converter, 'skip-these-precompiled-binaries', '');
|
324 |
document.getElementById('cwebp_try_supplied_binary').checked = getConverterOption(converter, 'try-supplied-binary-for-os', '');
|
325 |
document.getElementById('cwebp_set_size').checked = getConverterOption(converter, 'set-size', '');
|
326 |
document.getElementById('cwebp_size_in_percentage').value = getConverterOption(converter, 'size-in-percentage', '');
|
404 |
var methodString = document.getElementById('cwebp_method').value;
|
405 |
var methodNum = (methodString == '') ? 6 : parseInt(methodString, 10);
|
406 |
setConverterOption(converter, 'method', methodNum);
|
407 |
+
setConverterOption(converter, 'skip-these-precompiled-binaries', document.getElementById('cwebp_skip_these_precompiled_binaries').value);
|
408 |
setConverterOption(converter, 'try-common-system-paths', document.getElementById('cwebp_try_common_system_paths').checked);
|
409 |
setConverterOption(converter, 'try-supplied-binary-for-os', document.getElementById('cwebp_try_supplied_binary').checked);
|
410 |
setConverterOption(converter, 'set-size', document.getElementById('cwebp_set_size').checked);
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -12,10 +12,16 @@
|
|
12 |
<br>If checked, we will look for binaries in common locations, such as <i>/usr/bin/cwebp</i>
|
13 |
</div>
|
14 |
<div>
|
15 |
-
<label for="
|
16 |
<input type="checkbox" id="cwebp_try_supplied_binary">
|
17 |
<br>This plugin ships with precompiled cweb binaries for different platforms. If checked, and we have a precompiled binary for your OS, we will try to exectute it
|
18 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
<div>
|
20 |
<label for="cwebp_method">Method (0-6)</label>
|
21 |
<input type="text" size="2" id="cwebp_method">
|
12 |
<br>If checked, we will look for binaries in common locations, such as <i>/usr/bin/cwebp</i>
|
13 |
</div>
|
14 |
<div>
|
15 |
+
<label for="cwebp_try_supplied_binary">Try precompiled cwebp</label>
|
16 |
<input type="checkbox" id="cwebp_try_supplied_binary">
|
17 |
<br>This plugin ships with precompiled cweb binaries for different platforms. If checked, and we have a precompiled binary for your OS, we will try to exectute it
|
18 |
</div>
|
19 |
+
<div>
|
20 |
+
<label for="cwebp_skip_these_precompiled_binaries">Skip these precompiled cwebp</label>
|
21 |
+
<input type="text" size="40" id="cwebp_skip_these_precompiled_binaries" style="width:100%">
|
22 |
+
<br>To skip precompiled binaries that are known not to work on current system (check the conversion log).
|
23 |
+
This will cut down on conversion time. Separate values with comma.
|
24 |
+
</div>
|
25 |
<div>
|
26 |
<label for="cwebp_method">Method (0-6)</label>
|
27 |
<input type="text" size="2" id="cwebp_method">
|
@@ -6,7 +6,7 @@
|
|
6 |
enables the varied image responses (such that a request for a jpeg/png will result in a webp on browsers that supports webp).
|
7 |
The first option makes this happen for images that are already converted. The second option makes it happen even for
|
8 |
images that has not yet been converted, by redirecting the request to the converter, which converts, saves and delivers.</p>
|
9 |
-
<p>The third option is only relevant if you are using Alter HTML
|
10 |
<?php elseif ($config['operation-mode'] == 'cdn-friendly') : ?>
|
11 |
<h2><i>.htaccess</i> rules for webp generation</h2>
|
12 |
<?php elseif ($config['operation-mode'] == 'no-conversion') : ?>
|
6 |
enables the varied image responses (such that a request for a jpeg/png will result in a webp on browsers that supports webp).
|
7 |
The first option makes this happen for images that are already converted. The second option makes it happen even for
|
8 |
images that has not yet been converted, by redirecting the request to the converter, which converts, saves and delivers.</p>
|
9 |
+
<p>The third option is only relevant if you are using Alter HTML and want to reference webps that haven't been converted yet.</p>
|
10 |
<?php elseif ($config['operation-mode'] == 'cdn-friendly') : ?>
|
11 |
<h2><i>.htaccess</i> rules for webp generation</h2>
|
12 |
<?php elseif ($config['operation-mode'] == 'no-conversion') : ?>
|
@@ -15,6 +15,7 @@ use \WebPExpress\PlatformInfo;
|
|
15 |
use \WebPExpress\State;
|
16 |
|
17 |
|
|
|
18 |
// TODO: Move most of this file into a ProblemDetector class (SystemHealth)
|
19 |
|
20 |
if (!(State::getState('configured', false))) {
|
@@ -69,6 +70,21 @@ if ($cacheEnablerActivated && !$webpEnabled) {
|
|
69 |
);
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
if (($config['operation-mode'] == 'cdn-friendly') && !$config['alter-html']['enabled']) {
|
73 |
//echo print_r(get_option('cache-enabler'), true);
|
74 |
|
15 |
use \WebPExpress\State;
|
16 |
|
17 |
|
18 |
+
|
19 |
// TODO: Move most of this file into a ProblemDetector class (SystemHealth)
|
20 |
|
21 |
if (!(State::getState('configured', false))) {
|
70 |
);
|
71 |
}
|
72 |
|
73 |
+
$elementorActivated = in_array('elementor/elementor.php', get_option('active_plugins', []));
|
74 |
+
if ($elementorActivated) {
|
75 |
+
try {
|
76 |
+
// The following is wrapped in a try statement because it depends on Elementor classes which might be subject to change
|
77 |
+
if (\Elementor\Plugin::$instance->experiments->is_feature_active( 'e_optimized_css_loading' ) === false) {
|
78 |
+
if ($config['redirect-to-existing-in-htaccess'] === false) {
|
79 |
+
DismissableMessages::addDismissableMessage('0.23.0/elementor');
|
80 |
+
}
|
81 |
+
}
|
82 |
+
} catch (\Exception $e) {
|
83 |
+
// Well, just bad luck.
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
|
88 |
if (($config['operation-mode'] == 'cdn-friendly') && !$config['alter-html']['enabled']) {
|
89 |
//echo print_r(get_option('cache-enabler'), true);
|
90 |
|
@@ -229,6 +229,7 @@ function webpexpress_getSanitizedConverters() {
|
|
229 |
// cwebp
|
230 |
"try-common-system-paths" => 'boolean',
|
231 |
"try-supplied-binary-for-os" => 'boolean',
|
|
|
232 |
"method" => 'integer', // 0-6,
|
233 |
"size-in-percentage" => 'integer', // 0-100
|
234 |
"low-memory" => 'boolean',
|
@@ -241,7 +242,7 @@ function webpexpress_getSanitizedConverters() {
|
|
241 |
"crypt-api-key-in-transfer" => 'boolean',
|
242 |
"new-api-key" => 'string',
|
243 |
|
244 |
-
|
245 |
"api-key" => 'string',
|
246 |
"api-key-2" => 'string',
|
247 |
];
|
229 |
// cwebp
|
230 |
"try-common-system-paths" => 'boolean',
|
231 |
"try-supplied-binary-for-os" => 'boolean',
|
232 |
+
"skip-these-precompiled-binaries" => 'string',
|
233 |
"method" => 'integer', // 0-6,
|
234 |
"size-in-percentage" => 'integer', // 0-100
|
235 |
"low-memory" => 'boolean',
|
242 |
"crypt-api-key-in-transfer" => 'boolean',
|
243 |
"new-api-key" => 'string',
|
244 |
|
245 |
+
//ewww
|
246 |
"api-key" => 'string',
|
247 |
"api-key-2" => 'string',
|
248 |
];
|
@@ -0,0 +1 @@
|
|
|
1 |
+
.splitpanes{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;height:100%}.splitpanes--vertical{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.splitpanes--horizontal{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.splitpanes--dragging *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.splitpanes__pane{width:100%;height:100%;overflow:hidden}.splitpanes--vertical .splitpanes__pane{-webkit-transition:width .2s ease-out;transition:width .2s ease-out}.splitpanes--horizontal .splitpanes__pane{-webkit-transition:height .2s ease-out;transition:height .2s ease-out}.splitpanes--dragging .splitpanes__pane{-webkit-transition:none;transition:none}.splitpanes__splitter{-ms-touch-action:none;touch-action:none}.splitpanes--vertical>.splitpanes__splitter{min-width:1px;cursor:col-resize}.splitpanes--horizontal>.splitpanes__splitter{min-height:1px;cursor:row-resize}.splitpanes.default-theme .splitpanes__pane{background-color:#f2f2f2}.splitpanes.default-theme .splitpanes__splitter{background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;-ms-flex-negative:0;flex-shrink:0}.splitpanes.default-theme .splitpanes__splitter:after,.splitpanes.default-theme .splitpanes__splitter:before{content:"";position:absolute;top:50%;left:50%;background-color:#00000026;-webkit-transition:background-color .3s;transition:background-color .3s}.splitpanes.default-theme .splitpanes__splitter:hover:after,.splitpanes.default-theme .splitpanes__splitter:hover:before{background-color:#00000040}.splitpanes.default-theme .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme.splitpanes--vertical>.splitpanes__splitter,.default-theme .splitpanes--vertical>.splitpanes__splitter{width:7px;border-left:1px solid #eee;margin-left:-1px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after,.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{-webkit-transform:translateY(-50%);transform:translateY(-50%);width:1px;height:30px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter,.default-theme .splitpanes--horizontal>.splitpanes__splitter{height:7px;border-top:1px solid #eee;margin-top:-1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after,.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{-webkit-transform:translateX(-50%);transform:translate(-50%);width:30px;height:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}.selectbox[data-v-3ed78ba0]{width:200px;position:relative;display:inline-block}.selectbox .box[data-v-3ed78ba0]{border:1px solid black;padding:5px 10px;width:100%;box-sizing:border-box;cursor:pointer;user-select:none}.selectbox .box[data-v-3ed78ba0]:after{position:absolute;content:"";top:14px;right:10px;width:0;height:0;border:6px solid transparent;border-color:black transparent transparent transparent}.selectbox .box.is-open[data-v-3ed78ba0]:after{border-color:transparent transparent black transparent;top:6px}.selectbox .dropdown[data-v-3ed78ba0]{position:absolute;z-index:100;background-color:#fff;border:1px solid #eee;left:0;right:0}.selectbox .dropdown .option[data-v-3ed78ba0]{padding:5px 10px;border-bottom:1px solid #eee}.selectbox .dropdown .option .icon[data-v-3ed78ba0]{width:18px;height:18px;float:right}.selectbox .dropdown .option[data-v-3ed78ba0]:hover{background-color:#eee;cursor:pointer;user-select:none}.help-icon{display:inline-block;margin-left:2px}.convert-option-menu{display:inline-block;margin-left:2px}.menu-inner{font-size:16px}.icon{width:16px;height:16px;vertical-align:top;padding:0 2px 1px}.buttons a:first-child{margin-left:0}.buttons a{margin:0 5px;background-color:#f5f5f5;border-radius:0;color:#000!important;padding:2px 10px;border-color:#fff;text-decoration:none!important;font-family:arial,sans-serif;font-size:13.33px;border-width:1px;border-style:solid;border-bottom-color:#ccc;border-right-color:#ccc}.buttons a:hover{background-color:#fff}.buttons a.mouse-down{border-bottom-color:#fff;border-right-color:#fff;border-top-color:#ccc;border-left-color:#ccc}input[data-v-641ada22]{width:100%}input.small[data-v-641ada22]{max-width:100px}.multiselect__option--selected .click-to-add{display:none}.click-to-add[data-v-6b6f53d2]{float:right;font-size:13px}.vue-toggles{cursor:pointer;display:flex;align-items:center;border-radius:9999px;overflow:hidden;transition:background-color ease .2s,width ease .2s,height ease .2s}.vue-toggles .dot{position:relative;display:flex;align-items:center;border-radius:9999px;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;transition:margin ease .2s}.vue-toggles .text{position:absolute;font-family:inherit;user-select:none;white-space:nowrap}@media all and (-ms-high-contrast: none){.vue-toggles .text{top:50%;transform:translateY(-50%)}}@media (prefers-reduced-motion){.vue-toggles,.vue-toggles *,.vue-toggles *:before,.vue-toggles *:after{animation:none!important;transition:none!important;transition-duration:none!important}}.slider-target,.slider-target *{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;touch-action:none;-ms-user-select:none;-moz-user-select:none;user-select:none;box-sizing:border-box}.slider-target{position:relative}.slider-base,.slider-connects{width:100%;height:100%;position:relative;z-index:1}.slider-connects{overflow:hidden;z-index:0}.slider-connect,.slider-origin{will-change:transform;position:absolute;z-index:1;top:0;right:0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;-webkit-transform-style:preserve-3d;transform-origin:0 0;transform-style:flat}.slider-connect{height:100%;width:100%}.slider-origin{height:10%;width:10%}.slider-txt-dir-rtl.slider-horizontal .slider-origin{left:0;right:auto}.slider-vertical .slider-origin{width:0}.slider-horizontal .slider-origin{height:0}.slider-handle{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute}.slider-touch-area{height:100%;width:100%}.slider-state-tap .slider-connect,.slider-state-tap .slider-origin{transition:transform .3s}.slider-state-drag *{cursor:inherit!important}.slider-horizontal{height:6px}.slider-horizontal .slider-handle{width:16px;height:16px;top:-6px;right:-8px}.slider-vertical{width:6px;height:300px}.slider-vertical .slider-handle{width:16px;height:16px;top:-8px;right:-6px}.slider-txt-dir-rtl.slider-horizontal .slider-handle{left:-8px;right:auto}.slider-base{background-color:#d4e0e7}.slider-base,.slider-connects{border-radius:3px}.slider-connect{background:#41b883;cursor:pointer}.slider-draggable{cursor:ew-resize}.slider-vertical .slider-draggable{cursor:ns-resize}.slider-handle{width:16px;height:16px;border-radius:50%;background:#fff;border:0;right:-8px;box-shadow:.5px .5px 2px 1px #00000052;cursor:-webkit-grab;cursor:grab}.slider-handle:focus{outline:none}.slider-active{box-shadow:.5px .5px 2px 1px #0000006b;cursor:-webkit-grabbing;cursor:grabbing}[disabled] .slider-connect{background:#b8b8b8}[disabled].slider-handle,[disabled] .slider-handle,[disabled].slider-target{cursor:not-allowed}[disabled] .slider-tooltip{background:#b8b8b8;border-color:#b8b8b8}.slider-tooltip{position:absolute;display:block;font-size:14px;font-weight:500;white-space:nowrap;padding:2px 5px;min-width:20px;text-align:center;color:#fff;border-radius:5px;border:1px solid #41b883;background:#41b883}.slider-horizontal .slider-tooltip{transform:translate(-50%);left:50%;bottom:24px}.slider-horizontal .slider-tooltip:before{content:"";position:absolute;bottom:-10px;left:50%;width:0;height:0;border:5px solid transparent;border-top-color:inherit;transform:translate(-50%)}.slider-vertical .slider-tooltip{transform:translateY(-50%);top:50%;right:24px}.slider-vertical .slider-tooltip:before{content:"";position:absolute;right:-10px;top:50%;width:0;height:0;border:5px solid transparent;border-left-color:inherit;transform:translateY(-50%)}.slider-horizontal .slider-origin>.slider-tooltip{transform:translate(50%);left:auto;bottom:14px}.slider-vertical .slider-origin>.slider-tooltip{transform:translateY(-18px);top:auto;right:18px}.slider-pips,.slider-pips *{box-sizing:border-box}.slider-pips{position:absolute;color:#999}.slider-value{position:absolute;white-space:nowrap;text-align:center}.slider-value-sub{color:#ccc;font-size:10px}.slider-marker{position:absolute;background:#ccc}.slider-marker-large,.slider-marker-sub{background:#aaa}.slider-pips-horizontal{padding:10px 0;height:80px;top:100%;left:0;width:100%}.slider-value-horizontal{transform:translate(-50%,50%)}.slider-rtl .slider-value-horizontal{transform:translate(50%,50%)}.slider-marker-horizontal.slider-marker{margin-left:-1px;width:2px;height:5px}.slider-marker-horizontal.slider-marker-sub{height:10px}.slider-marker-horizontal.slider-marker-large{height:15px}.slider-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.slider-value-vertical{transform:translateY(-50%);padding-left:25px}.slider-rtl .slider-value-vertical{transform:translateY(50%)}.slider-marker-vertical.slider-marker{width:5px;height:2px;margin-top:-1px}.slider-marker-vertical.slider-marker-sub{width:10px}.slider-marker-vertical.slider-marker-large{width:15px}.slider[data-v-636c0afb]{padding:10px 0}.slider .slider-connect{background-color:#0075ff}.slider .slider-tooltip{background-color:#0075ff;border-color:#0075ff;display:none}.slider:hover .slider-tooltip{display:block}.slider .slider-active .slider-tooltip{display:block}.convert-option>div[data-v-5def6a67]:first-child{min-width:210px;vertical-align:top;padding-top:10px}.convert-option>div[data-v-5def6a67]:last-child{width:300px;box-sizing:border-box}.convert-option input.method[data-v-5def6a67]{width:40px}.fade-enter-active[data-v-5def6a67]{transition:all 1s;opacity:0;transform:scale(0);transform:translate(30px)}.fade-enter-to[data-v-5def6a67]{opacity:1;transform:translate(0);transform:scale(1)}.fade-leave-active[data-v-5def6a67]{transition:all 1s;opacity:1}.fade-leave-to[data-v-5def6a67]{opacity:0}.view-select[data-v-563ca147]{display:block;text-align:right}.view *[data-v-563ca147]:first-child{display:inline-block;margin-right:10px}.view *[data-v-563ca147]:last-child{width:200px;display:inline-block}.fileitem.selected p[data-v-4fb0cc48]{background:#ccc!important}.fileitem[data-v-4fb0cc48]{vertical-align:middle;white-space:nowrap}.fileitem p[data-v-4fb0cc48]:hover{background:#eee}.fileitem p[data-v-4fb0cc48]{user-select:none;cursor:pointer;margin:0;padding:3px;line-height:25px;border-bottom:1px solid #f2f2f2}.fileitem p .fold-unfold[data-v-4fb0cc48]{user-select:none;cursor:pointer}.fileitem p .fold-unfold.empty[data-v-4fb0cc48]{visibility:hidden}.fileitem p svg.icon-unfold[data-v-4fb0cc48],.fileitem p svg.icon-fold[data-v-4fb0cc48]{width:12px;height:12px;vertical-align:middle;padding:3px;margin-right:3px;display:inline-block;border:0px solid grey}.fileitem p svg.icon-folder[data-v-4fb0cc48],.fileitem p svg.icon-file[data-v-4fb0cc48]{width:20px;height:20px;display:inline;vertical-align:middle;padding-top:1px;padding-bottom:2px;padding-right:5px}.fileitem p svg.icon-file[data-v-4fb0cc48]{margin-left:22px}ul{list-style-type:none;padding:0;margin:0}li{margin:0 0 0 20px}.modal-mask{position:fixed;z-index:9998;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:table}.modal-mask .modal-wrapper{height:100%;width:100%}.modal-mask .modal-wrapper .modal-container{padding:0;background-color:#fff;border-radius:2px;box-shadow:0 2px 8px #00000054;font-family:Helvetica,Arial,sans-serif;position:relative}.modal-mask .modal-wrapper .modal-container .title{position:absolute;left:0px;top:0;right:0;height:20px;background-color:#ccc;padding:5px 0 0 15px;font-size:14px;font-weight:bold}.modal-mask .modal-wrapper .modal-container .close-button{position:absolute;right:2px;top:2px;background-color:#fff;padding:2px 5px;font-size:12px;z-index:999;border-radius:20px;border:1px solid #ccc}.modal-mask .modal-wrapper .modal-container .close-button:hover{cursor:pointer}.modal-mask .modal-wrapper .modal-container .modal-body{position:absolute;top:25px;bottom:0px;left:0;right:0;overflow-y:auto;padding:20px}.modal-mask .modal-wrapper .modal-container .modal-body .close-button-with-text{text-align:right;margin-bottom:5px}.modal-mask .modal-wrapper .modal-container .modal-body .close-button-with-text button{padding:3px 20px}.modal-enter-active,.modal-leave-active{transition:opacity .5s ease}.modal-enter-from,.modal-leave-to{opacity:0}.image-viewport{position:relative}.image-viewport>.zoomer{width:100%;border:solid 1px silver;overflow:hidden}.image-viewport>.zoomer img{vertical-align:top;object-fit:contain;width:100%;height:100%;user-drag:none;-webkit-user-drag:none;-moz-user-drag:none}.image-viewport .zoom-info{display:none;position:absolute;bottom:0px;right:0px;padding:1px 4px;font-size:9px;background-color:#fff}.image-viewport:hover .zoom-info{display:block;cursor:pointer}.variant[data-v-0372e854]{display:inline-block;width:48%;margin-right:2%;margin-bottom:20px}.variant .header .title[data-v-0372e854]{display:inline-block}.variant .header .size[data-v-0372e854]{display:inline-block;float:right}.variant .header .zoom[data-v-0372e854]{display:inline-block;float:right;visibility:hidden}.variant .footer[data-v-0372e854]{font-style:italic;margin-top:2px}.variant .footer .select[data-v-0372e854]{float:right}.variant .footer .select button[data-v-0372e854]{padding:3px 10px}.variant:hover .header .zoom[data-v-0372e854]{visibility:visible}.variants-component .variants .variant.selected[data-v-25a3327e]{background-color:#ccc}.variants-component .variants .variant[data-v-25a3327e]{display:inline-block;width:47%;margin-right:1%;padding:1%;margin-bottom:20px}.variants-component .variants .variant .header .title[data-v-25a3327e]{display:inline-block}.variants-component .variants .variant .header .size[data-v-25a3327e]{display:inline-block;float:right}.variants-component .variants .variant .header .zoom[data-v-25a3327e]{display:inline-block;float:right;visibility:hidden}.variants-component .variants .variant .footer[data-v-25a3327e]{font-style:italic}.variants-component .variants .variant .footer .select[data-v-25a3327e]{float:right}.variants-component .variants .variant .footer .select button[data-v-25a3327e]{padding:3px 10px}.variants-component .variants .variant:hover .header .zoom[data-v-25a3327e]{visibility:visible}.file-properties .error[data-v-1f62a342]{color:red;font-weight:bold}.file-properties .path[data-v-1f62a342]{margin-bottom:20px}.file-properties .path .path[data-v-1f62a342]{color:#666;font-style:italic}.file-properties .log-button[data-v-1f62a342]{margin-left:15px}.file-properties .icon-converting[data-v-1f62a342]{padding:0 5px}.folder-properties .path{margin-bottom:20px}.folder-properties .path .path{color:#666;font-style:italic}.welcome{padding:20px 30px}.welcome h4{margin-bottom:3px}.welcome li{list-style-type:disc}.welcome ul{margin:0 0 20px}.welcome .headline h3{margin-top:0;padding-top:0;font-size:24px}.convertOptionsButton{position:absolute;right:10px;top:8px}.splitpanes__pane{background-color:#fff!important;padding:0;min-height:80px;box-shadow:inset 0 0 3px #0003}.pane-content{height:100%;overflow-y:auto}.pane-content>*{padding:10px 20px}body,html{height:100%;margin:0;padding:0}.mainpanel,#webpconvert-filemanager{height:100%;min-height:300px;position:relative}.mainpanel{min-height:400px}.wcfm,input{font-family:"Avenir",Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#222;font-size:14px}input{padding:5px 8px;border-color:#333;border-width:1px;box-sizing:border-box}div .multiselect{min-height:30px}div .multiselect__select{height:30px;line-height:16px;width:30px}div .multiselect__select:before{border-top-color:#000;border-width:6px 6px 0 6px}div .multiselect__single{margin-bottom:3px}div .multiselect__tags{border-color:#333;border-radius:0;padding:5px 40px 0 5px;min-height:30px}li.multiselect__element{margin-left:0}div .multiselect__tag{margin-bottom:0;padding-bottom:3px;padding-top:3px}fieldset[disabled] .multiselect{pointer-events:none}.multiselect__spinner{position:absolute;right:1px;top:1px;width:48px;height:35px;background:#fff;display:block}.multiselect__spinner:after,.multiselect__spinner:before{position:absolute;content:"";top:50%;left:50%;margin:-8px 0 0 -8px;width:16px;height:16px;border-radius:100%;border-color:#41b883 transparent transparent;border-style:solid;border-width:2px;box-shadow:0 0 0 1px transparent}.multiselect__spinner:before{-webkit-animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__spinner:after{-webkit-animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__loading-enter-active,.multiselect__loading-leave-active{transition:opacity .4s ease-in-out;opacity:1}.multiselect__loading-enter,.multiselect__loading-leave-active{opacity:0}.multiselect,.multiselect__input,.multiselect__single{font-family:inherit;font-size:16px;touch-action:manipulation}.multiselect{box-sizing:content-box;display:block;position:relative;width:100%;min-height:40px;text-align:left;color:#35495e}.multiselect *{box-sizing:border-box}.multiselect:focus{outline:none}.multiselect--disabled{background:#ededed;pointer-events:none;opacity:.6}.multiselect--active{z-index:50}.multiselect--active:not(.multiselect--above) .multiselect__current,.multiselect--active:not(.multiselect--above) .multiselect__input,.multiselect--active:not(.multiselect--above) .multiselect__tags{border-bottom-left-radius:0;border-bottom-right-radius:0}.multiselect--active .multiselect__select{transform:rotate(180deg)}.multiselect--above.multiselect--active .multiselect__current,.multiselect--above.multiselect--active .multiselect__input,.multiselect--above.multiselect--active .multiselect__tags{border-top-left-radius:0;border-top-right-radius:0}.multiselect__input,.multiselect__single{position:relative;display:inline-block;min-height:20px;line-height:20px;border:none;border-radius:5px;background:#fff;padding:0 0 0 5px;width:100%;transition:border .1s ease;box-sizing:border-box;margin-bottom:8px;vertical-align:top}.multiselect__input::-moz-placeholder{color:#35495e}.multiselect__input:-ms-input-placeholder{color:#35495e}.multiselect__input::placeholder{color:#35495e}.multiselect__tag~.multiselect__input,.multiselect__tag~.multiselect__single{width:auto}.multiselect__input:hover,.multiselect__single:hover{border-color:#cfcfcf}.multiselect__input:focus,.multiselect__single:focus{border-color:#a8a8a8;outline:none}.multiselect__single{padding-left:5px;margin-bottom:8px}.multiselect__tags-wrap{display:inline}.multiselect__tags{min-height:40px;display:block;padding:8px 40px 0 8px;border-radius:5px;border:1px solid #e8e8e8;background:#fff;font-size:14px}.multiselect__tag{position:relative;display:inline-block;padding:4px 26px 4px 10px;border-radius:5px;margin-right:10px;color:#fff;line-height:1;background:#41b883;margin-bottom:5px;white-space:nowrap;overflow:hidden;max-width:100%;text-overflow:ellipsis}.multiselect__tag-icon{cursor:pointer;margin-left:7px;position:absolute;right:0;top:0;bottom:0;font-weight:700;font-style:normal;width:22px;text-align:center;line-height:22px;transition:all .2s ease;border-radius:5px}.multiselect__tag-icon:after{content:"\d7";color:#266d4d;font-size:14px}.multiselect__tag-icon:focus:after,.multiselect__tag-icon:hover:after{color:#fff}.multiselect__current{min-height:40px;overflow:hidden;padding:8px 30px 0 12px;white-space:nowrap;border-radius:5px;border:1px solid #e8e8e8}.multiselect__current,.multiselect__select{line-height:16px;box-sizing:border-box;display:block;margin:0;text-decoration:none;cursor:pointer}.multiselect__select{position:absolute;width:40px;height:38px;right:1px;top:1px;padding:4px 8px;text-align:center;transition:transform .2s ease}.multiselect__select:before{position:relative;right:0;top:65%;color:#999;margin-top:4px;border-style:solid;border-width:5px 5px 0 5px;border-color:#999 transparent transparent transparent;content:""}.multiselect__placeholder{color:#adadad;display:inline-block;margin-bottom:10px;padding-top:2px}.multiselect--active .multiselect__placeholder{display:none}.multiselect__content-wrapper{position:absolute;display:block;background:#fff;width:100%;max-height:240px;overflow:auto;border:1px solid #e8e8e8;border-top:none;border-bottom-left-radius:5px;border-bottom-right-radius:5px;z-index:50;-webkit-overflow-scrolling:touch}.multiselect__content{list-style:none;display:inline-block;padding:0;margin:0;min-width:100%;vertical-align:top}.multiselect--above .multiselect__content-wrapper{bottom:100%;border-radius:5px 5px 0 0;border-bottom:none;border-top:1px solid #e8e8e8}.multiselect__content::-webkit-scrollbar{display:none}.multiselect__element{display:block}.multiselect__option{display:block;padding:12px;min-height:40px;line-height:16px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer;white-space:nowrap}.multiselect__option:after{top:0;right:0;position:absolute;line-height:40px;padding-right:12px;padding-left:20px;font-size:13px}.multiselect__option--highlight{background:#41b883;outline:none;color:#fff}.multiselect__option--highlight:after{content:attr(data-select);background:#41b883;color:#fff}.multiselect__option--selected{background:#f3f3f3;color:#35495e;font-weight:700}.multiselect__option--selected:after{content:attr(data-selected);color:silver}.multiselect__option--selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect--disabled .multiselect__current,.multiselect--disabled .multiselect__select{background:#ededed;color:#a6a6a6}.multiselect__option--disabled{background:#ededed!important;color:#a6a6a6!important;cursor:text;pointer-events:none}.multiselect__option--group{background:#ededed;color:#35495e}.multiselect__option--group.multiselect__option--highlight{background:#35495e;color:#fff}.multiselect__option--group.multiselect__option--highlight:after{background:#35495e}.multiselect__option--disabled.multiselect__option--highlight{background:#dedede}.multiselect__option--group-selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--group-selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect-enter-active,.multiselect-leave-active{transition:all .15s ease}.multiselect-enter,.multiselect-leave-active{opacity:0}.multiselect__strong{margin-bottom:8px;line-height:20px;display:inline-block;vertical-align:top}[dir=rtl] .multiselect{text-align:right}[dir=rtl] .multiselect__select{right:auto;left:1px}[dir=rtl] .multiselect__tags{padding:8px 8px 0 40px}[dir=rtl] .multiselect__content{text-align:right}[dir=rtl] .multiselect__option:after{right:auto;left:0}[dir=rtl] .multiselect__clear{right:auto;left:12px}[dir=rtl] .multiselect__spinner{right:auto;left:1px}@-webkit-keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}@keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}div.v-popper--theme-menu .v-popper__inner{background-color:#66f;color:#fff;padding:10px 15px 11px;line-height:1.2;max-width:300px}.v-popper__inner a{color:#fff;text-decoration:underline}.v-popper__inner p{margin-top:0}.v-popper__inner p:last-child{margin-bottom:0}.table-table{display:table}.table-table>*{display:table-row}.table-table>*>*{display:table-cell;padding:5px 20px 5px 0}.table-inline-block>div>*{display:inline-block;margin-right:10px;padding:5px 20px 5px 0}.table-inline-block>div>*:first-child{width:120px}.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;padding:24px;border-radius:6px;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow{border-color:#fff}.v-popper{width:max-content}.v-popper--theme-tooltip .v-popper__inner{background:rgba(0,0,0,.8);color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow{border-color:#000c}.v-popper__popper{z-index:10000}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__inner{position:relative}.v-popper__arrow-container{width:10px;height:10px}.v-popper__arrow{border-style:solid;position:relative;width:0;height:0}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow{border-width:5px 5px 0 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow{border-width:0 5px 5px 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important;top:-5px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow{border-width:5px 5px 5px 0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important;left:-5px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-5px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow{border-width:5px 0 5px 5px;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important;right:-5px}
|
@@ -1 +0,0 @@
|
|
1 |
-
.splitpanes{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;height:100%}.splitpanes--vertical{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.splitpanes--horizontal{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.splitpanes--dragging *{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.splitpanes__pane{width:100%;height:100%;overflow:hidden}.splitpanes--vertical .splitpanes__pane{-webkit-transition:width .2s ease-out;transition:width .2s ease-out}.splitpanes--horizontal .splitpanes__pane{-webkit-transition:height .2s ease-out;transition:height .2s ease-out}.splitpanes--dragging .splitpanes__pane{-webkit-transition:none;transition:none}.splitpanes__splitter{-ms-touch-action:none;touch-action:none}.splitpanes--vertical>.splitpanes__splitter{min-width:1px;cursor:col-resize}.splitpanes--horizontal>.splitpanes__splitter{min-height:1px;cursor:row-resize}.splitpanes.default-theme .splitpanes__pane{background-color:#f2f2f2}.splitpanes.default-theme .splitpanes__splitter{background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;-ms-flex-negative:0;flex-shrink:0}.splitpanes.default-theme .splitpanes__splitter:after,.splitpanes.default-theme .splitpanes__splitter:before{content:"";position:absolute;top:50%;left:50%;background-color:#00000026;-webkit-transition:background-color .3s;transition:background-color .3s}.splitpanes.default-theme .splitpanes__splitter:hover:after,.splitpanes.default-theme .splitpanes__splitter:hover:before{background-color:#00000040}.splitpanes.default-theme .splitpanes__splitter:first-child{cursor:auto}.default-theme.splitpanes .splitpanes .splitpanes__splitter{z-index:1}.default-theme.splitpanes--vertical>.splitpanes__splitter,.default-theme .splitpanes--vertical>.splitpanes__splitter{width:7px;border-left:1px solid #eee;margin-left:-1px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after,.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{-webkit-transform:translateY(-50%);transform:translateY(-50%);width:1px;height:30px}.default-theme.splitpanes--vertical>.splitpanes__splitter:before,.default-theme .splitpanes--vertical>.splitpanes__splitter:before{margin-left:-2px}.default-theme.splitpanes--vertical>.splitpanes__splitter:after,.default-theme .splitpanes--vertical>.splitpanes__splitter:after{margin-left:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter,.default-theme .splitpanes--horizontal>.splitpanes__splitter{height:7px;border-top:1px solid #eee;margin-top:-1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after,.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{-webkit-transform:translateX(-50%);transform:translate(-50%);width:30px;height:1px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:before,.default-theme .splitpanes--horizontal>.splitpanes__splitter:before{margin-top:-2px}.default-theme.splitpanes--horizontal>.splitpanes__splitter:after,.default-theme .splitpanes--horizontal>.splitpanes__splitter:after{margin-top:1px}.selectbox[data-v-3ed78ba0]{width:200px;position:relative;display:inline-block}.selectbox .box[data-v-3ed78ba0]{border:1px solid black;padding:5px 10px;width:100%;box-sizing:border-box;cursor:pointer;user-select:none}.selectbox .box[data-v-3ed78ba0]:after{position:absolute;content:"";top:14px;right:10px;width:0;height:0;border:6px solid transparent;border-color:black transparent transparent transparent}.selectbox .box.is-open[data-v-3ed78ba0]:after{border-color:transparent transparent black transparent;top:6px}.selectbox .dropdown[data-v-3ed78ba0]{position:absolute;z-index:100;background-color:#fff;border:1px solid #eee;left:0;right:0}.selectbox .dropdown .option[data-v-3ed78ba0]{padding:5px 10px;border-bottom:1px solid #eee}.selectbox .dropdown .option .icon[data-v-3ed78ba0]{width:18px;height:18px;float:right}.selectbox .dropdown .option[data-v-3ed78ba0]:hover{background-color:#eee;cursor:pointer;user-select:none}.help-icon{display:inline-block;margin-left:2px}.convert-option-menu{display:inline-block;margin-left:2px}.menu-inner{font-size:16px}.icon{width:16px;height:16px;vertical-align:top;padding:0 2px 1px}.buttons a:first-child{margin-left:0}.buttons a{margin:0 5px;background-color:#f5f5f5;border-radius:0;color:#000!important;padding:2px 10px;border-color:#fff;text-decoration:none!important;font-family:arial,sans-serif;font-size:13.33px;border-width:1px;border-style:solid;border-bottom-color:#ccc;border-right-color:#ccc}.buttons a:hover{background-color:#fff}.buttons a.mouse-down{border-bottom-color:#fff;border-right-color:#fff;border-top-color:#ccc;border-left-color:#ccc}input[data-v-641ada22]{width:100%}input.small[data-v-641ada22]{max-width:100px}.multiselect__option--selected .click-to-add{display:none}.click-to-add[data-v-6b6f53d2]{float:right;font-size:13px}.vue-toggles{cursor:pointer;display:flex;align-items:center;border-radius:9999px;overflow:hidden;transition:background-color ease .2s,width ease .2s,height ease .2s}.vue-toggles .dot{position:relative;display:flex;align-items:center;border-radius:9999px;box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f;transition:margin ease .2s}.vue-toggles .text{position:absolute;font-family:inherit;user-select:none;white-space:nowrap}@media all and (-ms-high-contrast: none){.vue-toggles .text{top:50%;transform:translateY(-50%)}}@media (prefers-reduced-motion){.vue-toggles,.vue-toggles *,.vue-toggles *:before,.vue-toggles *:after{animation:none!important;transition:none!important;transition-duration:none!important}}.slider-target,.slider-target *{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;touch-action:none;-ms-user-select:none;-moz-user-select:none;user-select:none;box-sizing:border-box}.slider-target{position:relative}.slider-base,.slider-connects{width:100%;height:100%;position:relative;z-index:1}.slider-connects{overflow:hidden;z-index:0}.slider-connect,.slider-origin{will-change:transform;position:absolute;z-index:1;top:0;right:0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;-webkit-transform-style:preserve-3d;transform-origin:0 0;transform-style:flat}.slider-connect{height:100%;width:100%}.slider-origin{height:10%;width:10%}.slider-txt-dir-rtl.slider-horizontal .slider-origin{left:0;right:auto}.slider-vertical .slider-origin{width:0}.slider-horizontal .slider-origin{height:0}.slider-handle{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute}.slider-touch-area{height:100%;width:100%}.slider-state-tap .slider-connect,.slider-state-tap .slider-origin{transition:transform .3s}.slider-state-drag *{cursor:inherit!important}.slider-horizontal{height:6px}.slider-horizontal .slider-handle{width:16px;height:16px;top:-6px;right:-8px}.slider-vertical{width:6px;height:300px}.slider-vertical .slider-handle{width:16px;height:16px;top:-8px;right:-6px}.slider-txt-dir-rtl.slider-horizontal .slider-handle{left:-8px;right:auto}.slider-base{background-color:#d4e0e7}.slider-base,.slider-connects{border-radius:3px}.slider-connect{background:#41b883;cursor:pointer}.slider-draggable{cursor:ew-resize}.slider-vertical .slider-draggable{cursor:ns-resize}.slider-handle{width:16px;height:16px;border-radius:50%;background:#fff;border:0;right:-8px;box-shadow:.5px .5px 2px 1px #00000052;cursor:-webkit-grab;cursor:grab}.slider-handle:focus{outline:none}.slider-active{box-shadow:.5px .5px 2px 1px #0000006b;cursor:-webkit-grabbing;cursor:grabbing}[disabled] .slider-connect{background:#b8b8b8}[disabled].slider-handle,[disabled] .slider-handle,[disabled].slider-target{cursor:not-allowed}[disabled] .slider-tooltip{background:#b8b8b8;border-color:#b8b8b8}.slider-tooltip{position:absolute;display:block;font-size:14px;font-weight:500;white-space:nowrap;padding:2px 5px;min-width:20px;text-align:center;color:#fff;border-radius:5px;border:1px solid #41b883;background:#41b883}.slider-horizontal .slider-tooltip{transform:translate(-50%);left:50%;bottom:24px}.slider-horizontal .slider-tooltip:before{content:"";position:absolute;bottom:-10px;left:50%;width:0;height:0;border:5px solid transparent;border-top-color:inherit;transform:translate(-50%)}.slider-vertical .slider-tooltip{transform:translateY(-50%);top:50%;right:24px}.slider-vertical .slider-tooltip:before{content:"";position:absolute;right:-10px;top:50%;width:0;height:0;border:5px solid transparent;border-left-color:inherit;transform:translateY(-50%)}.slider-horizontal .slider-origin>.slider-tooltip{transform:translate(50%);left:auto;bottom:14px}.slider-vertical .slider-origin>.slider-tooltip{transform:translateY(-18px);top:auto;right:18px}.slider-pips,.slider-pips *{box-sizing:border-box}.slider-pips{position:absolute;color:#999}.slider-value{position:absolute;white-space:nowrap;text-align:center}.slider-value-sub{color:#ccc;font-size:10px}.slider-marker{position:absolute;background:#ccc}.slider-marker-large,.slider-marker-sub{background:#aaa}.slider-pips-horizontal{padding:10px 0;height:80px;top:100%;left:0;width:100%}.slider-value-horizontal{transform:translate(-50%,50%)}.slider-rtl .slider-value-horizontal{transform:translate(50%,50%)}.slider-marker-horizontal.slider-marker{margin-left:-1px;width:2px;height:5px}.slider-marker-horizontal.slider-marker-sub{height:10px}.slider-marker-horizontal.slider-marker-large{height:15px}.slider-pips-vertical{padding:0 10px;height:100%;top:0;left:100%}.slider-value-vertical{transform:translateY(-50%);padding-left:25px}.slider-rtl .slider-value-vertical{transform:translateY(50%)}.slider-marker-vertical.slider-marker{width:5px;height:2px;margin-top:-1px}.slider-marker-vertical.slider-marker-sub{width:10px}.slider-marker-vertical.slider-marker-large{width:15px}.slider[data-v-636c0afb]{padding:10px 0}.slider .slider-connect{background-color:#0075ff}.slider .slider-tooltip{background-color:#0075ff;border-color:#0075ff;display:none}.slider:hover .slider-tooltip{display:block}.slider .slider-active .slider-tooltip{display:block}.convert-option>div[data-v-5def6a67]:first-child{min-width:210px;vertical-align:top;padding-top:10px}.convert-option>div[data-v-5def6a67]:last-child{width:300px;box-sizing:border-box}.convert-option input.method[data-v-5def6a67]{width:40px}.fade-enter-active[data-v-5def6a67]{transition:all 1s;opacity:0;transform:scale(0);transform:translate(30px)}.fade-enter-to[data-v-5def6a67]{opacity:1;transform:translate(0);transform:scale(1)}.fade-leave-active[data-v-5def6a67]{transition:all 1s;opacity:1}.fade-leave-to[data-v-5def6a67]{opacity:0}.view-select[data-v-563ca147]{display:block;text-align:right}.view *[data-v-563ca147]:first-child{display:inline-block;margin-right:10px}.view *[data-v-563ca147]:last-child{width:200px;display:inline-block}.fileitem.selected p[data-v-4fb0cc48]{background:#ccc!important}.fileitem[data-v-4fb0cc48]{vertical-align:middle;white-space:nowrap}.fileitem p[data-v-4fb0cc48]:hover{background:#eee}.fileitem p[data-v-4fb0cc48]{user-select:none;cursor:pointer;margin:0;padding:3px;line-height:25px;border-bottom:1px solid #f2f2f2}.fileitem p .fold-unfold[data-v-4fb0cc48]{user-select:none;cursor:pointer}.fileitem p .fold-unfold.empty[data-v-4fb0cc48]{visibility:hidden}.fileitem p svg.icon-unfold[data-v-4fb0cc48],.fileitem p svg.icon-fold[data-v-4fb0cc48]{width:12px;height:12px;vertical-align:middle;padding:3px;margin-right:3px;display:inline-block;border:0px solid grey}.fileitem p svg.icon-folder[data-v-4fb0cc48],.fileitem p svg.icon-file[data-v-4fb0cc48]{width:20px;height:20px;display:inline;vertical-align:middle;padding-top:1px;padding-bottom:2px;padding-right:5px}.fileitem p svg.icon-file[data-v-4fb0cc48]{margin-left:22px}ul{list-style-type:none;padding:0;margin:0}li{margin:0 0 0 20px}.modal-mask{position:fixed;z-index:9998;top:0;left:0;width:100%;height:100%;background-color:#00000080;display:table}.modal-mask .modal-wrapper{height:100%;width:100%;padding-top:30px}.modal-mask .modal-wrapper .modal-container{padding:0;background-color:#fff;border-radius:2px;box-shadow:0 2px 8px #00000054;font-family:Helvetica,Arial,sans-serif;position:relative}.modal-mask .modal-wrapper .modal-container .title{position:absolute;left:0px;top:0;right:0;height:20px;background-color:#ccc;padding:5px 0 0 15px;font-size:14px;font-weight:bold}.modal-mask .modal-wrapper .modal-container .close-button{position:absolute;right:2px;top:2px;background-color:#fff;padding:2px 5px;font-size:12px;z-index:999;border-radius:20px;border:1px solid #ccc}.modal-mask .modal-wrapper .modal-container .close-button:hover{cursor:pointer}.modal-mask .modal-wrapper .modal-container .modal-body{position:absolute;top:25px;bottom:0px;left:0;right:0;overflow-y:auto;padding:20px}.modal-mask .modal-wrapper .modal-container .modal-body .close-button-with-text{text-align:right;margin-bottom:5px}.modal-mask .modal-wrapper .modal-container .modal-body .close-button-with-text button{padding:3px 20px}.modal-enter-active,.modal-leave-active{transition:opacity .5s ease}.modal-enter-from,.modal-leave-to{opacity:0}.image-viewport{position:relative}.image-viewport>.zoomer{width:100%;border:solid 1px silver;overflow:hidden}.image-viewport>.zoomer img{vertical-align:top;object-fit:contain;width:100%;height:100%;user-drag:none;-webkit-user-drag:none;-moz-user-drag:none}.image-viewport .zoom-info{display:none;position:absolute;bottom:0px;right:0px;padding:1px 4px;font-size:9px;background-color:#fff}.image-viewport:hover .zoom-info{display:block;cursor:pointer}.variant[data-v-0372e854]{display:inline-block;width:48%;margin-right:2%;margin-bottom:20px}.variant .header .title[data-v-0372e854]{display:inline-block}.variant .header .size[data-v-0372e854]{display:inline-block;float:right}.variant .header .zoom[data-v-0372e854]{display:inline-block;float:right;visibility:hidden}.variant .footer[data-v-0372e854]{font-style:italic;margin-top:2px}.variant .footer .select[data-v-0372e854]{float:right}.variant .footer .select button[data-v-0372e854]{padding:3px 10px}.variant:hover .header .zoom[data-v-0372e854]{visibility:visible}.variants-component .variants .variant.selected[data-v-25a3327e]{background-color:#ccc}.variants-component .variants .variant[data-v-25a3327e]{display:inline-block;width:47%;margin-right:1%;padding:1%;margin-bottom:20px}.variants-component .variants .variant .header .title[data-v-25a3327e]{display:inline-block}.variants-component .variants .variant .header .size[data-v-25a3327e]{display:inline-block;float:right}.variants-component .variants .variant .header .zoom[data-v-25a3327e]{display:inline-block;float:right;visibility:hidden}.variants-component .variants .variant .footer[data-v-25a3327e]{font-style:italic}.variants-component .variants .variant .footer .select[data-v-25a3327e]{float:right}.variants-component .variants .variant .footer .select button[data-v-25a3327e]{padding:3px 10px}.variants-component .variants .variant:hover .header .zoom[data-v-25a3327e]{visibility:visible}.file-properties .error[data-v-32d950b3]{color:red;font-weight:bold}.file-properties .path[data-v-32d950b3]{margin-bottom:20px}.file-properties .path .path[data-v-32d950b3]{color:#666;font-style:italic}.folder-properties .path{margin-bottom:20px}.folder-properties .path .path{color:#666;font-style:italic}.welcome{padding:20px 30px}.welcome h4{margin-bottom:3px}.welcome li{list-style-type:disc}.welcome ul{margin:0 0 20px}.welcome .headline h3{margin-top:0;padding-top:0;font-size:24px}.convertOptionsButton{position:absolute;right:10px;top:8px}.splitpanes__pane{background-color:#fff!important;padding:0;min-height:80px;box-shadow:inset 0 0 3px #0003}.pane-content{height:100%;overflow-y:auto}.pane-content>*{padding:10px 20px}body,html{height:100%;margin:0;padding:0}.mainpanel,#webpconvert-filemanager{height:100%;min-height:300px;position:relative}.mainpanel{min-height:400px}.wcfm,input{font-family:"Avenir",Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#222;font-size:14px}input{padding:5px 8px;border-color:#333;border-width:1px;box-sizing:border-box}div .multiselect{min-height:30px}div .multiselect__select{height:30px;line-height:16px;width:30px}div .multiselect__select:before{border-top-color:#000;border-width:6px 6px 0 6px}div .multiselect__single{margin-bottom:3px}div .multiselect__tags{border-color:#333;border-radius:0;padding:5px 40px 0 5px;min-height:30px}li.multiselect__element{margin-left:0}div .multiselect__tag{margin-bottom:0;padding-bottom:3px;padding-top:3px}fieldset[disabled] .multiselect{pointer-events:none}.multiselect__spinner{position:absolute;right:1px;top:1px;width:48px;height:35px;background:#fff;display:block}.multiselect__spinner:after,.multiselect__spinner:before{position:absolute;content:"";top:50%;left:50%;margin:-8px 0 0 -8px;width:16px;height:16px;border-radius:100%;border-color:#41b883 transparent transparent;border-style:solid;border-width:2px;box-shadow:0 0 0 1px transparent}.multiselect__spinner:before{-webkit-animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);animation:spinning 2.4s cubic-bezier(.41,.26,.2,.62);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__spinner:after{-webkit-animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);animation:spinning 2.4s cubic-bezier(.51,.09,.21,.8);-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.multiselect__loading-enter-active,.multiselect__loading-leave-active{transition:opacity .4s ease-in-out;opacity:1}.multiselect__loading-enter,.multiselect__loading-leave-active{opacity:0}.multiselect,.multiselect__input,.multiselect__single{font-family:inherit;font-size:16px;touch-action:manipulation}.multiselect{box-sizing:content-box;display:block;position:relative;width:100%;min-height:40px;text-align:left;color:#35495e}.multiselect *{box-sizing:border-box}.multiselect:focus{outline:none}.multiselect--disabled{background:#ededed;pointer-events:none;opacity:.6}.multiselect--active{z-index:50}.multiselect--active:not(.multiselect--above) .multiselect__current,.multiselect--active:not(.multiselect--above) .multiselect__input,.multiselect--active:not(.multiselect--above) .multiselect__tags{border-bottom-left-radius:0;border-bottom-right-radius:0}.multiselect--active .multiselect__select{transform:rotate(180deg)}.multiselect--above.multiselect--active .multiselect__current,.multiselect--above.multiselect--active .multiselect__input,.multiselect--above.multiselect--active .multiselect__tags{border-top-left-radius:0;border-top-right-radius:0}.multiselect__input,.multiselect__single{position:relative;display:inline-block;min-height:20px;line-height:20px;border:none;border-radius:5px;background:#fff;padding:0 0 0 5px;width:100%;transition:border .1s ease;box-sizing:border-box;margin-bottom:8px;vertical-align:top}.multiselect__input::-moz-placeholder{color:#35495e}.multiselect__input:-ms-input-placeholder{color:#35495e}.multiselect__input::placeholder{color:#35495e}.multiselect__tag~.multiselect__input,.multiselect__tag~.multiselect__single{width:auto}.multiselect__input:hover,.multiselect__single:hover{border-color:#cfcfcf}.multiselect__input:focus,.multiselect__single:focus{border-color:#a8a8a8;outline:none}.multiselect__single{padding-left:5px;margin-bottom:8px}.multiselect__tags-wrap{display:inline}.multiselect__tags{min-height:40px;display:block;padding:8px 40px 0 8px;border-radius:5px;border:1px solid #e8e8e8;background:#fff;font-size:14px}.multiselect__tag{position:relative;display:inline-block;padding:4px 26px 4px 10px;border-radius:5px;margin-right:10px;color:#fff;line-height:1;background:#41b883;margin-bottom:5px;white-space:nowrap;overflow:hidden;max-width:100%;text-overflow:ellipsis}.multiselect__tag-icon{cursor:pointer;margin-left:7px;position:absolute;right:0;top:0;bottom:0;font-weight:700;font-style:normal;width:22px;text-align:center;line-height:22px;transition:all .2s ease;border-radius:5px}.multiselect__tag-icon:after{content:"\d7";color:#266d4d;font-size:14px}.multiselect__tag-icon:focus:after,.multiselect__tag-icon:hover:after{color:#fff}.multiselect__current{min-height:40px;overflow:hidden;padding:8px 30px 0 12px;white-space:nowrap;border-radius:5px;border:1px solid #e8e8e8}.multiselect__current,.multiselect__select{line-height:16px;box-sizing:border-box;display:block;margin:0;text-decoration:none;cursor:pointer}.multiselect__select{position:absolute;width:40px;height:38px;right:1px;top:1px;padding:4px 8px;text-align:center;transition:transform .2s ease}.multiselect__select:before{position:relative;right:0;top:65%;color:#999;margin-top:4px;border-style:solid;border-width:5px 5px 0 5px;border-color:#999 transparent transparent transparent;content:""}.multiselect__placeholder{color:#adadad;display:inline-block;margin-bottom:10px;padding-top:2px}.multiselect--active .multiselect__placeholder{display:none}.multiselect__content-wrapper{position:absolute;display:block;background:#fff;width:100%;max-height:240px;overflow:auto;border:1px solid #e8e8e8;border-top:none;border-bottom-left-radius:5px;border-bottom-right-radius:5px;z-index:50;-webkit-overflow-scrolling:touch}.multiselect__content{list-style:none;display:inline-block;padding:0;margin:0;min-width:100%;vertical-align:top}.multiselect--above .multiselect__content-wrapper{bottom:100%;border-radius:5px 5px 0 0;border-bottom:none;border-top:1px solid #e8e8e8}.multiselect__content::-webkit-scrollbar{display:none}.multiselect__element{display:block}.multiselect__option{display:block;padding:12px;min-height:40px;line-height:16px;text-decoration:none;text-transform:none;vertical-align:middle;position:relative;cursor:pointer;white-space:nowrap}.multiselect__option:after{top:0;right:0;position:absolute;line-height:40px;padding-right:12px;padding-left:20px;font-size:13px}.multiselect__option--highlight{background:#41b883;outline:none;color:#fff}.multiselect__option--highlight:after{content:attr(data-select);background:#41b883;color:#fff}.multiselect__option--selected{background:#f3f3f3;color:#35495e;font-weight:700}.multiselect__option--selected:after{content:attr(data-selected);color:silver}.multiselect__option--selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect--disabled .multiselect__current,.multiselect--disabled .multiselect__select{background:#ededed;color:#a6a6a6}.multiselect__option--disabled{background:#ededed!important;color:#a6a6a6!important;cursor:text;pointer-events:none}.multiselect__option--group{background:#ededed;color:#35495e}.multiselect__option--group.multiselect__option--highlight{background:#35495e;color:#fff}.multiselect__option--group.multiselect__option--highlight:after{background:#35495e}.multiselect__option--disabled.multiselect__option--highlight{background:#dedede}.multiselect__option--group-selected.multiselect__option--highlight{background:#ff6a6a;color:#fff}.multiselect__option--group-selected.multiselect__option--highlight:after{background:#ff6a6a;content:attr(data-deselect);color:#fff}.multiselect-enter-active,.multiselect-leave-active{transition:all .15s ease}.multiselect-enter,.multiselect-leave-active{opacity:0}.multiselect__strong{margin-bottom:8px;line-height:20px;display:inline-block;vertical-align:top}[dir=rtl] .multiselect{text-align:right}[dir=rtl] .multiselect__select{right:auto;left:1px}[dir=rtl] .multiselect__tags{padding:8px 8px 0 40px}[dir=rtl] .multiselect__content{text-align:right}[dir=rtl] .multiselect__option:after{right:auto;left:0}[dir=rtl] .multiselect__clear{right:auto;left:12px}[dir=rtl] .multiselect__spinner{right:auto;left:1px}@-webkit-keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}@keyframes spinning{0%{transform:rotate(0)}to{transform:rotate(2turn)}}div.v-popper--theme-menu .v-popper__inner{background-color:#66f;color:#fff;padding:10px 15px 11px;line-height:1.2;max-width:300px}.v-popper__inner a{color:#fff;text-decoration:underline}.v-popper__inner p{margin-top:0}.v-popper__inner p:last-child{margin-bottom:0}.table-table{display:table}.table-table>*{display:table-row}.table-table>*>*{display:table-cell;padding:5px 20px 5px 0}.table-inline-block>div>*{display:inline-block;margin-right:10px;padding:5px 20px 5px 0}.table-inline-block>div>*:first-child{width:120px}.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;padding:24px;border-radius:6px;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow{border-color:#fff}.v-popper{width:max-content}.v-popper--theme-tooltip .v-popper__inner{background:rgba(0,0,0,.8);color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow{border-color:#000c}.v-popper__popper{z-index:10000}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__inner{position:relative}.v-popper__arrow-container{width:10px;height:10px}.v-popper__arrow{border-style:solid;position:relative;width:0;height:0}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow{border-width:5px 5px 0 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow{border-width:0 5px 5px 5px;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important;top:-5px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow{border-width:5px 5px 5px 0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important;left:-5px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-5px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow{border-width:5px 0 5px 5px;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important;right:-5px}
|
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import{_ as f,o as l,c,a as R,b as a,n as S,d as u,e as y,t as p,p as V,f as I,r as m,g as _,F as x,h as Y,i as z,j as D,k as H,m as j,V as O,w as b,l as $,v as k,s as X,q as B,u as U}from"./vendor.b4e4e155.js";const A=function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&n(r)}).observe(document,{childList:!0,subtree:!0});function s(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerpolicy&&(i.referrerPolicy=o.referrerpolicy),o.crossorigin==="use-credentials"?i.credentials="include":o.crossorigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(o){if(o.ep)return;o.ep=!0;const i=s(o);fetch(o.href,i)}};A();class v{static post(e,s,n){var o=this;window.wcfmoptions.poster(e,s,function(i){n.call(o,i)},function(){console.log("failure")})}}const E={},q={style:{position:"absolute",width:"0",height:"0"},width:"0",height:"0",version:"1.1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"},G=R(`<defs><symbol id="icon-folder" viewBox="0 0 309.267 309.267"><g><path style="fill:#D0994B;" d="M260.944,43.491H125.64c0,0-18.324-28.994-28.994-28.994H48.323c-10.67,0-19.329,8.65-19.329,19.329
|
2 |
+
v222.286c0,10.67,8.659,19.329,19.329,19.329h212.621c10.67,0,19.329-8.659,19.329-19.329V62.82
|
3 |
+
C280.273,52.15,271.614,43.491,260.944,43.491z"></path><path style="fill:#E4E7E7;" d="M28.994,72.484h251.279v77.317H28.994V72.484z"></path><path style="fill:#F4B459;" d="M19.329,91.814h270.609c10.67,0,19.329,8.65,19.329,19.329l-19.329,164.298
|
4 |
+
c0,10.67-8.659,19.329-19.329,19.329H38.658c-10.67,0-19.329-8.659-19.329-19.329L0,111.143C0,100.463,8.659,91.814,19.329,91.814z
|
5 |
+
"></path></g></symbol><symbol id="icon-unfold" viewBox="0 0 32 32"><path d="M28,14H18V4c0-1.104-0.896-2-2-2s-2,0.896-2,2v10H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h10v10c0,1.104,0.896,2,2,2 s2-0.896,2-2V18h10c1.104,0,2-0.896,2-2S29.104,14,28,14z"></path></symbol><symbol id="icon-fold" viewBox="0 0 24 24"><g fill="none" stroke="#000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line></g></symbol><symbol id="icon-file" viewBox="0 0 56 56"><g><path style="fill:#E9E9E0;" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074
|
6 |
+
c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"></path><polygon style="fill:#D9D7CA;" points="37.5,0.151 37.5,12 49.349,12 "></polygon><circle style="fill:#F3D55B;" cx="18.931" cy="14.431" r="4.569"></circle><polygon style="fill:#c5e8e1;" points="6.5,39 17.5,39 49.5,39 49.5,28 39.5,18.5 29,30 23.517,24.517 "></polygon><path style="fill:#14A085;" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"></path><g></g></g></symbol><svg id="icon-ok" viewBox="0 0 256 256"><g fill="green" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"></path></g></svg><svg id="icon-not-available" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet"><g fill="#b11010" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"></path></g></svg><svg id="icon-help" viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve"><g><path style="fill:#cccccc;" d="M199.996,0C89.719,0,0,89.72,0,200c0,110.279,89.719,200,199.996,200C310.281,400,400,310.279,400,200
|
7 |
+
C400,89.72,310.281,0,199.996,0z M199.996,373.77C104.187,373.77,26.23,295.816,26.23,200
|
8 |
+
c0-95.817,77.957-173.769,173.766-173.769c95.816,0,173.772,77.953,173.772,173.769
|
9 |
+
C373.769,295.816,295.812,373.77,199.996,373.77z"></path><path style="fill:#000000;" d="M199.996,91.382c-35.176,0-63.789,28.616-63.789,63.793c0,7.243,5.871,13.115,13.113,13.115
|
10 |
+
c7.246,0,13.117-5.873,13.117-13.115c0-20.71,16.848-37.562,37.559-37.562c20.719,0,37.566,16.852,37.566,37.562
|
11 |
+
c0,20.714-16.849,37.566-37.566,37.566c-7.242,0-13.113,5.873-13.113,13.114v45.684c0,7.243,5.871,13.115,13.113,13.115
|
12 |
+
s13.117-5.872,13.117-13.115v-33.938c28.905-6.064,50.68-31.746,50.68-62.427C263.793,119.998,235.176,91.382,199.996,91.382z"></path><path d="M200.004,273.738c-9.086,0-16.465,7.371-16.465,16.462s7.379,16.465,16.465,16.465c9.094,0,16.457-7.374,16.457-16.465
|
13 |
+
S209.098,273.738,200.004,273.738z"></path></g></svg><svg id="icon-help2" viewBox="0 0 431.855 431.855" style="enable-background:new 0 0 431.855 431.855;" xml:space="preserve"><g><path style="fill:#aaaaaa;" d="M215.936,0C96.722,0,0.008,96.592,0.008,215.814c0,119.336,96.714,216.041,215.927,216.041
|
14 |
+
c119.279,0,215.911-96.706,215.911-216.041C431.847,96.592,335.214,0,215.936,0z M231.323,335.962
|
15 |
+
c-5.015,4.463-10.827,6.706-17.411,6.706c-6.812,0-12.754-2.203-17.826-6.617c-5.08-4.406-7.625-10.575-7.625-18.501
|
16 |
+
c0-7.031,2.463-12.949,7.373-17.745c4.91-4.796,10.933-7.194,18.078-7.194c7.031,0,12.949,2.398,17.753,7.194
|
17 |
+
c4.796,4.796,7.202,10.713,7.202,17.745C238.858,325.362,236.346,331.5,231.323,335.962z M293.856,180.934
|
18 |
+
c-3.853,7.145-8.429,13.306-13.737,18.501c-5.292,5.194-14.81,13.924-28.548,26.198c-3.788,3.463-6.836,6.503-9.12,9.12
|
19 |
+
c-2.284,2.626-3.991,5.023-5.105,7.202c-1.122,2.178-1.983,4.357-2.593,6.535c-0.61,2.17-1.528,5.999-2.772,11.469
|
20 |
+
c-2.113,11.608-8.754,17.411-19.915,17.411c-5.804,0-10.681-1.894-14.656-5.69c-3.959-3.796-5.934-9.429-5.934-16.907
|
21 |
+
c0-9.372,1.455-17.493,4.357-24.361c2.886-6.869,6.747-12.892,11.543-18.086c4.804-5.194,11.274-11.356,19.427-18.501
|
22 |
+
c7.145-6.251,12.307-10.965,15.485-14.144c3.186-3.186,5.861-6.73,8.031-10.632c2.187-3.91,3.26-8.145,3.26-12.721
|
23 |
+
c0-8.933-3.308-16.46-9.957-22.597c-6.641-6.137-15.209-9.21-25.703-9.21c-12.282,0-21.321,3.097-27.125,9.291
|
24 |
+
c-5.804,6.194-10.705,15.314-14.729,27.369c-3.804,12.616-11.006,18.923-21.598,18.923c-6.251,0-11.526-2.203-15.826-6.609
|
25 |
+
c-4.292-4.406-6.438-9.177-6.438-14.314c0-10.6,3.406-21.346,10.21-32.23c6.812-10.884,16.745-19.899,29.807-27.036
|
26 |
+
c13.054-7.145,28.296-10.722,45.699-10.722c16.184,0,30.466,2.991,42.854,8.966c12.388,5.966,21.963,14.087,28.718,24.361
|
27 |
+
c6.747,10.266,10.128,21.427,10.128,33.482C299.635,165.473,297.709,173.789,293.856,180.934z"></path></g></svg><svg id="icon-loading" viewBox="0 0 128 128" xml:space="preserve"><g><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#049046"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(45 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(90 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(135 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(180 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(225 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(270 64 64)"></path><path d="M38.52 33.37L21.36 16.2A63.6 63.6 0 0 1 59.5.16v24.3a39.5 39.5 0 0 0-20.98 8.92z" fill="#c5e8e1" transform="rotate(315 64 64)"></path><animateTransform attributeName="transform" type="rotate" values="0 64 64;45 64 64;90 64 64;135 64 64;180 64 64;225 64 64;270 64 64;315 64 64" calcMode="discrete" dur="720ms" repeatCount="indefinite"></animateTransform></g></svg></defs>`,1),K=[G];function J(t,e){return l(),c("svg",q,K)}var Q=f(E,[["render",J]]);class w{static escape(e){return e.replace(/./gm,function(s){var n=/[0-9a-zA-Z\!\[\]\(\)\*\#]/;return n.test(s.charAt(0))?s.charAt(0):"&#"+s.charCodeAt(0)+";"})}static md2htmlOneLine(e){return e=w.escape(e),e=e.replace(/\[([^[]+)\]\(([^)]+)\)/gm,function(s,n,o){return'<a target="blank" href="'+o+'">'+n+"</a>"}),e=e.replace(/(\*\*[^\*]+\*\*)/gm,function(s){return"<b>"+s.substr(2,s.length-4)+"</b>"}),e=e.replace(/(\*[^\*]+\*)/gm,function(s){return"<i>"+s.substr(1,s.length-2)+"</i>"}),e.substr(0,1)=="#"&&(e.substr(0,2)=="# "&&(e="<h1>"+e.substr(2)+"</h1>"),e.substr(0,3)=="## "&&(e="<h2>"+e.substr(3)+"</h2>"),e.substr(0,4)=="### "&&(e="<h3>"+e.substr(4)+"</h3>"),e.substr(0,5)=="#### "&&(e="<h4>"+e.substr(5)+"</h4>")),e==""&&(e="<br>"),e}static md2html(e){for(var s=e.match(/[^\r\n]+/g),n=[],o=0;o<s.length;o++)n.push(w.md2htmlOneLine(s[o]));return n.join("<br>")}}const ee={name:"FileItem",emits:["toggle","select"],props:{item:Object},data(){return{hover:!1,selected:!1}},inject:["wcfm"],methods:{onClick(t){this.selected=!0,this.$emit("select",this)},getWCFM(){return this.wcfm},getFullPath(){for(var t=this.$parent,e=[];t!==null&&t.$parent!==null;)t.item&&e.push(t.item.name),t=t.$parent;return e.pop(),e=e.reverse().join("/"),e=e.replace("//","/"),e},infoClick(){this.getWCFM().displayInfo(this.getFullPath())},convertClick(){this.getWCFM().onConvertClick(this.getFullPath())}}},C=t=>(V("data-v-4fb0cc48"),t=t(),I(),t),te={key:0,class:"icon-fold"},oe=C(()=>a("use",{"xlink:href":"#icon-fold"},null,-1)),se=[oe],ie={key:1,class:"icon-unfold"},ne=C(()=>a("use",{"xlink:href":"#icon-unfold"},null,-1)),ae=[ne],le=C(()=>a("use",{"xlink:href":"#icon-folder"},null,-1)),re=[le],ce={key:2,class:"icon-file"},de=C(()=>a("use",{"xlink:href":"#icon-file"},null,-1)),he=[de];function ue(t,e,s,n,o,i){return l(),c("div",{class:S({fileitem:!0,selected:o.selected}),onMouseover:e[2]||(e[2]=r=>o.hover=!0),onMouseleave:e[3]||(e[3]=r=>o.hover=!1),onClick:e[4]||(e[4]=(...r)=>i.onClick&&i.onClick(...r))},[a("p",null,[s.item.isDir?(l(),c("span",{key:0,class:S({"fold-unfold":!0,empty:s.item.isEmpty}),onClick:e[0]||(e[0]=r=>this.$emit("toggle"))},[s.item.isOpen?(l(),c("svg",te,se)):u("",!0),s.item.isOpen?u("",!0):(l(),c("svg",ie,ae))],2)):u("",!0),s.item.isDir?(l(),c("svg",{key:1,class:"icon-folder",onClick:e[1]||(e[1]=r=>this.$emit("toggle"))},re)):u("",!0),s.item.isDir?u("",!0):(l(),c("svg",ce,he)),y(" "+p(s.item.nickname||s.item.name),1)])],34)}var me=f(ee,[["render",ue],["__scopeId","data-v-4fb0cc48"]]);const fe={name:"FileTree",components:{FileItem:me},emits:["select"],props:{item:Object},data(){return{loading:!1}},methods:{load(){var t=this;v.post("get-folder",{path:this.$refs.thefileitem.getFullPath()},function(e){t.loading=!0,t.item.children=e.children.sort(function(s,n){return s.isDir&&!n.isDir?-1:!s.isDir&&n.isDir||s.name>n.name?1:s.name<n.name?-1:0}),t.item.loaded=!0,t.loading=!1})},toggle(){this.item.isOpen=!this.item.isOpen,this.item.loaded||this.load()},onSelect(t){this.$emit("select",t)}},mounted(){let t=this.$refs.thefileitem.getFullPath();(t=="/"||t.indexOf("/")==-1)&&this.toggle()}},_e={key:0},pe=a("li",null,"loading...",-1),ge=[pe],ve={key:1,class:"tree"};function ye(t,e,s,n,o,i){const r=m("FileItem"),h=m("FileTree",!0);return l(),c(x,null,[_(r,{ref:"thefileitem",item:s.item,onDblclick:i.toggle,onToggle:i.toggle,onSelect:i.onSelect},null,8,["item","onDblclick","onToggle","onSelect"]),o.loading?(l(),c("ul",_e,ge)):u("",!0),s.item.children!==void 0&&s.item.isOpen?(l(),c("ul",ve,[(l(!0),c(x,null,Y(s.item.children,d=>(l(),c("li",null,[_(h,{item:d,onSelect:i.onSelect},null,8,["item","onSelect"])]))),256))])):u("",!0)],64)}var ze=f(fe,[["render",ye]]);const be={name:"Files",components:{FileTree:ze},emits:["select"],props:{item:Object,statusText:String},methods:{onSelect(t){this.selectedItem&&(this.selectedItem.selected=!1),this.selectedItem=t,this.$emit("select",this.selectedItem.getFullPath(),this.selectedItem.item.isDir)}},data(){return{selected:null}}},we={key:1};function xe(t,e,s,n,o,i){const r=m("FileTree");return l(),c(x,null,[s.item?(l(),z(r,{key:0,item:s.item,onSelect:i.onSelect},null,8,["item","onSelect"])):u("",!0),s.item?u("",!0):(l(),c("div",we,p(s.statusText),1))],64)}var $e=f(be,[["render",xe]]);const ke={name:"Modal",emits:["close"],props:{title:{type:String},closeButtonText:{type:String},width:{type:[Number,String],default:"95%"},maxwidth:{type:[Number,String],default:"700px"},alignment:{type:String,default:"center"},height:{type:[Number,String],default:"92%"},maxheight:{type:[Number,String],default:"700px"},valignment:{type:String,default:"center"}},computed:{containerStyle(){let t={width:this.width,"max-width":this.maxwidth,height:this.height,"max-height":this.maxheight};return this.alignment=="center"&&(t.margin="0px auto"),this.alignment=="right"&&(t.position="absolute",t.right="10px"),this.valignment=="center"&&(t.top="50%",t.transform="translateY(-50%)"),this.alignment=="bottom"&&(t.position="absolute",t.bottom="10px"),t}},methods:{onCloseClick(){this.$emit("close")},registerKeyDownEvent(){let t=this;document.onkeydown=function(e){e=e||window.event;var s=!1;"key"in e?s=e.key==="Escape"||e.key==="Esc":s=e.keyCode===27,s&&t.$emit("close")}}},mounted(){this.registerKeyDownEvent()}},Ce={class:"modal-mask"},Se={class:"modal-wrapper"},Ve={class:"title"},Ie={class:"modal-body"},Me={class:"content"},Fe=y(" default body "),Re={class:"close-button-with-text"};function Ye(t,e,s,n,o,i){return l(),c("div",Ce,[a("div",Se,[a("div",{class:"modal-container",style:D(i.containerStyle)},[a("a",{class:"close-button",onClick:e[0]||(e[0]=(...r)=>i.onCloseClick&&i.onCloseClick(...r))},"X"),a("div",Ve,p(s.title),1),a("div",Ie,[a("div",Me,[H(t.$slots,"default",{},()=>[Fe]),a("div",Re,[a("button",{onClick:e[1]||(e[1]=(...r)=>i.onCloseClick&&i.onCloseClick(...r))},p(s.closeButtonText),1)])])])],4)])])}var L=f(ke,[["render",Ye]]);const De={name:"ZoomSlider",components:{Slider:j},emits:["update:zoom"],props:{zoom:{type:Number,default:1}},watch:{exp(t,e){this.$emit("update:zoom",2**t)},zoom(t,e){this.exp=Math.log2(t)}},methods:{sliderFormat(t){return Math.round(2**t*100)+"%"}},mounted(){},data(){return{exp:0}}},Oe={class:"zoom-slider"};function Xe(t,e,s,n,o,i){const r=m("Slider");return l(),c("div",Oe,[_(r,{modelValue:o.exp,"onUpdate:modelValue":e[0]||(e[0]=h=>o.exp=h),min:-4,max:4,width:100,step:-1,format:i.sliderFormat,tooltipPosition:"bottom",orientation:"horizontal"},null,8,["modelValue","format"])])}var Le=f(De,[["render",Xe]]);const Te={name:"ImageViewport",components:{VueZoomer:O,ZoomSlider:Le},emits:["update:zoom","update:translateX","update:translateY","load","resize"],props:{src:{type:String},height:{type:Number,default:500},zoom:{type:Number,default:1},scaleZoomRatio:{type:Number},translateX:{type:Number,default:1},translateY:{type:Number,default:1}},data(){return{ratio:1,ro:null}},watch:{height(t,e){var s;((s=this.$refs)==null?void 0:s.zoomer)&&(this.$refs.zoomer.onWindowResize(),this.$refs.zoomer.refreshContainerPos())},scaleZoomRatio(t){var e;((e=this.$refs)==null?void 0:e.zoomer)&&(this.$refs.zoomer.onWindowResize(),this.$refs.zoomer.refreshContainerPos()),this.$refs.zoomer.scale=this.zoom*this.scaleZoomRatio},zoom(t,e){this.isImageReady(),this.$refs.zoomer.scale=t*this.scaleZoomRatio},translateX(t,e){this.$refs.zoomer.translateX!=t&&(this.$refs.zoomer.translateX=t)},translateY(t,e){this.$refs.zoomer.translateY!=t&&(this.$refs.zoomer.translateY=t)}},methods:{getGoodContainerHeight(){var t,e,s;if((e=(t=this.$refs)==null?void 0:t.theimg)==null?void 0:e.naturalWidth){let n=this.$refs.theimg.naturalWidth/this.$refs.theimg.naturalHeight,i=((s=this.$refs.root)==null?void 0:s.offsetWidth)/n;return i>300&&(i=300),i}return 300},updateContainerHeight(){},isImageReady(){var t,e,s;return!(!((e=(t=this.$refs)==null?void 0:t.theimg)==null?void 0:e.naturalWidth)||!((s=this.$refs.root)==null?void 0:s.offsetWidth))},calcScaleZoomRatio(){var n,o;if(!this.isImageReady())return 1;let t=this.$refs.theimg.naturalWidth/((n=this.$refs.root)==null?void 0:n.offsetWidth),e=this.$refs.theimg.naturalHeight/((o=this.$refs.root)==null?void 0:o.offsetHeight),s=Math.max(t,e);return isNaN(s)?1:s},updateRatio(){},updateScale(){this.zoom&&(this.$refs.zoomer.scale=this.zoom*this.scaleZoomRatio)},zoomToFit(){},onImgLoad(){var t,e;((e=(t=this.$refs)==null?void 0:t.theimg)==null?void 0:e.naturalWidth)&&this.$emit("load")},onResize(){this.$emit("resize")},onDoubleTap(){console.log("double tab - zoom to 100%"),this.$emit("update:zoom",1),this.$emit("update:translateX",0),this.$emit("update:translateY",0)}},mounted(){window.ResizeObserver&&(this.ro=new ResizeObserver(this.onResize).observe(this.$refs.root)),this.$refs.zoomer.tapDetector.onDoubleTap(this.onDoubleTap),this.$watch("$refs.zoomer.scale",(t,e)=>{this.isImageReady(),this.$emit("update:zoom",t/this.scaleZoomRatio)}),this.$watch("$refs.zoomer.translateX",(t,e)=>{this.$emit("update:translateX",t)}),this.$watch("$refs.zoomer.translateY",(t,e)=>{this.$emit("update:translateY",t)})},beforeDestroy(){window.ResizeObserver&&this.ro.unobserve(this.$refs.zoomer)}},We={ref:"root",class:"image-viewport"},Ne=["src"],Pe={class:"zoom-info"};function Ze(t,e,s,n,o,i){const r=m("v-zoomer");return l(),c("div",We,[_(r,{ref:"zoomer",class:"zoomer",minScale:.1,maxScale:8,onResize:i.onResize,doubleClickToZoom:!1,style:D({height:s.height+"px"}),pivot:"cursor",limitTranslation:!1,lockPanOnNoScale:!1},{default:b(()=>[a("img",{ref:"theimg",src:s.src,onLoad:e[0]||(e[0]=(...h)=>i.onImgLoad&&i.onImgLoad(...h))},null,40,Ne)]),_:1},8,["minScale","onResize","style"]),a("div",Pe," zoom: "+p(Math.round(s.zoom*100))+"% ",1)],512)}var He=f(Te,[["render",Ze]]);const je={name:"Variant",components:{ImageViewport:He},emits:["select","update:zoom","update:translateX","update:translateY","load","resize"],props:{title:{type:String},info:{type:Object},url:{type:String,default:""},height:{type:Number},zoom:{type:Number},scaleZoomRatio:{type:Number},translateX:{type:Number},translateY:{type:Number},variantIndex:{type:Number}},computed:{imageUrl:function(){var t;return(t=this.info)==null?void 0:t.url},filesize:function(){var e;if(!((e=this.info)==null?void 0:e.size))return"";let t=this.info.size;return t<1024?t+" bytes":(t/=1024,t<1024?Math.round(t*10)/10+" kb":(t/=1024,Math.round(t*10)/10+" MB"))}},methods:{onVariantSelect(){this.$emit("select",this.variantIndex)},onLoad(){this.$emit("load")},zoomToFit(){this.$refs.theport.zoomToFit()}},mounted(){this.$watch("$refs.theport.zoom",(t,e)=>{this.$emit("update:zoom",t)}),this.$watch("$refs.theport.translateX",(t,e)=>{this.$emit("update:translateX",t)}),this.$watch("$refs.theport.translateY",(t,e)=>{this.$emit("update:translateY",t)})},data(){return{}}},Be={class:"variant"},Ue={class:"header"},Ae={class:"title"},Ee={class:"size"};function qe(t,e,s,n,o,i){const r=m("ImageViewport");return l(),c("div",Be,[a("div",Ue,[a("div",Ae,p(s.title),1),a("div",Ee,p(i.filesize),1)]),_(r,{ref:"theport",src:i.imageUrl,height:s.height,zoom:s.zoom,"onUpdate:zoom":e[0]||(e[0]=h=>s.zoom=h),scaleZoomRatio:s.scaleZoomRatio,translateX:s.translateX,"onUpdate:translateX":e[1]||(e[1]=h=>s.translateX=h),translateY:s.translateY,"onUpdate:translateY":e[2]||(e[2]=h=>s.translateY=h),onLoad:i.onLoad,onResize:e[3]||(e[3]=h=>this.$emit("resize"))},null,8,["src","height","zoom","scaleZoomRatio","translateX","translateY","onLoad"])])}var T=f(je,[["render",qe],["__scopeId","data-v-0372e854"]]);const Ge={name:"Variants",components:{Variant:T},emits:["update:zoom","update:translateX","update:translateY"],props:{file:{type:Object},viewport:{type:Object},height:{type:Number},zoom:{type:Number,default:1},translateX:{type:Number,default:0},translateY:{type:Number,default:0}},watch:{file(t,e){}},methods:{onZoomChange(t){this.$emit("update:zoom",t)},onTranslateXChange(t){this.$emit("update:translateX",t)},onTranslateYChange(t){this.$emit("update:translateY",t)},sliderFormat(t){return Math.round(t*100)+"%"},changeImage(){this.imageUrl=="http://localhost:3000/src/assets/dummy.jpg"?this.imageUrl="http://localhost:3000/src/assets/dummy2.jpg":this.imageUrl="http://localhost:3000/src/assets/dummy.jpg",this.selectedVariant=-1},onVariantSelect(t){this.selectedVariant=t}},mounted(){this.$watch("$refs.variants.zoom",(t,e)=>{})},data(){var t="http://localhost:3000/src/assets/200x100.jpg";return{imageUrl:"",selectedVariant:-1,variants:[{title:"Existing conversion",size:732,url:t},{title:"Lossy, q:20",size:35e5,url:t}]}}},W=t=>(V("data-v-25a3327e"),t=t(),I(),t),Ke={class:"variants-component"},Je=W(()=>a("br",null,null,-1)),Qe=W(()=>a("br",null,null,-1)),et={class:"variants"};function tt(t,e,s,n,o,i){const r=m("Variant");return l(),c("div",Ke,[y(" File: "+p(s.file)+" ",1),a("button",{onClick:e[0]||(e[0]=h=>i.changeImage())},"Change image"),Je,Qe,a("div",et,[(l(!0),c(x,null,Y(o.variants,(h,d)=>(l(),z(r,{title:h.title,info:h,variantIndex:d,class:S({selected:d==o.selectedVariant}),height:s.height,zoom:s.zoom,"onUpdate:zoom":[e[1]||(e[1]=g=>s.zoom=g),i.onZoomChange],translateX:s.translateX,"onUpdate:translateX":[e[2]||(e[2]=g=>s.translateX=g),i.onTranslateXChange],translateY:s.translateY,"onUpdate:translateY":[e[3]||(e[3]=g=>s.translateY=g),i.onTranslateYChange],onSelect:i.onVariantSelect},null,8,["title","info","variantIndex","class","height","zoom","translateX","translateY","onSelect","onUpdate:zoom","onUpdate:translateX","onUpdate:translateY"]))),256))])])}var ot=f(Ge,[["render",tt],["__scopeId","data-v-25a3327e"]]);const st={name:"FileProperties",components:{Variant:T,Variants:ot,Modal:L},props:{file:{type:Object,default:{}}},watch:{file(t,e){t.isDir||this.changePath(t.path)}},methods:{onVariantSelect(t){this.selectedVariant=t},onOriginalLoad(){if(this.updateHeight(),this.$refs.original.$refs.theport.calcScaleZoomRatio()>1){let e=this.$refs.original.$refs.theport,s=e.$refs.theimg,n=e.$refs.root,o=s.naturalWidth,i=s.naturalHeight,r=n.offsetWidth,d=this.height/i,g=r/o;this.zoom=Math.min(d,g)}else this.zoom=1;this.translateX=0,this.translateY=0},onOriginalResize(){this.updateHeight()},onConvertClick(){let t=this;this.converting=!0,v.post("convert",{path:this.path},function(e){t.converting=!1,(e==null?void 0:e.success)==!1&&(t.errorMsg=e.data),e.converted&&(t.convertedInfo=e.converted),e.log&&(t.log=w.md2html(e.log))})},updateHeight(){this.$refs.original&&(this.height=this.$refs.original.$refs.theport.getGoodContainerHeight(),this.scaleZoomRatio=this.$refs.original.$refs.theport.calcScaleZoomRatio())},reset(){this.originalInfo=null,this.convertedInfo=null},reload(){this.load()},changePath(t){this.reset(),this.path=t,this.loading=!0,this.errorMsg="",this.log="",this.load()},load(){let t=this;v.post("info",{path:this.path},function(e){(e==null?void 0:e.success)==!1&&(t.errorMsg=e.data),t.loading=!1,t.originalInfo=e.original,e.converted&&(t.convertedInfo=e.converted),e.log&&(t.log=w.md2html(e.log))})}},mounted(){this.file&&(this.path=this.file.path,this.load())},data(){return{zoom:1,scaleZoomRatio:1,translateX:0,translateY:0,height:100,loading:!1,errorMsg:"",originalInfo:null,convertedInfo:null,path:"",log:"",showingLogDialog:!1,converting:!1}}},M=t=>(V("data-v-1f62a342"),t=t(),I(),t),it={class:"file-properties"},nt={class:"path"},at=y(" Path: "),lt={class:"path"},rt={key:0,class:"error"},ct=["innerHTML"],dt={key:0},ht={key:1},ut={key:0,class:"icon-converting",width:"15",height:"15"},mt=M(()=>a("use",{"xlink:href":"#icon-loading"},null,-1)),ft=[mt],_t=["disabled"],pt=M(()=>a("p",null," Above, you see the original image. If it has been converted, you also see the converted image (provided that your browser supports webp). ",-1)),gt=M(()=>a("p",null," You can zoom in on the image, ie using scroll wheel. Both images will zoom, allowing you to compare the quality. Double-click the image to set zoom to 100%. You can also drag the image. ",-1));function vt(t,e,s,n,o,i){const r=m("Variant"),h=m("Modal");return l(),c("div",it,[a("div",nt,[at,a("span",lt,p(s.file.path),1)]),o.errorMsg!=""?(l(),c("div",rt,[a("p",null,"Error: "+p(o.errorMsg),1)])):u("",!0),$(a("div",null,"Getting info...",512),[[k,o.loading]]),$(_(r,{ref:"original",title:"Original",info:o.originalInfo,height:o.height,zoom:o.zoom,"onUpdate:zoom":e[0]||(e[0]=d=>o.zoom=d),scaleZoomRatio:o.scaleZoomRatio,translateX:o.translateX,"onUpdate:translateX":e[1]||(e[1]=d=>o.translateX=d),translateY:o.translateY,"onUpdate:translateY":e[2]||(e[2]=d=>o.translateY=d),onLoad:i.onOriginalLoad,onResize:i.onOriginalResize},null,8,["info","height","zoom","scaleZoomRatio","translateX","translateY","onLoad","onResize"]),[[k,o.originalInfo]]),$(_(r,{title:"Existing conversion",info:o.convertedInfo,height:o.height,zoom:o.zoom,"onUpdate:zoom":e[3]||(e[3]=d=>o.zoom=d),scaleZoomRatio:o.scaleZoomRatio,translateX:o.translateX,"onUpdate:translateX":e[4]||(e[4]=d=>o.translateX=d),translateY:o.translateY,"onUpdate:translateY":e[5]||(e[5]=d=>o.translateY=d)},null,8,["info","height","zoom","scaleZoomRatio","translateX","translateY"]),[[k,o.convertedInfo]]),$(_(h,{title:"Conversion log",closeButtonText:"Ok",width:"95vw",maxwidth:"1400px",height:"95vh",onClose:e[6]||(e[6]=d=>o.showingLogDialog=!1)},{default:b(()=>[a("div",{innerHTML:o.log},null,8,ct)]),_:1},512),[[k,o.showingLogDialog]]),a("div",null,[a("button",{onClick:e[7]||(e[7]=(...d)=>i.onConvertClick&&i.onConvertClick(...d))},[o.convertedInfo?(l(),c("span",dt,"Reconvert")):u("",!0),o.convertedInfo?u("",!0):(l(),c("span",ht,"Convert"))]),o.converting?(l(),c("svg",ut,ft)):u("",!0),o.log!=""?(l(),c("button",{key:1,onClick:e[8]||(e[8]=d=>o.showingLogDialog=!0),class:"log-button",disabled:o.converting},"View conversion log",8,_t)):u("",!0)]),pt,gt])}var yt=f(st,[["render",vt],["__scopeId","data-v-1f62a342"]]);const zt={name:"FolderProperties",components:{},props:{file:{type:Object,default:{}}},watch:{file(t,e){}}},bt={class:"folder-properties"},wt={class:"path"},xt=y(" Path: "),$t={class:"path"},kt=a("p",null," You cannot do anything on folders yet. Browse to an image... ",-1);function Ct(t,e,s,n,o,i){return l(),c("div",bt,[a("div",wt,[xt,a("span",$t,p(s.file.path),1)]),kt])}var St=f(zt,[["render",Ct]]);const Vt={name:"Welcome"},It={class:"welcome"},Mt=R('<div class="headline"><div>Welcome to</div><h3>WebP Convert file manager</h3></div><p> To open a folder, click the "+" sign next to the folder name or double click the folder name </p><p><h4>Whats new?</h4><ul><li>You can now convert files and view conversion log</li></ul></p><p><h4>Whats planned ahead?</h4> I have plenty of ideas, but no planned priority. Ideas: <ul><li>Trigger bulk conversion on folders / mark for background conversion</li><li>Stats on folders</li><li>Display more info on images (mime type, dimensions and such)</li><li>Adjust conversion settings</li><li>Interface to allow adjusting quality on a conversion quickly and compare directly</li></ul> To support development, you can <a href="https://ko-fi.com/rosell" target="_blank">buy me a cup of coffee</a></p>',4),Ft=[Mt];function Rt(t,e,s,n,o,i){return l(),c("div",It,Ft)}var Yt=f(Vt,[["render",Rt]]);const Dt={name:"WCFM",components:{SVGs:Q,FileProperties:yt,FolderProperties:St,Modal:L,Files:$e,Splitpanes:X.exports.Splitpanes,Pane:X.exports.Pane,Welcome:Yt},methods:{onConvertClick(t){var n,o;let e=(o=(n=this.$refs.convertOptions)==null?void 0:n.general)==null?void 0:o.data,s={path:t,convertOptions:e};console.log(s),v.post("convert",s,function(i){console.log("convert response:",i)})},onConvertCloseClick(){console.log("CLRCL"),this.showConvertOptions=!1},onFileSelect(t,e){this.file={path:t,isDir:e}},displayInfo(t){var e=this;v.post("info",{path:t},function(s){e.selectedInfo=s})}},mounted(){var t=this;v.post("get-folder",{path:""},function(e){t.item=e.children[0]})},data(){return{file:null,selectedItem:null,item:null,treeStatusText:"loading file tree...",selectedInfo:{},showConvertOptions:!1}},provide(){return{wcfm:this}}},Ot={class:"wcfm",style:{overflow:"hidden"}},Xt={class:"pane-content"},Lt={key:0,class:"pane-content"};function Tt(t,e,s,n,o,i){const r=m("SVGs"),h=m("Files"),d=m("pane"),g=m("FileProperties"),N=m("FolderProperties"),P=m("Welcome"),Z=m("splitpanes");return l(),c("div",Ot,[_(r),_(Z,{class:"default-theme",style:{position:"absolute",top:"0",left:"0"}},{default:b(()=>[_(d,{size:"30"},{default:b(()=>[a("div",Xt,[a("div",null,[_(h,{item:o.item,statusText:o.treeStatusText,onSelect:i.onFileSelect},null,8,["item","statusText","onSelect"])])])]),_:1}),_(d,{size:"70",style:{"overflow-y":"auto"}},{default:b(()=>[o.file?(l(),c("div",Lt,[o.file.isDir?u("",!0):(l(),z(g,{key:0,file:o.file},null,8,["file"])),o.file.isDir?(l(),z(N,{key:1,file:o.file},null,8,["file"])):u("",!0)])):u("",!0),o.file?u("",!0):(l(),z(P,{key:1}))]),_:1})]),_:1})])}var Wt=f(Dt,[["render",Tt]]);const F=B(Wt);F.use(O);F.use(U,{defaultHtml:!1});window.wcfmoptions||(window.wcfmoptions={},window.wcfmoptions.poster=function(t,e,s,n){switch(t){case"get-folder":switch(e.path){case"":var o={children:[{name:"/",isDir:!0,nickname:"root"}]};break;case"/":var o={children:[{name:"empty-folder",isDir:!0,isEmpty:!0},{name:"file",isDir:!1,isConverted:!0},{name:"aaa",isDir:!1,isConverted:!0},{name:"test-folder",isDir:!0},{name:"file2",isDir:!1,isConverted:!1}]};break;case"/empty-folder":var o={children:[]};break;case"/test-folder":var o={children:[{name:"banana",isDir:!1},{name:"subfolder",isDir:!0},{name:"apple",isDir:!1}]};break;case"/test-folder/subfolder":var o={children:[{name:"file2",isDir:!1},{name:"file1",isDir:!1}]};break;default:n();return}break;case"conversion-settings":var o={systemStatus:{converterRequirements:{gd:{extensionLoaded:!1,compiledWithWebP:!0}}}};break;case"info":if(e.path=="/file2")var o={original:{size:100,url:"http://localhost:3000/src/assets/200x100.jpg"},converted:{size:70,url:"http://localhost:3000/src/assets/200x100.jpg"},log:`blah blah blah
|
28 |
+
\rand *more* blah`};else if(e.path=="/file")var o={original:{size:100,url:"http://localhost:3000/src/assets/dummy2.jpg"},log:"blah blah *blah*"};else var o={original:{size:100,url:"http://localhost:3000/src/assets/dummy.jpg"},converted:{size:70,url:"http://localhost:3000/src/assets/dummy.jpg"},log:"blah blah *blah*"};break;case"convert":if(e.path=="/file2")var o={success:!1,data:"We pretend file2 errors converting...",log:"Oh no!"};else var o={success:!0,converted:{size:26050,url:"http://we0/wordpress/wp-content/uploads/2021/10/Screenshot_2021-10-04_13-43-11.png.webp"},log:`All is *groovy*
|
29 |
+
next line`};break;default:var o="ok";break}s(o)});F.mount("#webpconvert-filemanager");
|
@@ -1,27 +0,0 @@
|
|
1 |
-
import{_ as m,o as c,c as d,a as F,b as l,n as $,d as u,e as v,t as f,p as C,f as k,r as h,g as _,F as b,h as M,i as y,j as R,k as P,m as H,V as Y,w,l as S,v as V,s as X,q as L,u as j}from"./vendor.b4e4e155.js";const B=function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const a of i.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&n(a)}).observe(document,{childList:!0,subtree:!0});function s(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerpolicy&&(i.referrerPolicy=o.referrerpolicy),o.crossorigin==="use-credentials"?i.credentials="include":o.crossorigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(o){if(o.ep)return;o.ep=!0;const i=s(o);fetch(o.href,i)}};B();class z{static post(t,s,n){var o=this;window.wcfmoptions.poster(t,s,function(i){n.call(o,i)},function(){console.log("failure")})}}const U={},E={style:{position:"absolute",width:"0",height:"0"},width:"0",height:"0",version:"1.1",xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"},q=F(`<defs><symbol id="icon-folder" viewBox="0 0 309.267 309.267"><g><path style="fill:#D0994B;" d="M260.944,43.491H125.64c0,0-18.324-28.994-28.994-28.994H48.323c-10.67,0-19.329,8.65-19.329,19.329
|
2 |
-
v222.286c0,10.67,8.659,19.329,19.329,19.329h212.621c10.67,0,19.329-8.659,19.329-19.329V62.82
|
3 |
-
C280.273,52.15,271.614,43.491,260.944,43.491z"></path><path style="fill:#E4E7E7;" d="M28.994,72.484h251.279v77.317H28.994V72.484z"></path><path style="fill:#F4B459;" d="M19.329,91.814h270.609c10.67,0,19.329,8.65,19.329,19.329l-19.329,164.298
|
4 |
-
c0,10.67-8.659,19.329-19.329,19.329H38.658c-10.67,0-19.329-8.659-19.329-19.329L0,111.143C0,100.463,8.659,91.814,19.329,91.814z
|
5 |
-
"></path></g></symbol><symbol id="icon-unfold" viewBox="0 0 32 32"><path d="M28,14H18V4c0-1.104-0.896-2-2-2s-2,0.896-2,2v10H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h10v10c0,1.104,0.896,2,2,2 s2-0.896,2-2V18h10c1.104,0,2-0.896,2-2S29.104,14,28,14z"></path></symbol><symbol id="icon-fold" viewBox="0 0 24 24"><g fill="none" stroke="#000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line></g></symbol><symbol id="icon-file" viewBox="0 0 56 56"><g><path style="fill:#E9E9E0;" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074
|
6 |
-
c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"></path><polygon style="fill:#D9D7CA;" points="37.5,0.151 37.5,12 49.349,12 "></polygon><circle style="fill:#F3D55B;" cx="18.931" cy="14.431" r="4.569"></circle><polygon style="fill:#26B99A;" points="6.5,39 17.5,39 49.5,39 49.5,28 39.5,18.5 29,30 23.517,24.517 "></polygon><path style="fill:#14A085;" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"></path><g></g></g></symbol><svg id="icon-ok" viewBox="0 0 256 256"><g fill="green" stroke="none" transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"><path d="M1064 2545 c-406 -72 -744 -324 -927 -690 -96 -193 -127 -333 -127 -575 0 -243 33 -387 133 -585 177 -351 518 -606 907 -676 118 -22 393 -17 511 8 110 24 252 78 356 136 327 183 569 525 628 887 19 122 19 338 0 460 -81 498 -483 914 -990 1025 -101 22 -389 28 -491 10z m814 -745 c39 -27 73 -59 77 -70 9 -27 10 -25 -372 -590 -345 -510 -357 -524 -420 -512 -19 4 -98 74 -250 225 -123 121 -225 228 -228 238 -3 10 1 31 9 47 20 40 125 132 149 132 11 0 79 -59 162 -140 79 -77 146 -140 149 -140 3 0 38 48 78 108 95 143 465 678 496 720 35 46 64 42 150 -18z"></path></g></svg><svg id="icon-not-available" viewBox="0 0 500.000000 500.000000" preserveAspectRatio="xMidYMid meet"><g fill="#b11010" stroke="none" transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"><path d="M2315 4800 c-479 -35 -928 -217 -1303 -527 -352 -293 -615 -702 -738 -1151 -104 -380 -104 -824 0 -1204 107 -389 302 -724 591 -1013 354 -354 785 -572 1279 -646 196 -30 476 -30 672 0 494 74 925 292 1279 646 354 354 571 784 646 1279 30 197 30 475 0 672 -75 495 -292 925 -646 1279 -289 289 -624 484 -1013 591 -228 62 -528 91 -767 74z m353 -511 c458 -50 874 -272 1170 -624 417 -497 536 -1174 308 -1763 -56 -145 -176 -367 -235 -434 -4 -4 -566 552 -1250 1236 l-1243 1243 94 60 c354 229 754 327 1156 282z m864 -3200 c-67 -59 -289 -179 -434 -235 -946 -366 -2024 172 -2322 1158 -47 155 -66 276 -73 453 -13 362 84 704 290 1023 l60 94 1243 -1243 c684 -684 1240 -1246 1236 -1250z"></path></g></svg><svg id="icon-help" viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve"><g><path style="fill:#cccccc;" d="M199.996,0C89.719,0,0,89.72,0,200c0,110.279,89.719,200,199.996,200C310.281,400,400,310.279,400,200
|
7 |
-
C400,89.72,310.281,0,199.996,0z M199.996,373.77C104.187,373.77,26.23,295.816,26.23,200
|
8 |
-
c0-95.817,77.957-173.769,173.766-173.769c95.816,0,173.772,77.953,173.772,173.769
|
9 |
-
C373.769,295.816,295.812,373.77,199.996,373.77z"></path><path style="fill:#000000;" d="M199.996,91.382c-35.176,0-63.789,28.616-63.789,63.793c0,7.243,5.871,13.115,13.113,13.115
|
10 |
-
c7.246,0,13.117-5.873,13.117-13.115c0-20.71,16.848-37.562,37.559-37.562c20.719,0,37.566,16.852,37.566,37.562
|
11 |
-
c0,20.714-16.849,37.566-37.566,37.566c-7.242,0-13.113,5.873-13.113,13.114v45.684c0,7.243,5.871,13.115,13.113,13.115
|
12 |
-
s13.117-5.872,13.117-13.115v-33.938c28.905-6.064,50.68-31.746,50.68-62.427C263.793,119.998,235.176,91.382,199.996,91.382z"></path><path d="M200.004,273.738c-9.086,0-16.465,7.371-16.465,16.462s7.379,16.465,16.465,16.465c9.094,0,16.457-7.374,16.457-16.465
|
13 |
-
S209.098,273.738,200.004,273.738z"></path></g></svg><svg id="icon-help2" viewBox="0 0 431.855 431.855" style="enable-background:new 0 0 431.855 431.855;" xml:space="preserve"><g><path style="fill:#aaaaaa;" d="M215.936,0C96.722,0,0.008,96.592,0.008,215.814c0,119.336,96.714,216.041,215.927,216.041
|
14 |
-
c119.279,0,215.911-96.706,215.911-216.041C431.847,96.592,335.214,0,215.936,0z M231.323,335.962
|
15 |
-
c-5.015,4.463-10.827,6.706-17.411,6.706c-6.812,0-12.754-2.203-17.826-6.617c-5.08-4.406-7.625-10.575-7.625-18.501
|
16 |
-
c0-7.031,2.463-12.949,7.373-17.745c4.91-4.796,10.933-7.194,18.078-7.194c7.031,0,12.949,2.398,17.753,7.194
|
17 |
-
c4.796,4.796,7.202,10.713,7.202,17.745C238.858,325.362,236.346,331.5,231.323,335.962z M293.856,180.934
|
18 |
-
c-3.853,7.145-8.429,13.306-13.737,18.501c-5.292,5.194-14.81,13.924-28.548,26.198c-3.788,3.463-6.836,6.503-9.12,9.12
|
19 |
-
c-2.284,2.626-3.991,5.023-5.105,7.202c-1.122,2.178-1.983,4.357-2.593,6.535c-0.61,2.17-1.528,5.999-2.772,11.469
|
20 |
-
c-2.113,11.608-8.754,17.411-19.915,17.411c-5.804,0-10.681-1.894-14.656-5.69c-3.959-3.796-5.934-9.429-5.934-16.907
|
21 |
-
c0-9.372,1.455-17.493,4.357-24.361c2.886-6.869,6.747-12.892,11.543-18.086c4.804-5.194,11.274-11.356,19.427-18.501
|
22 |
-
c7.145-6.251,12.307-10.965,15.485-14.144c3.186-3.186,5.861-6.73,8.031-10.632c2.187-3.91,3.26-8.145,3.26-12.721
|
23 |
-
c0-8.933-3.308-16.46-9.957-22.597c-6.641-6.137-15.209-9.21-25.703-9.21c-12.282,0-21.321,3.097-27.125,9.291
|
24 |
-
c-5.804,6.194-10.705,15.314-14.729,27.369c-3.804,12.616-11.006,18.923-21.598,18.923c-6.251,0-11.526-2.203-15.826-6.609
|
25 |
-
c-4.292-4.406-6.438-9.177-6.438-14.314c0-10.6,3.406-21.346,10.21-32.23c6.812-10.884,16.745-19.899,29.807-27.036
|
26 |
-
c13.054-7.145,28.296-10.722,45.699-10.722c16.184,0,30.466,2.991,42.854,8.966c12.388,5.966,21.963,14.087,28.718,24.361
|
27 |
-
c6.747,10.266,10.128,21.427,10.128,33.482C299.635,165.473,297.709,173.789,293.856,180.934z"></path></g></svg></defs>`,1),A=[q];function G(e,t){return c(),d("svg",E,A)}var K=m(U,[["render",G]]);const J={name:"FileItem",emits:["toggle","select"],props:{item:Object},data(){return{hover:!1,selected:!1}},inject:["wcfm"],methods:{onClick(e){this.selected=!0,this.$emit("select",this)},getWCFM(){return this.wcfm},getFullPath(){for(var e=this.$parent,t=[];e!==null&&e.$parent!==null;)e.item&&t.push(e.item.name),e=e.$parent;return t.pop(),t=t.reverse().join("/"),t=t.replace("//","/"),t},infoClick(){this.getWCFM().displayInfo(this.getFullPath())},convertClick(){this.getWCFM().onConvertClick(this.getFullPath())}}},x=e=>(C("data-v-4fb0cc48"),e=e(),k(),e),Q={key:0,class:"icon-fold"},ee=x(()=>l("use",{"xlink:href":"#icon-fold"},null,-1)),te=[ee],oe={key:1,class:"icon-unfold"},se=x(()=>l("use",{"xlink:href":"#icon-unfold"},null,-1)),ie=[se],ne=x(()=>l("use",{"xlink:href":"#icon-folder"},null,-1)),le=[ne],ae={key:2,class:"icon-file"},re=x(()=>l("use",{"xlink:href":"#icon-file"},null,-1)),ce=[re];function de(e,t,s,n,o,i){return c(),d("div",{class:$({fileitem:!0,selected:o.selected}),onMouseover:t[2]||(t[2]=a=>o.hover=!0),onMouseleave:t[3]||(t[3]=a=>o.hover=!1),onClick:t[4]||(t[4]=(...a)=>i.onClick&&i.onClick(...a))},[l("p",null,[s.item.isDir?(c(),d("span",{key:0,class:$({"fold-unfold":!0,empty:s.item.isEmpty}),onClick:t[0]||(t[0]=a=>this.$emit("toggle"))},[s.item.isOpen?(c(),d("svg",Q,te)):u("",!0),s.item.isOpen?u("",!0):(c(),d("svg",oe,ie))],2)):u("",!0),s.item.isDir?(c(),d("svg",{key:1,class:"icon-folder",onClick:t[1]||(t[1]=a=>this.$emit("toggle"))},le)):u("",!0),s.item.isDir?u("",!0):(c(),d("svg",ae,ce)),v(" "+f(s.item.nickname||s.item.name),1)])],34)}var he=m(J,[["render",de],["__scopeId","data-v-4fb0cc48"]]);const ue={name:"FileTree",components:{FileItem:he},emits:["select"],props:{item:Object},data(){return{loading:!1}},methods:{load(){var e=this;z.post("get-folder",{path:this.$refs.thefileitem.getFullPath()},function(t){e.loading=!0,e.item.children=t.children.sort(function(s,n){return s.isDir&&!n.isDir?-1:!s.isDir&&n.isDir||s.name>n.name?1:s.name<n.name?-1:0}),e.item.loaded=!0,e.loading=!1})},toggle(){this.item.isOpen=!this.item.isOpen,this.item.loaded||this.load()},onSelect(e){this.$emit("select",e)}},mounted(){let e=this.$refs.thefileitem.getFullPath();(e=="/"||e.indexOf("/")==-1)&&this.toggle()}},me={key:0},_e=l("li",null,"loading...",-1),fe=[_e],pe={key:1,class:"tree"};function ge(e,t,s,n,o,i){const a=h("FileItem"),r=h("FileTree",!0);return c(),d(b,null,[_(a,{ref:"thefileitem",item:s.item,onDblclick:i.toggle,onToggle:i.toggle,onSelect:i.onSelect},null,8,["item","onDblclick","onToggle","onSelect"]),o.loading?(c(),d("ul",me,fe)):u("",!0),s.item.children!==void 0&&s.item.isOpen?(c(),d("ul",pe,[(c(!0),d(b,null,M(s.item.children,p=>(c(),d("li",null,[_(r,{item:p,onSelect:i.onSelect},null,8,["item","onSelect"])]))),256))])):u("",!0)],64)}var ve=m(ue,[["render",ge]]);const ye={name:"Files",components:{FileTree:ve},emits:["select"],props:{item:Object,statusText:String},methods:{onSelect(e){this.selectedItem&&(this.selectedItem.selected=!1),this.selectedItem=e,this.$emit("select",this.selectedItem.getFullPath(),this.selectedItem.item.isDir)}},data(){return{selected:null}}},ze={key:1};function be(e,t,s,n,o,i){const a=h("FileTree");return c(),d(b,null,[s.item?(c(),y(a,{key:0,item:s.item,onSelect:i.onSelect},null,8,["item","onSelect"])):u("",!0),s.item?u("",!0):(c(),d("div",ze,f(s.statusText),1))],64)}var we=m(ye,[["render",be]]);const xe={name:"Modal",emits:["close"],props:{title:{type:String},closeButtonText:{type:String},alignment:{type:String},width:{type:[Number,String],default:"95%"},height:{type:[Number,String],default:"95%"},maxheight:{type:[Number,String],default:"700px"}},computed:{containerStyle(){let e={width:this.width,height:this.height,"max-height":this.maxheight};return this.alignment=="center"&&(e.margin="0px auto"),this.alignment=="right"&&(e.position="absolute",e.right="10px"),e}},methods:{onCloseClick(){this.$emit("close")}}},$e={class:"modal-mask"},Ce={class:"modal-wrapper"},ke={class:"title"},Se={class:"modal-body"},Ve={class:"content"},Ie=v(" default body "),Fe={class:"close-button-with-text"};function Me(e,t,s,n,o,i){return c(),d("div",$e,[l("div",Ce,[l("div",{class:"modal-container",style:R(i.containerStyle)},[l("a",{class:"close-button",onClick:t[0]||(t[0]=(...a)=>i.onCloseClick&&i.onCloseClick(...a))},"X"),l("div",ke,f(s.title),1),l("div",Se,[l("div",Ve,[P(e.$slots,"default",{},()=>[Ie]),l("div",Fe,[l("button",{onClick:t[1]||(t[1]=(...a)=>i.onCloseClick&&i.onCloseClick(...a))},f(s.closeButtonText),1)])])])],4)])])}var Re=m(xe,[["render",Me]]);const Ye={name:"ZoomSlider",components:{Slider:H},emits:["update:zoom"],props:{zoom:{type:Number,default:1}},watch:{exp(e,t){this.$emit("update:zoom",2**e)},zoom(e,t){this.exp=Math.log2(e)}},methods:{sliderFormat(e){return Math.round(2**e*100)+"%"}},mounted(){},data(){return{exp:0}}},Xe={class:"zoom-slider"};function Oe(e,t,s,n,o,i){const a=h("Slider");return c(),d("div",Xe,[_(a,{modelValue:o.exp,"onUpdate:modelValue":t[0]||(t[0]=r=>o.exp=r),min:-4,max:4,width:100,step:-1,format:i.sliderFormat,tooltipPosition:"bottom",orientation:"horizontal"},null,8,["modelValue","format"])])}var De=m(Ye,[["render",Oe]]);const Te={name:"ImageViewport",components:{VueZoomer:Y,ZoomSlider:De},emits:["update:zoom","update:translateX","update:translateY","load","resize"],props:{src:{type:String},height:{type:Number,default:500},zoom:{type:Number,default:1},scaleZoomRatio:{type:Number},translateX:{type:Number,default:1},translateY:{type:Number,default:1}},data(){return{ratio:1,ro:null}},watch:{height(e,t){var s;((s=this.$refs)==null?void 0:s.zoomer)&&(this.$refs.zoomer.onWindowResize(),this.$refs.zoomer.refreshContainerPos())},scaleZoomRatio(e){var t;((t=this.$refs)==null?void 0:t.zoomer)&&(this.$refs.zoomer.onWindowResize(),this.$refs.zoomer.refreshContainerPos()),this.$refs.zoomer.scale=this.zoom*this.scaleZoomRatio},zoom(e,t){this.isImageReady(),this.$refs.zoomer.scale=e*this.scaleZoomRatio},translateX(e,t){this.$refs.zoomer.translateX!=e&&(this.$refs.zoomer.translateX=e)},translateY(e,t){this.$refs.zoomer.translateY!=e&&(this.$refs.zoomer.translateY=e)}},methods:{getGoodContainerHeight(){var e,t,s;if((t=(e=this.$refs)==null?void 0:e.theimg)==null?void 0:t.naturalWidth){let n=this.$refs.theimg.naturalWidth/this.$refs.theimg.naturalHeight,i=((s=this.$refs.root)==null?void 0:s.offsetWidth)/n;return i>300&&(i=300),i}return 300},updateContainerHeight(){},isImageReady(){var e,t,s;return!(!((t=(e=this.$refs)==null?void 0:e.theimg)==null?void 0:t.naturalWidth)||!((s=this.$refs.root)==null?void 0:s.offsetWidth))},calcScaleZoomRatio(){var n,o;if(!this.isImageReady())return 1;let e=this.$refs.theimg.naturalWidth/((n=this.$refs.root)==null?void 0:n.offsetWidth),t=this.$refs.theimg.naturalHeight/((o=this.$refs.root)==null?void 0:o.offsetHeight),s=Math.max(e,t);return isNaN(s)?1:s},updateRatio(){},updateScale(){this.zoom&&(this.$refs.zoomer.scale=this.zoom*this.scaleZoomRatio)},zoomToFit(){},onImgLoad(){var e,t;((t=(e=this.$refs)==null?void 0:e.theimg)==null?void 0:t.naturalWidth)&&this.$emit("load")},onResize(){this.$emit("resize")},onDoubleTap(){console.log("double tab - zoom to 100%"),this.$emit("update:zoom",1),this.$emit("update:translateX",0),this.$emit("update:translateY",0)}},mounted(){window.ResizeObserver&&(this.ro=new ResizeObserver(this.onResize).observe(this.$refs.root)),this.$refs.zoomer.tapDetector.onDoubleTap(this.onDoubleTap),this.$watch("$refs.zoomer.scale",(e,t)=>{this.isImageReady(),this.$emit("update:zoom",e/this.scaleZoomRatio)}),this.$watch("$refs.zoomer.translateX",(e,t)=>{this.$emit("update:translateX",e)}),this.$watch("$refs.zoomer.translateY",(e,t)=>{this.$emit("update:translateY",e)})},beforeDestroy(){window.ResizeObserver&&this.ro.unobserve(this.$refs.zoomer)}},We={ref:"root",class:"image-viewport"},Ne=["src"],Ze={class:"zoom-info"};function Pe(e,t,s,n,o,i){const a=h("v-zoomer");return c(),d("div",We,[_(a,{ref:"zoomer",class:"zoomer",minScale:.1,maxScale:8,onResize:i.onResize,doubleClickToZoom:!1,style:R({height:s.height+"px"}),pivot:"cursor",limitTranslation:!1,lockPanOnNoScale:!1},{default:w(()=>[l("img",{ref:"theimg",src:s.src,onLoad:t[0]||(t[0]=(...r)=>i.onImgLoad&&i.onImgLoad(...r))},null,40,Ne)]),_:1},8,["minScale","onResize","style"]),l("div",Ze," zoom: "+f(Math.round(s.zoom*100))+"% ",1)],512)}var He=m(Te,[["render",Pe]]);const Le={name:"Variant",components:{ImageViewport:He},emits:["select","update:zoom","update:translateX","update:translateY","load","resize"],props:{title:{type:String},info:{type:Object},url:{type:String,default:""},height:{type:Number},zoom:{type:Number},scaleZoomRatio:{type:Number},translateX:{type:Number},translateY:{type:Number},variantIndex:{type:Number}},computed:{imageUrl:function(){var e;return(e=this.info)==null?void 0:e.url},filesize:function(){var t;if(!((t=this.info)==null?void 0:t.size))return"";let e=this.info.size;return e<1024?e+" bytes":(e/=1024,e<1024?Math.round(e*10)/10+" kb":(e/=1024,Math.round(e*10)/10+" MB"))}},methods:{onVariantSelect(){this.$emit("select",this.variantIndex)},onLoad(){this.$emit("load")},zoomToFit(){this.$refs.theport.zoomToFit()}},mounted(){this.$watch("$refs.theport.zoom",(e,t)=>{this.$emit("update:zoom",e)}),this.$watch("$refs.theport.translateX",(e,t)=>{this.$emit("update:translateX",e)}),this.$watch("$refs.theport.translateY",(e,t)=>{this.$emit("update:translateY",e)})},data(){return{}}},je={class:"variant"},Be={class:"header"},Ue={class:"title"},Ee={class:"size"};function qe(e,t,s,n,o,i){const a=h("ImageViewport");return c(),d("div",je,[l("div",Be,[l("div",Ue,f(s.title),1),l("div",Ee,f(i.filesize),1)]),_(a,{ref:"theport",src:i.imageUrl,height:s.height,zoom:s.zoom,"onUpdate:zoom":t[0]||(t[0]=r=>s.zoom=r),scaleZoomRatio:s.scaleZoomRatio,translateX:s.translateX,"onUpdate:translateX":t[1]||(t[1]=r=>s.translateX=r),translateY:s.translateY,"onUpdate:translateY":t[2]||(t[2]=r=>s.translateY=r),onLoad:i.onLoad,onResize:t[3]||(t[3]=r=>this.$emit("resize"))},null,8,["src","height","zoom","scaleZoomRatio","translateX","translateY","onLoad"])])}var O=m(Le,[["render",qe],["__scopeId","data-v-0372e854"]]);const Ae={name:"Variants",components:{Variant:O},emits:["update:zoom","update:translateX","update:translateY"],props:{file:{type:Object},viewport:{type:Object},height:{type:Number},zoom:{type:Number,default:1},translateX:{type:Number,default:0},translateY:{type:Number,default:0}},watch:{file(e,t){}},methods:{onZoomChange(e){this.$emit("update:zoom",e)},onTranslateXChange(e){this.$emit("update:translateX",e)},onTranslateYChange(e){this.$emit("update:translateY",e)},sliderFormat(e){return Math.round(e*100)+"%"},changeImage(){this.imageUrl=="http://localhost:3000/src/assets/dummy.jpg"?this.imageUrl="http://localhost:3000/src/assets/dummy2.jpg":this.imageUrl="http://localhost:3000/src/assets/dummy.jpg",this.selectedVariant=-1},onVariantSelect(e){this.selectedVariant=e}},mounted(){this.$watch("$refs.variants.zoom",(e,t)=>{})},data(){var e="http://localhost:3000/src/assets/200x100.jpg";return{imageUrl:"",selectedVariant:-1,variants:[{title:"Existing conversion",size:732,url:e},{title:"Lossy, q:20",size:35e5,url:e}]}}},D=e=>(C("data-v-25a3327e"),e=e(),k(),e),Ge={class:"variants-component"},Ke=D(()=>l("br",null,null,-1)),Je=D(()=>l("br",null,null,-1)),Qe={class:"variants"};function et(e,t,s,n,o,i){const a=h("Variant");return c(),d("div",Ge,[v(" File: "+f(s.file)+" ",1),l("button",{onClick:t[0]||(t[0]=r=>i.changeImage())},"Change image"),Ke,Je,l("div",Qe,[(c(!0),d(b,null,M(o.variants,(r,p)=>(c(),y(a,{title:r.title,info:r,variantIndex:p,class:$({selected:p==o.selectedVariant}),height:s.height,zoom:s.zoom,"onUpdate:zoom":[t[1]||(t[1]=g=>s.zoom=g),i.onZoomChange],translateX:s.translateX,"onUpdate:translateX":[t[2]||(t[2]=g=>s.translateX=g),i.onTranslateXChange],translateY:s.translateY,"onUpdate:translateY":[t[3]||(t[3]=g=>s.translateY=g),i.onTranslateYChange],onSelect:i.onVariantSelect},null,8,["title","info","variantIndex","class","height","zoom","translateX","translateY","onSelect","onUpdate:zoom","onUpdate:translateX","onUpdate:translateY"]))),256))])])}var tt=m(Ae,[["render",et],["__scopeId","data-v-25a3327e"]]);const ot={name:"FileProperties",components:{Variant:O,Variants:tt},props:{file:{type:Object,default:{}}},watch:{file(e,t){e.isDir||this.load(e.path)}},methods:{onVariantSelect(e){this.selectedVariant=e},onOriginalLoad(){if(this.updateHeight(),this.$refs.original.$refs.theport.calcScaleZoomRatio()>1){let t=this.$refs.original.$refs.theport,s=t.$refs.theimg,n=t.$refs.root,o=s.naturalWidth,i=s.naturalHeight,a=n.offsetWidth,p=this.height/i,g=a/o;this.zoom=Math.min(p,g)}else this.zoom=1;this.translateX=0,this.translateY=0},onOriginalResize(){this.updateHeight()},updateHeight(){this.$refs.original&&(this.height=this.$refs.original.$refs.theport.getGoodContainerHeight(),this.scaleZoomRatio=this.$refs.original.$refs.theport.calcScaleZoomRatio())},reset(){this.originalInfo=null,this.convertedInfo=null,this.errorMsg=""},load(e){let t=this;t.reset(),t.loading=!0,z.post("info",{path:e},function(s){s.success||(t.errorMsg=s.data),t.loading=!1,t.originalInfo=s.original,s.converted&&(t.convertedInfo=s.converted)})}},mounted(){this.file&&this.load(this.file.path)},data(){return{zoom:1,scaleZoomRatio:1,translateX:0,translateY:0,height:100,loading:!1,errorMsg:"",originalInfo:null,convertedInfo:null}}},T=e=>(C("data-v-32d950b3"),e=e(),k(),e),st={class:"file-properties"},it={class:"path"},nt=v(" Path: "),lt={class:"path"},at={key:0,class:"error"},rt=T(()=>l("p",null," Above, you see the original image. If it has been converted, you also see the converted image (provided that your browser supports webp). ",-1)),ct=T(()=>l("p",null," You can zoom in on the image, ie using scroll wheel. Both images will zoom, allowing you to compare the quality. Double-click the image to set zoom to 100%. You can also drag the image. ",-1));function dt(e,t,s,n,o,i){const a=h("Variant");return c(),d("div",st,[l("div",it,[nt,l("span",lt,f(s.file.path),1)]),o.errorMsg?(c(),d("div",at,f(o.errorMsg),1)):u("",!0),S(l("div",null,"Getting info...",512),[[V,o.loading]]),S(_(a,{ref:"original",title:"Original",info:o.originalInfo,height:o.height,zoom:o.zoom,"onUpdate:zoom":t[0]||(t[0]=r=>o.zoom=r),scaleZoomRatio:o.scaleZoomRatio,translateX:o.translateX,"onUpdate:translateX":t[1]||(t[1]=r=>o.translateX=r),translateY:o.translateY,"onUpdate:translateY":t[2]||(t[2]=r=>o.translateY=r),onLoad:i.onOriginalLoad,onResize:i.onOriginalResize},null,8,["info","height","zoom","scaleZoomRatio","translateX","translateY","onLoad","onResize"]),[[V,o.originalInfo]]),S(_(a,{title:"Existing conversion",info:o.convertedInfo,height:o.height,zoom:o.zoom,"onUpdate:zoom":t[3]||(t[3]=r=>o.zoom=r),scaleZoomRatio:o.scaleZoomRatio,translateX:o.translateX,"onUpdate:translateX":t[4]||(t[4]=r=>o.translateX=r),translateY:o.translateY,"onUpdate:translateY":t[5]||(t[5]=r=>o.translateY=r)},null,8,["info","height","zoom","scaleZoomRatio","translateX","translateY"]),[[V,o.convertedInfo]]),rt,ct])}var ht=m(ot,[["render",dt],["__scopeId","data-v-32d950b3"]]);const ut={name:"FolderProperties",components:{},props:{file:{type:Object,default:{}}},watch:{file(e,t){}}},mt={class:"folder-properties"},_t={class:"path"},ft=v(" Path: "),pt={class:"path"},gt=l("p",null," You cannot do anything on folders yet. Browse to an image... ",-1);function vt(e,t,s,n,o,i){return c(),d("div",mt,[l("div",_t,[ft,l("span",pt,f(s.file.path),1)]),gt])}var yt=m(ut,[["render",vt]]);const zt={name:"Welcome"},bt={class:"welcome"},wt=F('<div class="headline"><div>Welcome to</div><h3>WebP Convert file manager 0.2</h3></div><p> At current stage you can browse the image files and compare the original vs the converted file.<br> To open a folder, click the "+" sign next to the folder name or double click the folder name </p><p><h4>Whats new?</h4><i>Changes in 0.2:</i><ul><li>Tree branches are now loaded on need basis (loaded the complete tree in one go was causing timeout on sites with huge amounts of images)</li></ul><i>Changes in 0.1:</i><ul><li>Everything is new! This is the first tentative pre-alpha work-in-progress release.</li></ul></p><p><h4>Whats planned ahead?</h4> Next thing is of course to enable you to trigger conversions. To support development, you can <a href="https://ko-fi.com/rosell" target="_blank">buy me a cup of coffee</a></p>',4),xt=[wt];function $t(e,t,s,n,o,i){return c(),d("div",bt,xt)}var Ct=m(zt,[["render",$t]]);const kt={name:"WCFM",components:{SVGs:K,FileProperties:ht,FolderProperties:yt,Modal:Re,Files:we,Splitpanes:X.exports.Splitpanes,Pane:X.exports.Pane,Welcome:Ct},methods:{onConvertClick(e){var n,o;let t=(o=(n=this.$refs.convertOptions)==null?void 0:n.general)==null?void 0:o.data,s={path:e,convertOptions:t};console.log(s),z.post("convert",s,function(i){console.log("convert response:",i)})},onConvertCloseClick(){console.log("CLRCL"),this.showConvertOptions=!1},onFileSelect(e,t){this.file={path:e,isDir:t}},displayInfo(e){var t=this;z.post("info",{path:e},function(s){t.selectedInfo=s})}},mounted(){var e=this;z.post("get-folder",{path:""},function(t){e.item=t.children[0]})},data(){return{file:null,selectedItem:null,item:null,treeStatusText:"loading file tree...",selectedInfo:{},showConvertOptions:!1}},provide(){return{wcfm:this}}},St={class:"wcfm",style:{overflow:"hidden"}},Vt={class:"pane-content"},It={key:0,class:"pane-content"};function Ft(e,t,s,n,o,i){const a=h("SVGs"),r=h("Files"),p=h("pane"),g=h("FileProperties"),W=h("FolderProperties"),N=h("Welcome"),Z=h("splitpanes");return c(),d("div",St,[_(a),_(Z,{class:"default-theme",style:{position:"absolute",top:"0",left:"0"}},{default:w(()=>[_(p,{size:"30"},{default:w(()=>[l("div",Vt,[l("div",null,[_(r,{item:o.item,statusText:o.treeStatusText,onSelect:i.onFileSelect},null,8,["item","statusText","onSelect"])])])]),_:1}),_(p,{size:"70",style:{"overflow-y":"auto"}},{default:w(()=>[o.file?(c(),d("div",It,[o.file.isDir?u("",!0):(c(),y(g,{key:0,file:o.file},null,8,["file"])),o.file.isDir?(c(),y(W,{key:1,file:o.file},null,8,["file"])):u("",!0)])):u("",!0),o.file?u("",!0):(c(),y(N,{key:1}))]),_:1})]),_:1})])}var Mt=m(kt,[["render",Ft]]);const I=L(Mt);I.use(Y);I.use(j,{defaultHtml:!1});window.wcfmoptions||(window.wcfmoptions={},window.wcfmoptions.poster=function(e,t,s,n){switch(e){case"get-folder":switch(t.path){case"":var o={children:[{name:"/",isDir:!0,nickname:"root"}]};break;case"/":var o={children:[{name:"empty-folder",isDir:!0,isEmpty:!0},{name:"file",isDir:!1,isConverted:!0},{name:"aaa",isDir:!1,isConverted:!0},{name:"test-folder",isDir:!0},{name:"file2",isDir:!1,isConverted:!1}]};break;case"/empty-folder":var o={children:[]};break;case"/test-folder":var o={children:[{name:"banana",isDir:!1},{name:"subfolder",isDir:!0},{name:"apple",isDir:!1}]};break;case"/test-folder/subfolder":var o={children:[{name:"file2",isDir:!1},{name:"file1",isDir:!1}]};break;default:n();return}break;case"conversion-settings":var o={systemStatus:{converterRequirements:{gd:{extensionLoaded:!1,compiledWithWebP:!0}}}};break;case"info":if(t.path=="root/file2")var o={original:{filename:"file.png",size:100,url:"http://localhost:3000/src/assets/200x100.jpg"},converted:{filename:"file.png.webp",size:70,url:"http://localhost:3000/src/assets/200x100.jpg"},log:"blah blah blah"};else if(t.path=="root/file")var o={original:{filename:"file.png",size:100,url:"http://localhost:3000/src/assets/dummy2.jpg"},log:"blah blah blah"};else var o={original:{filename:"file.png",size:100,url:"http://localhost:3000/src/assets/dummy.jpg"},converted:{filename:"file.png.webp",size:70,url:"http://localhost:3000/src/assets/dummy.jpg"},log:"blah blah blah"};break;case"convert":var o={success:!1,msg:"Image type could not be detected"};break;default:var o="ok";break}s(o)});I.mount("#webpconvert-filemanager");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -144,6 +144,7 @@ return array(
|
|
144 |
'ImageMimeTypeGuesser\\Detectors\\Stack' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/Detectors/Stack.php',
|
145 |
'ImageMimeTypeGuesser\\GuessFromExtension' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/GuessFromExtension.php',
|
146 |
'ImageMimeTypeGuesser\\ImageMimeTypeGuesser' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/ImageMimeTypeGuesser.php',
|
|
|
147 |
'WebPConvertCloudService\\AccessCheck' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/AccessCheck.php',
|
148 |
'WebPConvertCloudService\\Serve' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/Serve.php',
|
149 |
'WebPConvertCloudService\\WebPConvertCloudService' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/WebPConvertCloudService.php',
|
144 |
'ImageMimeTypeGuesser\\Detectors\\Stack' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/Detectors/Stack.php',
|
145 |
'ImageMimeTypeGuesser\\GuessFromExtension' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/GuessFromExtension.php',
|
146 |
'ImageMimeTypeGuesser\\ImageMimeTypeGuesser' => $vendorDir . '/rosell-dk/image-mime-type-guesser/src/ImageMimeTypeGuesser.php',
|
147 |
+
'KubAT\\PhpSimple\\HtmlDomParser' => $vendorDir . '/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/HtmlDomParser.php',
|
148 |
'WebPConvertCloudService\\AccessCheck' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/AccessCheck.php',
|
149 |
'WebPConvertCloudService\\Serve' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/Serve.php',
|
150 |
'WebPConvertCloudService\\WebPConvertCloudService' => $vendorDir . '/rosell-dk/webp-convert-cloud-service/src/WebPConvertCloudService.php',
|
@@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
9 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
+
'KubAT\\PhpSimple\\HtmlDomParser' => array($vendorDir . '/kub-at/php-simple-html-dom-parser/src'),
|
10 |
);
|
@@ -57,6 +57,16 @@ class ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243
|
|
57 |
),
|
58 |
);
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
public static $classMap = array (
|
61 |
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
62 |
'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php',
|
@@ -196,6 +206,7 @@ class ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243
|
|
196 |
'ImageMimeTypeGuesser\\Detectors\\Stack' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/Detectors/Stack.php',
|
197 |
'ImageMimeTypeGuesser\\GuessFromExtension' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/GuessFromExtension.php',
|
198 |
'ImageMimeTypeGuesser\\ImageMimeTypeGuesser' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/ImageMimeTypeGuesser.php',
|
|
|
199 |
'WebPConvertCloudService\\AccessCheck' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/AccessCheck.php',
|
200 |
'WebPConvertCloudService\\Serve' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/Serve.php',
|
201 |
'WebPConvertCloudService\\WebPConvertCloudService' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/WebPConvertCloudService.php',
|
@@ -280,6 +291,7 @@ class ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243
|
|
280 |
return \Closure::bind(function () use ($loader) {
|
281 |
$loader->prefixLengthsPsr4 = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$prefixLengthsPsr4;
|
282 |
$loader->prefixDirsPsr4 = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$prefixDirsPsr4;
|
|
|
283 |
$loader->classMap = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$classMap;
|
284 |
|
285 |
}, null, ClassLoader::class);
|
57 |
),
|
58 |
);
|
59 |
|
60 |
+
public static $prefixesPsr0 = array (
|
61 |
+
'K' =>
|
62 |
+
array (
|
63 |
+
'KubAT\\PhpSimple\\HtmlDomParser' =>
|
64 |
+
array (
|
65 |
+
0 => __DIR__ . '/..' . '/kub-at/php-simple-html-dom-parser/src',
|
66 |
+
),
|
67 |
+
),
|
68 |
+
);
|
69 |
+
|
70 |
public static $classMap = array (
|
71 |
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
72 |
'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php',
|
206 |
'ImageMimeTypeGuesser\\Detectors\\Stack' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/Detectors/Stack.php',
|
207 |
'ImageMimeTypeGuesser\\GuessFromExtension' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/GuessFromExtension.php',
|
208 |
'ImageMimeTypeGuesser\\ImageMimeTypeGuesser' => __DIR__ . '/..' . '/rosell-dk/image-mime-type-guesser/src/ImageMimeTypeGuesser.php',
|
209 |
+
'KubAT\\PhpSimple\\HtmlDomParser' => __DIR__ . '/..' . '/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/HtmlDomParser.php',
|
210 |
'WebPConvertCloudService\\AccessCheck' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/AccessCheck.php',
|
211 |
'WebPConvertCloudService\\Serve' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/Serve.php',
|
212 |
'WebPConvertCloudService\\WebPConvertCloudService' => __DIR__ . '/..' . '/rosell-dk/webp-convert-cloud-service/src/WebPConvertCloudService.php',
|
291 |
return \Closure::bind(function () use ($loader) {
|
292 |
$loader->prefixLengthsPsr4 = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$prefixLengthsPsr4;
|
293 |
$loader->prefixDirsPsr4 = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$prefixDirsPsr4;
|
294 |
+
$loader->prefixesPsr0 = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$prefixesPsr0;
|
295 |
$loader->classMap = ComposerStaticInit16597e36dd1bfcd787ed5a8e6d908243::$classMap;
|
296 |
|
297 |
}, null, ClassLoader::class);
|
@@ -154,27 +154,83 @@
|
|
154 |
],
|
155 |
"install-path": "./installers"
|
156 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
{
|
158 |
"name": "rosell-dk/dom-util-for-webp",
|
159 |
-
"version": "0.
|
160 |
-
"version_normalized": "0.
|
161 |
"source": {
|
162 |
"type": "git",
|
163 |
"url": "https://github.com/rosell-dk/dom-util-for-webp.git",
|
164 |
-
"reference": "
|
165 |
},
|
166 |
"dist": {
|
167 |
"type": "zip",
|
168 |
-
"url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/
|
169 |
-
"reference": "
|
170 |
"shasum": ""
|
171 |
},
|
|
|
|
|
|
|
172 |
"require-dev": {
|
173 |
"friendsofphp/php-cs-fixer": "^2.11",
|
174 |
"phpunit/phpunit": "^9.3",
|
175 |
"squizlabs/php_codesniffer": "3.*"
|
176 |
},
|
177 |
-
"time": "2021-11-
|
178 |
"type": "library",
|
179 |
"extra": {
|
180 |
"scripts-descriptions": {
|
@@ -212,7 +268,7 @@
|
|
212 |
],
|
213 |
"support": {
|
214 |
"issues": "https://github.com/rosell-dk/dom-util-for-webp/issues",
|
215 |
-
"source": "https://github.com/rosell-dk/dom-util-for-webp/tree/0.
|
216 |
},
|
217 |
"funding": [
|
218 |
{
|
154 |
],
|
155 |
"install-path": "./installers"
|
156 |
},
|
157 |
+
{
|
158 |
+
"name": "kub-at/php-simple-html-dom-parser",
|
159 |
+
"version": "1.9.1",
|
160 |
+
"version_normalized": "1.9.1.0",
|
161 |
+
"source": {
|
162 |
+
"type": "git",
|
163 |
+
"url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git",
|
164 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913"
|
165 |
+
},
|
166 |
+
"dist": {
|
167 |
+
"type": "zip",
|
168 |
+
"url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/ff22f98bfd9235115c128059076f3eb740d66913",
|
169 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913",
|
170 |
+
"shasum": ""
|
171 |
+
},
|
172 |
+
"require": {
|
173 |
+
"php": ">=5.3.2"
|
174 |
+
},
|
175 |
+
"time": "2019-10-25T12:34:43+00:00",
|
176 |
+
"type": "library",
|
177 |
+
"installation-source": "dist",
|
178 |
+
"autoload": {
|
179 |
+
"psr-0": {
|
180 |
+
"KubAT\\PhpSimple\\HtmlDomParser": "src/"
|
181 |
+
}
|
182 |
+
},
|
183 |
+
"notification-url": "https://packagist.org/downloads/",
|
184 |
+
"license": [
|
185 |
+
"MIT"
|
186 |
+
],
|
187 |
+
"authors": [
|
188 |
+
{
|
189 |
+
"name": "S.C. Chen",
|
190 |
+
"email": "me578022@gmail.com"
|
191 |
+
},
|
192 |
+
{
|
193 |
+
"name": "Jakub Stawowy",
|
194 |
+
"email": "Kub-AT@users.noreply.github.com"
|
195 |
+
}
|
196 |
+
],
|
197 |
+
"description": "PHP Simple HTML DOM Parser with namespace and PHP 7.3 compatible",
|
198 |
+
"homepage": "http://simplehtmldom.sourceforge.net/",
|
199 |
+
"keywords": [
|
200 |
+
"Simple",
|
201 |
+
"dom",
|
202 |
+
"html"
|
203 |
+
],
|
204 |
+
"support": {
|
205 |
+
"issues": "https://github.com/Kub-AT/php-simple-html-dom-parser/issues",
|
206 |
+
"source": "https://github.com/Kub-AT/php-simple-html-dom-parser/tree/master"
|
207 |
+
},
|
208 |
+
"install-path": "../kub-at/php-simple-html-dom-parser"
|
209 |
+
},
|
210 |
{
|
211 |
"name": "rosell-dk/dom-util-for-webp",
|
212 |
+
"version": "0.5.0",
|
213 |
+
"version_normalized": "0.5.0.0",
|
214 |
"source": {
|
215 |
"type": "git",
|
216 |
"url": "https://github.com/rosell-dk/dom-util-for-webp.git",
|
217 |
+
"reference": "d2554c79a0e6ffc710c2c0d646e217a9ac76dcaf"
|
218 |
},
|
219 |
"dist": {
|
220 |
"type": "zip",
|
221 |
+
"url": "https://api.github.com/repos/rosell-dk/dom-util-for-webp/zipball/d2554c79a0e6ffc710c2c0d646e217a9ac76dcaf",
|
222 |
+
"reference": "d2554c79a0e6ffc710c2c0d646e217a9ac76dcaf",
|
223 |
"shasum": ""
|
224 |
},
|
225 |
+
"require": {
|
226 |
+
"kub-at/php-simple-html-dom-parser": "^1.9"
|
227 |
+
},
|
228 |
"require-dev": {
|
229 |
"friendsofphp/php-cs-fixer": "^2.11",
|
230 |
"phpunit/phpunit": "^9.3",
|
231 |
"squizlabs/php_codesniffer": "3.*"
|
232 |
},
|
233 |
+
"time": "2021-11-10T08:51:27+00:00",
|
234 |
"type": "library",
|
235 |
"extra": {
|
236 |
"scripts-descriptions": {
|
268 |
],
|
269 |
"support": {
|
270 |
"issues": "https://github.com/rosell-dk/dom-util-for-webp/issues",
|
271 |
+
"source": "https://github.com/rosell-dk/dom-util-for-webp/tree/0.5.0"
|
272 |
},
|
273 |
"funding": [
|
274 |
{
|
@@ -5,7 +5,7 @@
|
|
5 |
'type' => 'wordpress-plugin',
|
6 |
'install_path' => __DIR__ . '/../../',
|
7 |
'aliases' => array(),
|
8 |
-
'reference' => '
|
9 |
'name' => 'rosell-dk/webp-express',
|
10 |
'dev' => true,
|
11 |
),
|
@@ -19,13 +19,22 @@
|
|
19 |
'reference' => 'd20a64ed3c94748397ff5973488761b22f6d3f19',
|
20 |
'dev_requirement' => false,
|
21 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
'rosell-dk/dom-util-for-webp' => array(
|
23 |
-
'pretty_version' => '0.
|
24 |
-
'version' => '0.
|
25 |
'type' => 'library',
|
26 |
'install_path' => __DIR__ . '/../rosell-dk/dom-util-for-webp',
|
27 |
'aliases' => array(),
|
28 |
-
'reference' => '
|
29 |
'dev_requirement' => false,
|
30 |
),
|
31 |
'rosell-dk/htaccess-capability-tester' => array(
|
@@ -70,7 +79,7 @@
|
|
70 |
'type' => 'wordpress-plugin',
|
71 |
'install_path' => __DIR__ . '/../../',
|
72 |
'aliases' => array(),
|
73 |
-
'reference' => '
|
74 |
'dev_requirement' => false,
|
75 |
),
|
76 |
'roundcube/plugin-installer' => array(
|
5 |
'type' => 'wordpress-plugin',
|
6 |
'install_path' => __DIR__ . '/../../',
|
7 |
'aliases' => array(),
|
8 |
+
'reference' => '8164dbbb89311a20d4cf5dcdf33cfac7c788cfce',
|
9 |
'name' => 'rosell-dk/webp-express',
|
10 |
'dev' => true,
|
11 |
),
|
19 |
'reference' => 'd20a64ed3c94748397ff5973488761b22f6d3f19',
|
20 |
'dev_requirement' => false,
|
21 |
),
|
22 |
+
'kub-at/php-simple-html-dom-parser' => array(
|
23 |
+
'pretty_version' => '1.9.1',
|
24 |
+
'version' => '1.9.1.0',
|
25 |
+
'type' => 'library',
|
26 |
+
'install_path' => __DIR__ . '/../kub-at/php-simple-html-dom-parser',
|
27 |
+
'aliases' => array(),
|
28 |
+
'reference' => 'ff22f98bfd9235115c128059076f3eb740d66913',
|
29 |
+
'dev_requirement' => false,
|
30 |
+
),
|
31 |
'rosell-dk/dom-util-for-webp' => array(
|
32 |
+
'pretty_version' => '0.5.0',
|
33 |
+
'version' => '0.5.0.0',
|
34 |
'type' => 'library',
|
35 |
'install_path' => __DIR__ . '/../rosell-dk/dom-util-for-webp',
|
36 |
'aliases' => array(),
|
37 |
+
'reference' => 'd2554c79a0e6ffc710c2c0d646e217a9ac76dcaf',
|
38 |
'dev_requirement' => false,
|
39 |
),
|
40 |
'rosell-dk/htaccess-capability-tester' => array(
|
79 |
'type' => 'wordpress-plugin',
|
80 |
'install_path' => __DIR__ . '/../../',
|
81 |
'aliases' => array(),
|
82 |
+
'reference' => '8164dbbb89311a20d4cf5dcdf33cfac7c788cfce',
|
83 |
'dev_requirement' => false,
|
84 |
),
|
85 |
'roundcube/plugin-installer' => array(
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
# Contributing
|
2 |
+
|
3 |
+
I'm not the maintainer of the PHP Simple HTML DOM Parser project (https://sourceforge.net/projects/simplehtmldom/)
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2019 Jakub Stawowy
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
php-simple-html-dom-parser
|
2 |
+
==========================
|
3 |
+
|
4 |
+
Version 1.9.1 - PHP 7.3 compatible
|
5 |
+
PHP Simple HTML DOM Parser changelog: https://sourceforge.net/projects/simplehtmldom/files/simplehtmldom/1.9.1/
|
6 |
+
|
7 |
+
|
8 |
+
Install
|
9 |
+
-------
|
10 |
+
|
11 |
+
```
|
12 |
+
composer require kub-at/php-simple-html-dom-parser
|
13 |
+
```
|
14 |
+
|
15 |
+
Usage
|
16 |
+
-----
|
17 |
+
|
18 |
+
```php
|
19 |
+
use KubAT\PhpSimple\HtmlDomParser;
|
20 |
+
|
21 |
+
...
|
22 |
+
$dom = HtmlDomParser::str_get_html( $str );
|
23 |
+
or
|
24 |
+
$dom = HtmlDomParser::file_get_html( $file_name );
|
25 |
+
|
26 |
+
$elems = $dom->find($elem_name);
|
27 |
+
...
|
28 |
+
|
29 |
+
```
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "kub-at/php-simple-html-dom-parser",
|
3 |
+
"description": "PHP Simple HTML DOM Parser with namespace and PHP 7.3 compatible",
|
4 |
+
"keywords": ["html", "dom", "simple"],
|
5 |
+
"homepage": "http://simplehtmldom.sourceforge.net/",
|
6 |
+
"type": "library",
|
7 |
+
"license": "MIT",
|
8 |
+
"authors": [
|
9 |
+
{
|
10 |
+
"name": "S.C. Chen",
|
11 |
+
"email": "me578022@gmail.com"
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"name": "Jakub Stawowy",
|
15 |
+
"email": "Kub-AT@users.noreply.github.com"
|
16 |
+
}
|
17 |
+
],
|
18 |
+
"require": {
|
19 |
+
"php": ">=5.3.2"
|
20 |
+
},
|
21 |
+
"autoload": {
|
22 |
+
"psr-0": { "KubAT\\PhpSimple\\HtmlDomParser": "src/" }
|
23 |
+
}
|
24 |
+
}
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace KubAT\PhpSimple;
|
3 |
+
|
4 |
+
require 'lib'.DIRECTORY_SEPARATOR.'simple_html_dom.php';
|
5 |
+
|
6 |
+
|
7 |
+
class HtmlDomParser {
|
8 |
+
|
9 |
+
static public function file_get_html() {
|
10 |
+
return call_user_func_array('\simple_html_dom\file_get_html' , func_get_args());
|
11 |
+
}
|
12 |
+
|
13 |
+
static public function str_get_html() {
|
14 |
+
return call_user_func_array('\simple_html_dom\str_get_html' , func_get_args());
|
15 |
+
}
|
16 |
+
}
|
@@ -0,0 +1,2355 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace simple_html_dom;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Website: http://sourceforge.net/projects/simplehtmldom/
|
6 |
+
* Additional projects: http://sourceforge.net/projects/debugobject/
|
7 |
+
* Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
|
8 |
+
*
|
9 |
+
* Licensed under The MIT License
|
10 |
+
* See the LICENSE file in the project root for more information.
|
11 |
+
*
|
12 |
+
* Authors:
|
13 |
+
* S.C. Chen
|
14 |
+
* John Schlick
|
15 |
+
* Rus Carroll
|
16 |
+
* logmanoriginal
|
17 |
+
*
|
18 |
+
* Contributors:
|
19 |
+
* Yousuke Kumakura
|
20 |
+
* Vadim Voituk
|
21 |
+
* Antcs
|
22 |
+
*
|
23 |
+
* Version Rev. 1.9.1 (291)
|
24 |
+
*/
|
25 |
+
|
26 |
+
define('HDOM_TYPE_ELEMENT', 1);
|
27 |
+
define('HDOM_TYPE_COMMENT', 2);
|
28 |
+
define('HDOM_TYPE_TEXT', 3);
|
29 |
+
define('HDOM_TYPE_ENDTAG', 4);
|
30 |
+
define('HDOM_TYPE_ROOT', 5);
|
31 |
+
define('HDOM_TYPE_UNKNOWN', 6);
|
32 |
+
define('HDOM_QUOTE_DOUBLE', 0);
|
33 |
+
define('HDOM_QUOTE_SINGLE', 1);
|
34 |
+
define('HDOM_QUOTE_NO', 3);
|
35 |
+
define('HDOM_INFO_BEGIN', 0);
|
36 |
+
define('HDOM_INFO_END', 1);
|
37 |
+
define('HDOM_INFO_QUOTE', 2);
|
38 |
+
define('HDOM_INFO_SPACE', 3);
|
39 |
+
define('HDOM_INFO_TEXT', 4);
|
40 |
+
define('HDOM_INFO_INNER', 5);
|
41 |
+
define('HDOM_INFO_OUTER', 6);
|
42 |
+
define('HDOM_INFO_ENDSPACE', 7);
|
43 |
+
|
44 |
+
defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
|
45 |
+
defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
|
46 |
+
defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
|
47 |
+
defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
|
48 |
+
define('HDOM_SMARTY_AS_TEXT', 1);
|
49 |
+
|
50 |
+
function file_get_html(
|
51 |
+
$url,
|
52 |
+
$use_include_path = false,
|
53 |
+
$context = null,
|
54 |
+
$offset = 0,
|
55 |
+
$maxLen = -1,
|
56 |
+
$lowercase = true,
|
57 |
+
$forceTagsClosed = true,
|
58 |
+
$target_charset = DEFAULT_TARGET_CHARSET,
|
59 |
+
$stripRN = true,
|
60 |
+
$defaultBRText = DEFAULT_BR_TEXT,
|
61 |
+
$defaultSpanText = DEFAULT_SPAN_TEXT)
|
62 |
+
{
|
63 |
+
if($maxLen <= 0) { $maxLen = MAX_FILE_SIZE; }
|
64 |
+
|
65 |
+
$dom = new simple_html_dom(
|
66 |
+
null,
|
67 |
+
$lowercase,
|
68 |
+
$forceTagsClosed,
|
69 |
+
$target_charset,
|
70 |
+
$stripRN,
|
71 |
+
$defaultBRText,
|
72 |
+
$defaultSpanText
|
73 |
+
);
|
74 |
+
|
75 |
+
/**
|
76 |
+
* For sourceforge users: uncomment the next line and comment the
|
77 |
+
* retrieve_url_contents line 2 lines down if it is not already done.
|
78 |
+
*/
|
79 |
+
$contents = file_get_contents(
|
80 |
+
$url,
|
81 |
+
$use_include_path,
|
82 |
+
$context,
|
83 |
+
$offset,
|
84 |
+
$maxLen
|
85 |
+
);
|
86 |
+
// $contents = retrieve_url_contents($url);
|
87 |
+
|
88 |
+
if (empty($contents) || strlen($contents) > $maxLen) {
|
89 |
+
$dom->clear();
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
return $dom->load($contents, $lowercase, $stripRN);
|
94 |
+
}
|
95 |
+
|
96 |
+
function str_get_html(
|
97 |
+
$str,
|
98 |
+
$lowercase = true,
|
99 |
+
$forceTagsClosed = true,
|
100 |
+
$target_charset = DEFAULT_TARGET_CHARSET,
|
101 |
+
$stripRN = true,
|
102 |
+
$defaultBRText = DEFAULT_BR_TEXT,
|
103 |
+
$defaultSpanText = DEFAULT_SPAN_TEXT)
|
104 |
+
{
|
105 |
+
$dom = new simple_html_dom(
|
106 |
+
null,
|
107 |
+
$lowercase,
|
108 |
+
$forceTagsClosed,
|
109 |
+
$target_charset,
|
110 |
+
$stripRN,
|
111 |
+
$defaultBRText,
|
112 |
+
$defaultSpanText
|
113 |
+
);
|
114 |
+
|
115 |
+
if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
|
116 |
+
$dom->clear();
|
117 |
+
return false;
|
118 |
+
}
|
119 |
+
|
120 |
+
return $dom->load($str, $lowercase, $stripRN);
|
121 |
+
}
|
122 |
+
|
123 |
+
function dump_html_tree($node, $show_attr = true, $deep = 0)
|
124 |
+
{
|
125 |
+
$node->dump($node);
|
126 |
+
}
|
127 |
+
|
128 |
+
class simple_html_dom_node
|
129 |
+
{
|
130 |
+
public $nodetype = HDOM_TYPE_TEXT;
|
131 |
+
public $tag = 'text';
|
132 |
+
public $attr = array();
|
133 |
+
public $children = array();
|
134 |
+
public $nodes = array();
|
135 |
+
public $parent = null;
|
136 |
+
public $_ = array();
|
137 |
+
public $tag_start = 0;
|
138 |
+
private $dom = null;
|
139 |
+
|
140 |
+
function __construct($dom)
|
141 |
+
{
|
142 |
+
$this->dom = $dom;
|
143 |
+
$dom->nodes[] = $this;
|
144 |
+
}
|
145 |
+
|
146 |
+
function __destruct()
|
147 |
+
{
|
148 |
+
$this->clear();
|
149 |
+
}
|
150 |
+
|
151 |
+
function __toString()
|
152 |
+
{
|
153 |
+
return $this->outertext();
|
154 |
+
}
|
155 |
+
|
156 |
+
function clear()
|
157 |
+
{
|
158 |
+
$this->dom = null;
|
159 |
+
$this->nodes = null;
|
160 |
+
$this->parent = null;
|
161 |
+
$this->children = null;
|
162 |
+
}
|
163 |
+
|
164 |
+
function dump($show_attr = true, $depth = 0)
|
165 |
+
{
|
166 |
+
echo str_repeat("\t", $depth) . $this->tag;
|
167 |
+
|
168 |
+
if ($show_attr && count($this->attr) > 0) {
|
169 |
+
echo '(';
|
170 |
+
foreach ($this->attr as $k => $v) {
|
171 |
+
echo "[$k]=>\"$v\", ";
|
172 |
+
}
|
173 |
+
echo ')';
|
174 |
+
}
|
175 |
+
|
176 |
+
echo "\n";
|
177 |
+
|
178 |
+
if ($this->nodes) {
|
179 |
+
foreach ($this->nodes as $node) {
|
180 |
+
$node->dump($show_attr, $depth + 1);
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
function dump_node($echo = true)
|
186 |
+
{
|
187 |
+
$string = $this->tag;
|
188 |
+
|
189 |
+
if (count($this->attr) > 0) {
|
190 |
+
$string .= '(';
|
191 |
+
foreach ($this->attr as $k => $v) {
|
192 |
+
$string .= "[$k]=>\"$v\", ";
|
193 |
+
}
|
194 |
+
$string .= ')';
|
195 |
+
}
|
196 |
+
|
197 |
+
if (count($this->_) > 0) {
|
198 |
+
$string .= ' $_ (';
|
199 |
+
foreach ($this->_ as $k => $v) {
|
200 |
+
if (is_array($v)) {
|
201 |
+
$string .= "[$k]=>(";
|
202 |
+
foreach ($v as $k2 => $v2) {
|
203 |
+
$string .= "[$k2]=>\"$v2\", ";
|
204 |
+
}
|
205 |
+
$string .= ')';
|
206 |
+
} else {
|
207 |
+
$string .= "[$k]=>\"$v\", ";
|
208 |
+
}
|
209 |
+
}
|
210 |
+
$string .= ')';
|
211 |
+
}
|
212 |
+
|
213 |
+
if (isset($this->text)) {
|
214 |
+
$string .= " text: ({$this->text})";
|
215 |
+
}
|
216 |
+
|
217 |
+
$string .= ' HDOM_INNER_INFO: ';
|
218 |
+
|
219 |
+
if (isset($node->_[HDOM_INFO_INNER])) {
|
220 |
+
$string .= "'" . $node->_[HDOM_INFO_INNER] . "'";
|
221 |
+
} else {
|
222 |
+
$string .= ' NULL ';
|
223 |
+
}
|
224 |
+
|
225 |
+
$string .= ' children: ' . count($this->children);
|
226 |
+
$string .= ' nodes: ' . count($this->nodes);
|
227 |
+
$string .= ' tag_start: ' . $this->tag_start;
|
228 |
+
$string .= "\n";
|
229 |
+
|
230 |
+
if ($echo) {
|
231 |
+
echo $string;
|
232 |
+
return;
|
233 |
+
} else {
|
234 |
+
return $string;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
|
238 |
+
function parent($parent = null)
|
239 |
+
{
|
240 |
+
// I am SURE that this doesn't work properly.
|
241 |
+
// It fails to unset the current node from it's current parents nodes or
|
242 |
+
// children list first.
|
243 |
+
if ($parent !== null) {
|
244 |
+
$this->parent = $parent;
|
245 |
+
$this->parent->nodes[] = $this;
|
246 |
+
$this->parent->children[] = $this;
|
247 |
+
}
|
248 |
+
|
249 |
+
return $this->parent;
|
250 |
+
}
|
251 |
+
|
252 |
+
function has_child()
|
253 |
+
{
|
254 |
+
return !empty($this->children);
|
255 |
+
}
|
256 |
+
|
257 |
+
function children($idx = -1)
|
258 |
+
{
|
259 |
+
if ($idx === -1) {
|
260 |
+
return $this->children;
|
261 |
+
}
|
262 |
+
|
263 |
+
if (isset($this->children[$idx])) {
|
264 |
+
return $this->children[$idx];
|
265 |
+
}
|
266 |
+
|
267 |
+
return null;
|
268 |
+
}
|
269 |
+
|
270 |
+
function first_child()
|
271 |
+
{
|
272 |
+
if (count($this->children) > 0) {
|
273 |
+
return $this->children[0];
|
274 |
+
}
|
275 |
+
return null;
|
276 |
+
}
|
277 |
+
|
278 |
+
function last_child()
|
279 |
+
{
|
280 |
+
if (count($this->children) > 0) {
|
281 |
+
return end($this->children);
|
282 |
+
}
|
283 |
+
return null;
|
284 |
+
}
|
285 |
+
|
286 |
+
function next_sibling()
|
287 |
+
{
|
288 |
+
if ($this->parent === null) {
|
289 |
+
return null;
|
290 |
+
}
|
291 |
+
|
292 |
+
$idx = array_search($this, $this->parent->children, true);
|
293 |
+
|
294 |
+
if ($idx !== false && isset($this->parent->children[$idx + 1])) {
|
295 |
+
return $this->parent->children[$idx + 1];
|
296 |
+
}
|
297 |
+
|
298 |
+
return null;
|
299 |
+
}
|
300 |
+
|
301 |
+
function prev_sibling()
|
302 |
+
{
|
303 |
+
if ($this->parent === null) {
|
304 |
+
return null;
|
305 |
+
}
|
306 |
+
|
307 |
+
$idx = array_search($this, $this->parent->children, true);
|
308 |
+
|
309 |
+
if ($idx !== false && $idx > 0) {
|
310 |
+
return $this->parent->children[$idx - 1];
|
311 |
+
}
|
312 |
+
|
313 |
+
return null;
|
314 |
+
}
|
315 |
+
|
316 |
+
function find_ancestor_tag($tag)
|
317 |
+
{
|
318 |
+
global $debug_object;
|
319 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
320 |
+
|
321 |
+
if ($this->parent === null) {
|
322 |
+
return null;
|
323 |
+
}
|
324 |
+
|
325 |
+
$ancestor = $this->parent;
|
326 |
+
|
327 |
+
while (!is_null($ancestor)) {
|
328 |
+
if (is_object($debug_object)) {
|
329 |
+
$debug_object->debug_log(2, 'Current tag is: ' . $ancestor->tag);
|
330 |
+
}
|
331 |
+
|
332 |
+
if ($ancestor->tag === $tag) {
|
333 |
+
break;
|
334 |
+
}
|
335 |
+
|
336 |
+
$ancestor = $ancestor->parent;
|
337 |
+
}
|
338 |
+
|
339 |
+
return $ancestor;
|
340 |
+
}
|
341 |
+
|
342 |
+
function innertext()
|
343 |
+
{
|
344 |
+
if (isset($this->_[HDOM_INFO_INNER])) {
|
345 |
+
return $this->_[HDOM_INFO_INNER];
|
346 |
+
}
|
347 |
+
|
348 |
+
if (isset($this->_[HDOM_INFO_TEXT])) {
|
349 |
+
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
350 |
+
}
|
351 |
+
|
352 |
+
$ret = '';
|
353 |
+
|
354 |
+
foreach ($this->nodes as $n) {
|
355 |
+
$ret .= $n->outertext();
|
356 |
+
}
|
357 |
+
|
358 |
+
return $ret;
|
359 |
+
}
|
360 |
+
|
361 |
+
function outertext()
|
362 |
+
{
|
363 |
+
global $debug_object;
|
364 |
+
|
365 |
+
if (is_object($debug_object)) {
|
366 |
+
$text = '';
|
367 |
+
|
368 |
+
if ($this->tag === 'text') {
|
369 |
+
if (!empty($this->text)) {
|
370 |
+
$text = ' with text: ' . $this->text;
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
|
375 |
+
}
|
376 |
+
|
377 |
+
if ($this->tag === 'root') {
|
378 |
+
return $this->innertext();
|
379 |
+
}
|
380 |
+
|
381 |
+
// todo: What is the use of this callback? Remove?
|
382 |
+
if ($this->dom && $this->dom->callback !== null) {
|
383 |
+
call_user_func_array($this->dom->callback, array($this));
|
384 |
+
}
|
385 |
+
|
386 |
+
if (isset($this->_[HDOM_INFO_OUTER])) {
|
387 |
+
return $this->_[HDOM_INFO_OUTER];
|
388 |
+
}
|
389 |
+
|
390 |
+
if (isset($this->_[HDOM_INFO_TEXT])) {
|
391 |
+
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
392 |
+
}
|
393 |
+
|
394 |
+
$ret = '';
|
395 |
+
|
396 |
+
if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
|
397 |
+
$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
|
398 |
+
}
|
399 |
+
|
400 |
+
if (isset($this->_[HDOM_INFO_INNER])) {
|
401 |
+
// todo: <br> should either never have HDOM_INFO_INNER or always
|
402 |
+
if ($this->tag !== 'br') {
|
403 |
+
$ret .= $this->_[HDOM_INFO_INNER];
|
404 |
+
}
|
405 |
+
} elseif ($this->nodes) {
|
406 |
+
foreach ($this->nodes as $n) {
|
407 |
+
$ret .= $this->convert_text($n->outertext());
|
408 |
+
}
|
409 |
+
}
|
410 |
+
|
411 |
+
if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
|
412 |
+
$ret .= '</' . $this->tag . '>';
|
413 |
+
}
|
414 |
+
|
415 |
+
return $ret;
|
416 |
+
}
|
417 |
+
|
418 |
+
function text()
|
419 |
+
{
|
420 |
+
if (isset($this->_[HDOM_INFO_INNER])) {
|
421 |
+
return $this->_[HDOM_INFO_INNER];
|
422 |
+
}
|
423 |
+
|
424 |
+
switch ($this->nodetype) {
|
425 |
+
case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
426 |
+
case HDOM_TYPE_COMMENT: return '';
|
427 |
+
case HDOM_TYPE_UNKNOWN: return '';
|
428 |
+
}
|
429 |
+
|
430 |
+
if (strcasecmp($this->tag, 'script') === 0) { return ''; }
|
431 |
+
if (strcasecmp($this->tag, 'style') === 0) { return ''; }
|
432 |
+
|
433 |
+
$ret = '';
|
434 |
+
|
435 |
+
// In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed
|
436 |
+
// for some span tags, and some p tags) $this->nodes is set to NULL.
|
437 |
+
// NOTE: This indicates that there is a problem where it's set to NULL
|
438 |
+
// without a clear happening.
|
439 |
+
// WHY is this happening?
|
440 |
+
if (!is_null($this->nodes)) {
|
441 |
+
foreach ($this->nodes as $n) {
|
442 |
+
// Start paragraph after a blank line
|
443 |
+
if ($n->tag === 'p') {
|
444 |
+
$ret = trim($ret) . "\n\n";
|
445 |
+
}
|
446 |
+
|
447 |
+
$ret .= $this->convert_text($n->text());
|
448 |
+
|
449 |
+
// If this node is a span... add a space at the end of it so
|
450 |
+
// multiple spans don't run into each other. This is plaintext
|
451 |
+
// after all.
|
452 |
+
if ($n->tag === 'span') {
|
453 |
+
$ret .= $this->dom->default_span_text;
|
454 |
+
}
|
455 |
+
}
|
456 |
+
}
|
457 |
+
return $ret;
|
458 |
+
}
|
459 |
+
|
460 |
+
function xmltext()
|
461 |
+
{
|
462 |
+
$ret = $this->innertext();
|
463 |
+
$ret = str_ireplace('<![CDATA[', '', $ret);
|
464 |
+
$ret = str_replace(']]>', '', $ret);
|
465 |
+
return $ret;
|
466 |
+
}
|
467 |
+
|
468 |
+
function makeup()
|
469 |
+
{
|
470 |
+
// text, comment, unknown
|
471 |
+
if (isset($this->_[HDOM_INFO_TEXT])) {
|
472 |
+
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
473 |
+
}
|
474 |
+
|
475 |
+
$ret = '<' . $this->tag;
|
476 |
+
$i = -1;
|
477 |
+
|
478 |
+
foreach ($this->attr as $key => $val) {
|
479 |
+
++$i;
|
480 |
+
|
481 |
+
// skip removed attribute
|
482 |
+
if ($val === null || $val === false) { continue; }
|
483 |
+
|
484 |
+
$ret .= $this->_[HDOM_INFO_SPACE][$i][0];
|
485 |
+
|
486 |
+
//no value attr: nowrap, checked selected...
|
487 |
+
if ($val === true) {
|
488 |
+
$ret .= $key;
|
489 |
+
} else {
|
490 |
+
switch ($this->_[HDOM_INFO_QUOTE][$i])
|
491 |
+
{
|
492 |
+
case HDOM_QUOTE_DOUBLE: $quote = '"'; break;
|
493 |
+
case HDOM_QUOTE_SINGLE: $quote = '\''; break;
|
494 |
+
default: $quote = '';
|
495 |
+
}
|
496 |
+
|
497 |
+
$ret .= $key
|
498 |
+
. $this->_[HDOM_INFO_SPACE][$i][1]
|
499 |
+
. '='
|
500 |
+
. $this->_[HDOM_INFO_SPACE][$i][2]
|
501 |
+
. $quote
|
502 |
+
. $val
|
503 |
+
. $quote;
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
$ret = $this->dom->restore_noise($ret);
|
508 |
+
return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
|
509 |
+
}
|
510 |
+
|
511 |
+
function find($selector, $idx = null, $lowercase = false)
|
512 |
+
{
|
513 |
+
$selectors = $this->parse_selector($selector);
|
514 |
+
if (($count = count($selectors)) === 0) { return array(); }
|
515 |
+
$found_keys = array();
|
516 |
+
|
517 |
+
// find each selector
|
518 |
+
for ($c = 0; $c < $count; ++$c) {
|
519 |
+
// The change on the below line was documented on the sourceforge
|
520 |
+
// code tracker id 2788009
|
521 |
+
// used to be: if (($levle=count($selectors[0]))===0) return array();
|
522 |
+
if (($levle = count($selectors[$c])) === 0) { return array(); }
|
523 |
+
if (!isset($this->_[HDOM_INFO_BEGIN])) { return array(); }
|
524 |
+
|
525 |
+
$head = array($this->_[HDOM_INFO_BEGIN] => 1);
|
526 |
+
$cmd = ' '; // Combinator
|
527 |
+
|
528 |
+
// handle descendant selectors, no recursive!
|
529 |
+
for ($l = 0; $l < $levle; ++$l) {
|
530 |
+
$ret = array();
|
531 |
+
|
532 |
+
foreach ($head as $k => $v) {
|
533 |
+
$n = ($k === -1) ? $this->dom->root : $this->dom->nodes[$k];
|
534 |
+
//PaperG - Pass this optional parameter on to the seek function.
|
535 |
+
$n->seek($selectors[$c][$l], $ret, $cmd, $lowercase);
|
536 |
+
}
|
537 |
+
|
538 |
+
$head = $ret;
|
539 |
+
$cmd = $selectors[$c][$l][4]; // Next Combinator
|
540 |
+
}
|
541 |
+
|
542 |
+
foreach ($head as $k => $v) {
|
543 |
+
if (!isset($found_keys[$k])) {
|
544 |
+
$found_keys[$k] = 1;
|
545 |
+
}
|
546 |
+
}
|
547 |
+
}
|
548 |
+
|
549 |
+
// sort keys
|
550 |
+
ksort($found_keys);
|
551 |
+
|
552 |
+
$found = array();
|
553 |
+
foreach ($found_keys as $k => $v) {
|
554 |
+
$found[] = $this->dom->nodes[$k];
|
555 |
+
}
|
556 |
+
|
557 |
+
// return nth-element or array
|
558 |
+
if (is_null($idx)) { return $found; }
|
559 |
+
elseif ($idx < 0) { $idx = count($found) + $idx; }
|
560 |
+
return (isset($found[$idx])) ? $found[$idx] : null;
|
561 |
+
}
|
562 |
+
|
563 |
+
protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
|
564 |
+
{
|
565 |
+
global $debug_object;
|
566 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
567 |
+
|
568 |
+
list($tag, $id, $class, $attributes, $cmb) = $selector;
|
569 |
+
$nodes = array();
|
570 |
+
|
571 |
+
if ($parent_cmd === ' ') { // Descendant Combinator
|
572 |
+
// Find parent closing tag if the current element doesn't have a closing
|
573 |
+
// tag (i.e. void element)
|
574 |
+
$end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
|
575 |
+
if ($end == 0) {
|
576 |
+
$parent = $this->parent;
|
577 |
+
while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) {
|
578 |
+
$end -= 1;
|
579 |
+
$parent = $parent->parent;
|
580 |
+
}
|
581 |
+
$end += $parent->_[HDOM_INFO_END];
|
582 |
+
}
|
583 |
+
|
584 |
+
// Get list of target nodes
|
585 |
+
$nodes_start = $this->_[HDOM_INFO_BEGIN] + 1;
|
586 |
+
$nodes_count = $end - $nodes_start;
|
587 |
+
$nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true);
|
588 |
+
} elseif ($parent_cmd === '>') { // Child Combinator
|
589 |
+
$nodes = $this->children;
|
590 |
+
} elseif ($parent_cmd === '+'
|
591 |
+
&& $this->parent
|
592 |
+
&& in_array($this, $this->parent->children)) { // Next-Sibling Combinator
|
593 |
+
$index = array_search($this, $this->parent->children, true) + 1;
|
594 |
+
if ($index < count($this->parent->children))
|
595 |
+
$nodes[] = $this->parent->children[$index];
|
596 |
+
} elseif ($parent_cmd === '~'
|
597 |
+
&& $this->parent
|
598 |
+
&& in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
|
599 |
+
$index = array_search($this, $this->parent->children, true);
|
600 |
+
$nodes = array_slice($this->parent->children, $index);
|
601 |
+
}
|
602 |
+
|
603 |
+
// Go throgh each element starting at this element until the end tag
|
604 |
+
// Note: If this element is a void tag, any previous void element is
|
605 |
+
// skipped.
|
606 |
+
foreach($nodes as $node) {
|
607 |
+
$pass = true;
|
608 |
+
|
609 |
+
// Skip root nodes
|
610 |
+
if(!$node->parent) {
|
611 |
+
$pass = false;
|
612 |
+
}
|
613 |
+
|
614 |
+
// Handle 'text' selector
|
615 |
+
if($pass && $tag === 'text' && $node->tag === 'text') {
|
616 |
+
$ret[array_search($node, $this->dom->nodes, true)] = 1;
|
617 |
+
unset($node);
|
618 |
+
continue;
|
619 |
+
}
|
620 |
+
|
621 |
+
// Skip if node isn't a child node (i.e. text nodes)
|
622 |
+
if($pass && !in_array($node, $node->parent->children, true)) {
|
623 |
+
$pass = false;
|
624 |
+
}
|
625 |
+
|
626 |
+
// Skip if tag doesn't match
|
627 |
+
if ($pass && $tag !== '' && $tag !== $node->tag && $tag !== '*') {
|
628 |
+
$pass = false;
|
629 |
+
}
|
630 |
+
|
631 |
+
// Skip if ID doesn't exist
|
632 |
+
if ($pass && $id !== '' && !isset($node->attr['id'])) {
|
633 |
+
$pass = false;
|
634 |
+
}
|
635 |
+
|
636 |
+
// Check if ID matches
|
637 |
+
if ($pass && $id !== '' && isset($node->attr['id'])) {
|
638 |
+
// Note: Only consider the first ID (as browsers do)
|
639 |
+
$node_id = explode(' ', trim($node->attr['id']))[0];
|
640 |
+
|
641 |
+
if($id !== $node_id) { $pass = false; }
|
642 |
+
}
|
643 |
+
|
644 |
+
// Check if all class(es) exist
|
645 |
+
if ($pass && $class !== '' && is_array($class) && !empty($class)) {
|
646 |
+
if (isset($node->attr['class'])) {
|
647 |
+
$node_classes = explode(' ', $node->attr['class']);
|
648 |
+
|
649 |
+
if ($lowercase) {
|
650 |
+
$node_classes = array_map('strtolower', $node_classes);
|
651 |
+
}
|
652 |
+
|
653 |
+
foreach($class as $c) {
|
654 |
+
if(!in_array($c, $node_classes)) {
|
655 |
+
$pass = false;
|
656 |
+
break;
|
657 |
+
}
|
658 |
+
}
|
659 |
+
} else {
|
660 |
+
$pass = false;
|
661 |
+
}
|
662 |
+
}
|
663 |
+
|
664 |
+
// Check attributes
|
665 |
+
if ($pass
|
666 |
+
&& $attributes !== ''
|
667 |
+
&& is_array($attributes)
|
668 |
+
&& !empty($attributes)) {
|
669 |
+
foreach($attributes as $a) {
|
670 |
+
list (
|
671 |
+
$att_name,
|
672 |
+
$att_expr,
|
673 |
+
$att_val,
|
674 |
+
$att_inv,
|
675 |
+
$att_case_sensitivity
|
676 |
+
) = $a;
|
677 |
+
|
678 |
+
// Handle indexing attributes (i.e. "[2]")
|
679 |
+
/**
|
680 |
+
* Note: This is not supported by the CSS Standard but adds
|
681 |
+
* the ability to select items compatible to XPath (i.e.
|
682 |
+
* the 3rd element within it's parent).
|
683 |
+
*
|
684 |
+
* Note: This doesn't conflict with the CSS Standard which
|
685 |
+
* doesn't work on numeric attributes anyway.
|
686 |
+
*/
|
687 |
+
if (is_numeric($att_name)
|
688 |
+
&& $att_expr === ''
|
689 |
+
&& $att_val === '') {
|
690 |
+
$count = 0;
|
691 |
+
|
692 |
+
// Find index of current element in parent
|
693 |
+
foreach ($node->parent->children as $c) {
|
694 |
+
if ($c->tag === $node->tag) ++$count;
|
695 |
+
if ($c === $node) break;
|
696 |
+
}
|
697 |
+
|
698 |
+
// If this is the correct node, continue with next
|
699 |
+
// attribute
|
700 |
+
if ($count === (int)$att_name) continue;
|
701 |
+
}
|
702 |
+
|
703 |
+
// Check attribute availability
|
704 |
+
if ($att_inv) { // Attribute should NOT be set
|
705 |
+
if (isset($node->attr[$att_name])) {
|
706 |
+
$pass = false;
|
707 |
+
break;
|
708 |
+
}
|
709 |
+
} else { // Attribute should be set
|
710 |
+
// todo: "plaintext" is not a valid CSS selector!
|
711 |
+
if ($att_name !== 'plaintext'
|
712 |
+
&& !isset($node->attr[$att_name])) {
|
713 |
+
$pass = false;
|
714 |
+
break;
|
715 |
+
}
|
716 |
+
}
|
717 |
+
|
718 |
+
// Continue with next attribute if expression isn't defined
|
719 |
+
if ($att_expr === '') continue;
|
720 |
+
|
721 |
+
// If they have told us that this is a "plaintext"
|
722 |
+
// search then we want the plaintext of the node - right?
|
723 |
+
// todo "plaintext" is not a valid CSS selector!
|
724 |
+
if ($att_name === 'plaintext') {
|
725 |
+
$nodeKeyValue = $node->text();
|
726 |
+
} else {
|
727 |
+
$nodeKeyValue = $node->attr[$att_name];
|
728 |
+
}
|
729 |
+
|
730 |
+
if (is_object($debug_object)) {
|
731 |
+
$debug_object->debug_log(2,
|
732 |
+
'testing node: '
|
733 |
+
. $node->tag
|
734 |
+
. ' for attribute: '
|
735 |
+
. $att_name
|
736 |
+
. $att_expr
|
737 |
+
. $att_val
|
738 |
+
. ' where nodes value is: '
|
739 |
+
. $nodeKeyValue
|
740 |
+
);
|
741 |
+
}
|
742 |
+
|
743 |
+
// If lowercase is set, do a case insensitive test of
|
744 |
+
// the value of the selector.
|
745 |
+
if ($lowercase) {
|
746 |
+
$check = $this->match(
|
747 |
+
$att_expr,
|
748 |
+
strtolower($att_val),
|
749 |
+
strtolower($nodeKeyValue),
|
750 |
+
$att_case_sensitivity
|
751 |
+
);
|
752 |
+
} else {
|
753 |
+
$check = $this->match(
|
754 |
+
$att_expr,
|
755 |
+
$att_val,
|
756 |
+
$nodeKeyValue,
|
757 |
+
$att_case_sensitivity
|
758 |
+
);
|
759 |
+
}
|
760 |
+
|
761 |
+
if (is_object($debug_object)) {
|
762 |
+
$debug_object->debug_log(2,
|
763 |
+
'after match: '
|
764 |
+
. ($check ? 'true' : 'false')
|
765 |
+
);
|
766 |
+
}
|
767 |
+
|
768 |
+
if (!$check) {
|
769 |
+
$pass = false;
|
770 |
+
break;
|
771 |
+
}
|
772 |
+
}
|
773 |
+
}
|
774 |
+
|
775 |
+
// Found a match. Add to list and clear node
|
776 |
+
if ($pass) $ret[$node->_[HDOM_INFO_BEGIN]] = 1;
|
777 |
+
unset($node);
|
778 |
+
}
|
779 |
+
// It's passed by reference so this is actually what this function returns.
|
780 |
+
if (is_object($debug_object)) {
|
781 |
+
$debug_object->debug_log(1, 'EXIT - ret: ', $ret);
|
782 |
+
}
|
783 |
+
}
|
784 |
+
|
785 |
+
protected function match($exp, $pattern, $value, $case_sensitivity)
|
786 |
+
{
|
787 |
+
global $debug_object;
|
788 |
+
if (is_object($debug_object)) {$debug_object->debug_log_entry(1);}
|
789 |
+
|
790 |
+
if ($case_sensitivity === 'i') {
|
791 |
+
$pattern = strtolower($pattern);
|
792 |
+
$value = strtolower($value);
|
793 |
+
}
|
794 |
+
|
795 |
+
switch ($exp) {
|
796 |
+
case '=':
|
797 |
+
return ($value === $pattern);
|
798 |
+
case '!=':
|
799 |
+
return ($value !== $pattern);
|
800 |
+
case '^=':
|
801 |
+
return preg_match('/^' . preg_quote($pattern, '/') . '/', $value);
|
802 |
+
case '$=':
|
803 |
+
return preg_match('/' . preg_quote($pattern, '/') . '$/', $value);
|
804 |
+
case '*=':
|
805 |
+
return preg_match('/' . preg_quote($pattern, '/') . '/', $value);
|
806 |
+
case '|=':
|
807 |
+
/**
|
808 |
+
* [att|=val]
|
809 |
+
*
|
810 |
+
* Represents an element with the att attribute, its value
|
811 |
+
* either being exactly "val" or beginning with "val"
|
812 |
+
* immediately followed by "-" (U+002D).
|
813 |
+
*/
|
814 |
+
return strpos($value, $pattern) === 0;
|
815 |
+
case '~=':
|
816 |
+
/**
|
817 |
+
* [att~=val]
|
818 |
+
*
|
819 |
+
* Represents an element with the att attribute whose value is a
|
820 |
+
* whitespace-separated list of words, one of which is exactly
|
821 |
+
* "val". If "val" contains whitespace, it will never represent
|
822 |
+
* anything (since the words are separated by spaces). Also if
|
823 |
+
* "val" is the empty string, it will never represent anything.
|
824 |
+
*/
|
825 |
+
return in_array($pattern, explode(' ', trim($value)), true);
|
826 |
+
}
|
827 |
+
return false;
|
828 |
+
}
|
829 |
+
|
830 |
+
protected function parse_selector($selector_string)
|
831 |
+
{
|
832 |
+
global $debug_object;
|
833 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
834 |
+
|
835 |
+
/**
|
836 |
+
* Pattern of CSS selectors, modified from mootools (https://mootools.net/)
|
837 |
+
*
|
838 |
+
* Paperg: Add the colon to the attribute, so that it properly finds
|
839 |
+
* <tag attr:ibute="something" > like google does.
|
840 |
+
*
|
841 |
+
* Note: if you try to look at this attribute, you MUST use getAttribute
|
842 |
+
* since $dom->x:y will fail the php syntax check.
|
843 |
+
*
|
844 |
+
* Notice the \[ starting the attribute? and the @? following? This
|
845 |
+
* implies that an attribute can begin with an @ sign that is not
|
846 |
+
* captured. This implies that an html attribute specifier may start
|
847 |
+
* with an @ sign that is NOT captured by the expression. Farther study
|
848 |
+
* is required to determine of this should be documented or removed.
|
849 |
+
*
|
850 |
+
* Matches selectors in this order:
|
851 |
+
*
|
852 |
+
* [0] - full match
|
853 |
+
*
|
854 |
+
* [1] - tag name
|
855 |
+
* ([\w:\*-]*)
|
856 |
+
* Matches the tag name consisting of zero or more words, colons,
|
857 |
+
* asterisks and hyphens.
|
858 |
+
*
|
859 |
+
* [2] - id name
|
860 |
+
* (?:\#([\w-]+))
|
861 |
+
* Optionally matches a id name, consisting of an "#" followed by
|
862 |
+
* the id name (one or more words and hyphens).
|
863 |
+
*
|
864 |
+
* [3] - class names (including dots)
|
865 |
+
* (?:\.([\w\.-]+))?
|
866 |
+
* Optionally matches a list of classs, consisting of an "."
|
867 |
+
* followed by the class name (one or more words and hyphens)
|
868 |
+
* where multiple classes can be chained (i.e. ".foo.bar.baz")
|
869 |
+
*
|
870 |
+
* [4] - attributes
|
871 |
+
* ((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?
|
872 |
+
* Optionally matches the attributes list
|
873 |
+
*
|
874 |
+
* [5] - separator
|
875 |
+
* ([\/, >+~]+)
|
876 |
+
* Matches the selector list separator
|
877 |
+
*/
|
878 |
+
// phpcs:ignore Generic.Files.LineLength
|
879 |
+
$pattern = "/([\w:\*-]*)(?:\#([\w-]+))?(?:|\.([\w\.-]+))?((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?([\/, >+~]+)/is";
|
880 |
+
|
881 |
+
preg_match_all(
|
882 |
+
$pattern,
|
883 |
+
trim($selector_string) . ' ', // Add final ' ' as pseudo separator
|
884 |
+
$matches,
|
885 |
+
PREG_SET_ORDER
|
886 |
+
);
|
887 |
+
|
888 |
+
if (is_object($debug_object)) {
|
889 |
+
$debug_object->debug_log(2, 'Matches Array: ', $matches);
|
890 |
+
}
|
891 |
+
|
892 |
+
$selectors = array();
|
893 |
+
$result = array();
|
894 |
+
|
895 |
+
foreach ($matches as $m) {
|
896 |
+
$m[0] = trim($m[0]);
|
897 |
+
|
898 |
+
// Skip NoOps
|
899 |
+
if ($m[0] === '' || $m[0] === '/' || $m[0] === '//') { continue; }
|
900 |
+
|
901 |
+
// Convert to lowercase
|
902 |
+
if ($this->dom->lowercase) {
|
903 |
+
$m[1] = strtolower($m[1]);
|
904 |
+
}
|
905 |
+
|
906 |
+
// Extract classes
|
907 |
+
if ($m[3] !== '') { $m[3] = explode('.', $m[3]); }
|
908 |
+
|
909 |
+
/* Extract attributes (pattern based on the pattern above!)
|
910 |
+
|
911 |
+
* [0] - full match
|
912 |
+
* [1] - attribute name
|
913 |
+
* [2] - attribute expression
|
914 |
+
* [3] - attribute value
|
915 |
+
* [4] - case sensitivity
|
916 |
+
*
|
917 |
+
* Note: Attributes can be negated with a "!" prefix to their name
|
918 |
+
*/
|
919 |
+
if($m[4] !== '') {
|
920 |
+
preg_match_all(
|
921 |
+
"/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s+?([iIsS])?)?\]/is",
|
922 |
+
trim($m[4]),
|
923 |
+
$attributes,
|
924 |
+
PREG_SET_ORDER
|
925 |
+
);
|
926 |
+
|
927 |
+
// Replace element by array
|
928 |
+
$m[4] = array();
|
929 |
+
|
930 |
+
foreach($attributes as $att) {
|
931 |
+
// Skip empty matches
|
932 |
+
if(trim($att[0]) === '') { continue; }
|
933 |
+
|
934 |
+
$inverted = (isset($att[1][0]) && $att[1][0] === '!');
|
935 |
+
$m[4][] = array(
|
936 |
+
$inverted ? substr($att[1], 1) : $att[1], // Name
|
937 |
+
(isset($att[2])) ? $att[2] : '', // Expression
|
938 |
+
(isset($att[3])) ? $att[3] : '', // Value
|
939 |
+
$inverted, // Inverted Flag
|
940 |
+
(isset($att[4])) ? strtolower($att[4]) : '', // Case-Sensitivity
|
941 |
+
);
|
942 |
+
}
|
943 |
+
}
|
944 |
+
|
945 |
+
// Sanitize Separator
|
946 |
+
if ($m[5] !== '' && trim($m[5]) === '') { // Descendant Separator
|
947 |
+
$m[5] = ' ';
|
948 |
+
} else { // Other Separator
|
949 |
+
$m[5] = trim($m[5]);
|
950 |
+
}
|
951 |
+
|
952 |
+
// Clear Separator if it's a Selector List
|
953 |
+
if ($is_list = ($m[5] === ',')) { $m[5] = ''; }
|
954 |
+
|
955 |
+
// Remove full match before adding to results
|
956 |
+
array_shift($m);
|
957 |
+
$result[] = $m;
|
958 |
+
|
959 |
+
if ($is_list) { // Selector List
|
960 |
+
$selectors[] = $result;
|
961 |
+
$result = array();
|
962 |
+
}
|
963 |
+
}
|
964 |
+
|
965 |
+
if (count($result) > 0) { $selectors[] = $result; }
|
966 |
+
return $selectors;
|
967 |
+
}
|
968 |
+
|
969 |
+
function __get($name)
|
970 |
+
{
|
971 |
+
if (isset($this->attr[$name])) {
|
972 |
+
return $this->convert_text($this->attr[$name]);
|
973 |
+
}
|
974 |
+
switch ($name) {
|
975 |
+
case 'outertext': return $this->outertext();
|
976 |
+
case 'innertext': return $this->innertext();
|
977 |
+
case 'plaintext': return $this->text();
|
978 |
+
case 'xmltext': return $this->xmltext();
|
979 |
+
default: return array_key_exists($name, $this->attr);
|
980 |
+
}
|
981 |
+
}
|
982 |
+
|
983 |
+
function __set($name, $value)
|
984 |
+
{
|
985 |
+
global $debug_object;
|
986 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
987 |
+
|
988 |
+
switch ($name) {
|
989 |
+
case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value;
|
990 |
+
case 'innertext':
|
991 |
+
if (isset($this->_[HDOM_INFO_TEXT])) {
|
992 |
+
return $this->_[HDOM_INFO_TEXT] = $value;
|
993 |
+
}
|
994 |
+
return $this->_[HDOM_INFO_INNER] = $value;
|
995 |
+
}
|
996 |
+
|
997 |
+
if (!isset($this->attr[$name])) {
|
998 |
+
$this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
|
999 |
+
$this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
$this->attr[$name] = $value;
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
function __isset($name)
|
1006 |
+
{
|
1007 |
+
switch ($name) {
|
1008 |
+
case 'outertext': return true;
|
1009 |
+
case 'innertext': return true;
|
1010 |
+
case 'plaintext': return true;
|
1011 |
+
}
|
1012 |
+
//no value attr: nowrap, checked selected...
|
1013 |
+
return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
|
1014 |
+
}
|
1015 |
+
|
1016 |
+
function __unset($name)
|
1017 |
+
{
|
1018 |
+
if (isset($this->attr[$name])) { unset($this->attr[$name]); }
|
1019 |
+
}
|
1020 |
+
|
1021 |
+
function convert_text($text)
|
1022 |
+
{
|
1023 |
+
global $debug_object;
|
1024 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
1025 |
+
|
1026 |
+
$converted_text = $text;
|
1027 |
+
|
1028 |
+
$sourceCharset = '';
|
1029 |
+
$targetCharset = '';
|
1030 |
+
|
1031 |
+
if ($this->dom) {
|
1032 |
+
$sourceCharset = strtoupper($this->dom->_charset);
|
1033 |
+
$targetCharset = strtoupper($this->dom->_target_charset);
|
1034 |
+
}
|
1035 |
+
|
1036 |
+
if (is_object($debug_object)) {
|
1037 |
+
$debug_object->debug_log(3,
|
1038 |
+
'source charset: '
|
1039 |
+
. $sourceCharset
|
1040 |
+
. ' target charaset: '
|
1041 |
+
. $targetCharset
|
1042 |
+
);
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
if (!empty($sourceCharset)
|
1046 |
+
&& !empty($targetCharset)
|
1047 |
+
&& (strcasecmp($sourceCharset, $targetCharset) != 0)) {
|
1048 |
+
// Check if the reported encoding could have been incorrect and the text is actually already UTF-8
|
1049 |
+
if ((strcasecmp($targetCharset, 'UTF-8') == 0)
|
1050 |
+
&& ($this->is_utf8($text))) {
|
1051 |
+
$converted_text = $text;
|
1052 |
+
} else {
|
1053 |
+
$converted_text = iconv($sourceCharset, $targetCharset, $text);
|
1054 |
+
}
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
// Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
|
1058 |
+
if ($targetCharset === 'UTF-8') {
|
1059 |
+
if (substr($converted_text, 0, 3) === "\xef\xbb\xbf") {
|
1060 |
+
$converted_text = substr($converted_text, 3);
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
if (substr($converted_text, -3) === "\xef\xbb\xbf") {
|
1064 |
+
$converted_text = substr($converted_text, 0, -3);
|
1065 |
+
}
|
1066 |
+
}
|
1067 |
+
|
1068 |
+
return $converted_text;
|
1069 |
+
}
|
1070 |
+
|
1071 |
+
static function is_utf8($str)
|
1072 |
+
{
|
1073 |
+
$c = 0; $b = 0;
|
1074 |
+
$bits = 0;
|
1075 |
+
$len = strlen($str);
|
1076 |
+
for($i = 0; $i < $len; $i++) {
|
1077 |
+
$c = ord($str[$i]);
|
1078 |
+
if($c > 128) {
|
1079 |
+
if(($c >= 254)) { return false; }
|
1080 |
+
elseif($c >= 252) { $bits = 6; }
|
1081 |
+
elseif($c >= 248) { $bits = 5; }
|
1082 |
+
elseif($c >= 240) { $bits = 4; }
|
1083 |
+
elseif($c >= 224) { $bits = 3; }
|
1084 |
+
elseif($c >= 192) { $bits = 2; }
|
1085 |
+
else { return false; }
|
1086 |
+
if(($i + $bits) > $len) { return false; }
|
1087 |
+
while($bits > 1) {
|
1088 |
+
$i++;
|
1089 |
+
$b = ord($str[$i]);
|
1090 |
+
if($b < 128 || $b > 191) { return false; }
|
1091 |
+
$bits--;
|
1092 |
+
}
|
1093 |
+
}
|
1094 |
+
}
|
1095 |
+
return true;
|
1096 |
+
}
|
1097 |
+
|
1098 |
+
function get_display_size()
|
1099 |
+
{
|
1100 |
+
global $debug_object;
|
1101 |
+
|
1102 |
+
$width = -1;
|
1103 |
+
$height = -1;
|
1104 |
+
|
1105 |
+
if ($this->tag !== 'img') {
|
1106 |
+
return false;
|
1107 |
+
}
|
1108 |
+
|
1109 |
+
// See if there is aheight or width attribute in the tag itself.
|
1110 |
+
if (isset($this->attr['width'])) {
|
1111 |
+
$width = $this->attr['width'];
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
if (isset($this->attr['height'])) {
|
1115 |
+
$height = $this->attr['height'];
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
// Now look for an inline style.
|
1119 |
+
if (isset($this->attr['style'])) {
|
1120 |
+
// Thanks to user gnarf from stackoverflow for this regular expression.
|
1121 |
+
$attributes = array();
|
1122 |
+
|
1123 |
+
preg_match_all(
|
1124 |
+
'/([\w-]+)\s*:\s*([^;]+)\s*;?/',
|
1125 |
+
$this->attr['style'],
|
1126 |
+
$matches,
|
1127 |
+
PREG_SET_ORDER
|
1128 |
+
);
|
1129 |
+
|
1130 |
+
foreach ($matches as $match) {
|
1131 |
+
$attributes[$match[1]] = $match[2];
|
1132 |
+
}
|
1133 |
+
|
1134 |
+
// If there is a width in the style attributes:
|
1135 |
+
if (isset($attributes['width']) && $width == -1) {
|
1136 |
+
// check that the last two characters are px (pixels)
|
1137 |
+
if (strtolower(substr($attributes['width'], -2)) === 'px') {
|
1138 |
+
$proposed_width = substr($attributes['width'], 0, -2);
|
1139 |
+
// Now make sure that it's an integer and not something stupid.
|
1140 |
+
if (filter_var($proposed_width, FILTER_VALIDATE_INT)) {
|
1141 |
+
$width = $proposed_width;
|
1142 |
+
}
|
1143 |
+
}
|
1144 |
+
}
|
1145 |
+
|
1146 |
+
// If there is a width in the style attributes:
|
1147 |
+
if (isset($attributes['height']) && $height == -1) {
|
1148 |
+
// check that the last two characters are px (pixels)
|
1149 |
+
if (strtolower(substr($attributes['height'], -2)) == 'px') {
|
1150 |
+
$proposed_height = substr($attributes['height'], 0, -2);
|
1151 |
+
// Now make sure that it's an integer and not something stupid.
|
1152 |
+
if (filter_var($proposed_height, FILTER_VALIDATE_INT)) {
|
1153 |
+
$height = $proposed_height;
|
1154 |
+
}
|
1155 |
+
}
|
1156 |
+
}
|
1157 |
+
|
1158 |
+
}
|
1159 |
+
|
1160 |
+
// Future enhancement:
|
1161 |
+
// Look in the tag to see if there is a class or id specified that has
|
1162 |
+
// a height or width attribute to it.
|
1163 |
+
|
1164 |
+
// Far future enhancement
|
1165 |
+
// Look at all the parent tags of this image to see if they specify a
|
1166 |
+
// class or id that has an img selector that specifies a height or width
|
1167 |
+
// Note that in this case, the class or id will have the img subselector
|
1168 |
+
// for it to apply to the image.
|
1169 |
+
|
1170 |
+
// ridiculously far future development
|
1171 |
+
// If the class or id is specified in a SEPARATE css file thats not on
|
1172 |
+
// the page, go get it and do what we were just doing for the ones on
|
1173 |
+
// the page.
|
1174 |
+
|
1175 |
+
$result = array(
|
1176 |
+
'height' => $height,
|
1177 |
+
'width' => $width
|
1178 |
+
);
|
1179 |
+
|
1180 |
+
return $result;
|
1181 |
+
}
|
1182 |
+
|
1183 |
+
function save($filepath = '')
|
1184 |
+
{
|
1185 |
+
$ret = $this->outertext();
|
1186 |
+
|
1187 |
+
if ($filepath !== '') {
|
1188 |
+
file_put_contents($filepath, $ret, LOCK_EX);
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
return $ret;
|
1192 |
+
}
|
1193 |
+
|
1194 |
+
function addClass($class)
|
1195 |
+
{
|
1196 |
+
if (is_string($class)) {
|
1197 |
+
$class = explode(' ', $class);
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
if (is_array($class)) {
|
1201 |
+
foreach($class as $c) {
|
1202 |
+
if (isset($this->class)) {
|
1203 |
+
if ($this->hasClass($c)) {
|
1204 |
+
continue;
|
1205 |
+
} else {
|
1206 |
+
$this->class .= ' ' . $c;
|
1207 |
+
}
|
1208 |
+
} else {
|
1209 |
+
$this->class = $c;
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
} else {
|
1213 |
+
if (is_object($debug_object)) {
|
1214 |
+
$debug_object->debug_log(2, 'Invalid type: ', gettype($class));
|
1215 |
+
}
|
1216 |
+
}
|
1217 |
+
}
|
1218 |
+
|
1219 |
+
function hasClass($class)
|
1220 |
+
{
|
1221 |
+
if (is_string($class)) {
|
1222 |
+
if (isset($this->class)) {
|
1223 |
+
return in_array($class, explode(' ', $this->class), true);
|
1224 |
+
}
|
1225 |
+
} else {
|
1226 |
+
if (is_object($debug_object)) {
|
1227 |
+
$debug_object->debug_log(2, 'Invalid type: ', gettype($class));
|
1228 |
+
}
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
return false;
|
1232 |
+
}
|
1233 |
+
|
1234 |
+
function removeClass($class = null)
|
1235 |
+
{
|
1236 |
+
if (!isset($this->class)) {
|
1237 |
+
return;
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
if (is_null($class)) {
|
1241 |
+
$this->removeAttribute('class');
|
1242 |
+
return;
|
1243 |
+
}
|
1244 |
+
|
1245 |
+
if (is_string($class)) {
|
1246 |
+
$class = explode(' ', $class);
|
1247 |
+
}
|
1248 |
+
|
1249 |
+
if (is_array($class)) {
|
1250 |
+
$class = array_diff(explode(' ', $this->class), $class);
|
1251 |
+
if (empty($class)) {
|
1252 |
+
$this->removeAttribute('class');
|
1253 |
+
} else {
|
1254 |
+
$this->class = implode(' ', $class);
|
1255 |
+
}
|
1256 |
+
}
|
1257 |
+
}
|
1258 |
+
|
1259 |
+
function getAllAttributes()
|
1260 |
+
{
|
1261 |
+
return $this->attr;
|
1262 |
+
}
|
1263 |
+
|
1264 |
+
function getAttribute($name)
|
1265 |
+
{
|
1266 |
+
return $this->__get($name);
|
1267 |
+
}
|
1268 |
+
|
1269 |
+
function setAttribute($name, $value)
|
1270 |
+
{
|
1271 |
+
$this->__set($name, $value);
|
1272 |
+
}
|
1273 |
+
|
1274 |
+
function hasAttribute($name)
|
1275 |
+
{
|
1276 |
+
return $this->__isset($name);
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
function removeAttribute($name)
|
1280 |
+
{
|
1281 |
+
$this->__set($name, null);
|
1282 |
+
}
|
1283 |
+
|
1284 |
+
function remove()
|
1285 |
+
{
|
1286 |
+
if ($this->parent) {
|
1287 |
+
$this->parent->removeChild($this);
|
1288 |
+
}
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
function removeChild($node)
|
1292 |
+
{
|
1293 |
+
$nidx = array_search($node, $this->nodes, true);
|
1294 |
+
$cidx = array_search($node, $this->children, true);
|
1295 |
+
$didx = array_search($node, $this->dom->nodes, true);
|
1296 |
+
|
1297 |
+
if ($nidx !== false && $cidx !== false && $didx !== false) {
|
1298 |
+
|
1299 |
+
foreach($node->children as $child) {
|
1300 |
+
$node->removeChild($child);
|
1301 |
+
}
|
1302 |
+
|
1303 |
+
foreach($node->nodes as $entity) {
|
1304 |
+
$enidx = array_search($entity, $node->nodes, true);
|
1305 |
+
$edidx = array_search($entity, $node->dom->nodes, true);
|
1306 |
+
|
1307 |
+
if ($enidx !== false && $edidx !== false) {
|
1308 |
+
unset($node->nodes[$enidx]);
|
1309 |
+
unset($node->dom->nodes[$edidx]);
|
1310 |
+
}
|
1311 |
+
}
|
1312 |
+
|
1313 |
+
unset($this->nodes[$nidx]);
|
1314 |
+
unset($this->children[$cidx]);
|
1315 |
+
unset($this->dom->nodes[$didx]);
|
1316 |
+
|
1317 |
+
$node->clear();
|
1318 |
+
|
1319 |
+
}
|
1320 |
+
}
|
1321 |
+
|
1322 |
+
function getElementById($id)
|
1323 |
+
{
|
1324 |
+
return $this->find("#$id", 0);
|
1325 |
+
}
|
1326 |
+
|
1327 |
+
function getElementsById($id, $idx = null)
|
1328 |
+
{
|
1329 |
+
return $this->find("#$id", $idx);
|
1330 |
+
}
|
1331 |
+
|
1332 |
+
function getElementByTagName($name)
|
1333 |
+
{
|
1334 |
+
return $this->find($name, 0);
|
1335 |
+
}
|
1336 |
+
|
1337 |
+
function getElementsByTagName($name, $idx = null)
|
1338 |
+
{
|
1339 |
+
return $this->find($name, $idx);
|
1340 |
+
}
|
1341 |
+
|
1342 |
+
function parentNode()
|
1343 |
+
{
|
1344 |
+
return $this->parent();
|
1345 |
+
}
|
1346 |
+
|
1347 |
+
function childNodes($idx = -1)
|
1348 |
+
{
|
1349 |
+
return $this->children($idx);
|
1350 |
+
}
|
1351 |
+
|
1352 |
+
function firstChild()
|
1353 |
+
{
|
1354 |
+
return $this->first_child();
|
1355 |
+
}
|
1356 |
+
|
1357 |
+
function lastChild()
|
1358 |
+
{
|
1359 |
+
return $this->last_child();
|
1360 |
+
}
|
1361 |
+
|
1362 |
+
function nextSibling()
|
1363 |
+
{
|
1364 |
+
return $this->next_sibling();
|
1365 |
+
}
|
1366 |
+
|
1367 |
+
function previousSibling()
|
1368 |
+
{
|
1369 |
+
return $this->prev_sibling();
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
function hasChildNodes()
|
1373 |
+
{
|
1374 |
+
return $this->has_child();
|
1375 |
+
}
|
1376 |
+
|
1377 |
+
function nodeName()
|
1378 |
+
{
|
1379 |
+
return $this->tag;
|
1380 |
+
}
|
1381 |
+
|
1382 |
+
function appendChild($node)
|
1383 |
+
{
|
1384 |
+
$node->parent($this);
|
1385 |
+
return $node;
|
1386 |
+
}
|
1387 |
+
|
1388 |
+
}
|
1389 |
+
|
1390 |
+
class simple_html_dom
|
1391 |
+
{
|
1392 |
+
public $root = null;
|
1393 |
+
public $nodes = array();
|
1394 |
+
public $callback = null;
|
1395 |
+
public $lowercase = false;
|
1396 |
+
public $original_size;
|
1397 |
+
public $size;
|
1398 |
+
|
1399 |
+
protected $pos;
|
1400 |
+
protected $doc;
|
1401 |
+
protected $char;
|
1402 |
+
|
1403 |
+
protected $cursor;
|
1404 |
+
protected $parent;
|
1405 |
+
protected $noise = array();
|
1406 |
+
protected $token_blank = " \t\r\n";
|
1407 |
+
protected $token_equal = ' =/>';
|
1408 |
+
protected $token_slash = " />\r\n\t";
|
1409 |
+
protected $token_attr = ' >';
|
1410 |
+
|
1411 |
+
public $_charset = '';
|
1412 |
+
public $_target_charset = '';
|
1413 |
+
|
1414 |
+
protected $default_br_text = '';
|
1415 |
+
|
1416 |
+
public $default_span_text = '';
|
1417 |
+
|
1418 |
+
protected $self_closing_tags = array(
|
1419 |
+
'area' => 1,
|
1420 |
+
'base' => 1,
|
1421 |
+
'br' => 1,
|
1422 |
+
'col' => 1,
|
1423 |
+
'embed' => 1,
|
1424 |
+
'hr' => 1,
|
1425 |
+
'img' => 1,
|
1426 |
+
'input' => 1,
|
1427 |
+
'link' => 1,
|
1428 |
+
'meta' => 1,
|
1429 |
+
'param' => 1,
|
1430 |
+
'source' => 1,
|
1431 |
+
'track' => 1,
|
1432 |
+
'wbr' => 1
|
1433 |
+
);
|
1434 |
+
protected $block_tags = array(
|
1435 |
+
'body' => 1,
|
1436 |
+
'div' => 1,
|
1437 |
+
'form' => 1,
|
1438 |
+
'root' => 1,
|
1439 |
+
'span' => 1,
|
1440 |
+
'table' => 1
|
1441 |
+
);
|
1442 |
+
protected $optional_closing_tags = array(
|
1443 |
+
// Not optional, see
|
1444 |
+
// https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
|
1445 |
+
'b' => array('b' => 1),
|
1446 |
+
'dd' => array('dd' => 1, 'dt' => 1),
|
1447 |
+
// Not optional, see
|
1448 |
+
// https://www.w3.org/TR/html/grouping-content.html#the-dl-element
|
1449 |
+
'dl' => array('dd' => 1, 'dt' => 1),
|
1450 |
+
'dt' => array('dd' => 1, 'dt' => 1),
|
1451 |
+
'li' => array('li' => 1),
|
1452 |
+
'optgroup' => array('optgroup' => 1, 'option' => 1),
|
1453 |
+
'option' => array('optgroup' => 1, 'option' => 1),
|
1454 |
+
'p' => array('p' => 1),
|
1455 |
+
'rp' => array('rp' => 1, 'rt' => 1),
|
1456 |
+
'rt' => array('rp' => 1, 'rt' => 1),
|
1457 |
+
'td' => array('td' => 1, 'th' => 1),
|
1458 |
+
'th' => array('td' => 1, 'th' => 1),
|
1459 |
+
'tr' => array('td' => 1, 'th' => 1, 'tr' => 1),
|
1460 |
+
);
|
1461 |
+
|
1462 |
+
function __construct(
|
1463 |
+
$str = null,
|
1464 |
+
$lowercase = true,
|
1465 |
+
$forceTagsClosed = true,
|
1466 |
+
$target_charset = DEFAULT_TARGET_CHARSET,
|
1467 |
+
$stripRN = true,
|
1468 |
+
$defaultBRText = DEFAULT_BR_TEXT,
|
1469 |
+
$defaultSpanText = DEFAULT_SPAN_TEXT,
|
1470 |
+
$options = 0)
|
1471 |
+
{
|
1472 |
+
if ($str) {
|
1473 |
+
if (preg_match('/^http:\/\//i', $str) || is_file($str)) {
|
1474 |
+
$this->load_file($str);
|
1475 |
+
} else {
|
1476 |
+
$this->load(
|
1477 |
+
$str,
|
1478 |
+
$lowercase,
|
1479 |
+
$stripRN,
|
1480 |
+
$defaultBRText,
|
1481 |
+
$defaultSpanText,
|
1482 |
+
$options
|
1483 |
+
);
|
1484 |
+
}
|
1485 |
+
}
|
1486 |
+
// Forcing tags to be closed implies that we don't trust the html, but
|
1487 |
+
// it can lead to parsing errors if we SHOULD trust the html.
|
1488 |
+
if (!$forceTagsClosed) {
|
1489 |
+
$this->optional_closing_array = array();
|
1490 |
+
}
|
1491 |
+
|
1492 |
+
$this->_target_charset = $target_charset;
|
1493 |
+
}
|
1494 |
+
|
1495 |
+
function __destruct()
|
1496 |
+
{
|
1497 |
+
$this->clear();
|
1498 |
+
}
|
1499 |
+
|
1500 |
+
function load(
|
1501 |
+
$str,
|
1502 |
+
$lowercase = true,
|
1503 |
+
$stripRN = true,
|
1504 |
+
$defaultBRText = DEFAULT_BR_TEXT,
|
1505 |
+
$defaultSpanText = DEFAULT_SPAN_TEXT,
|
1506 |
+
$options = 0)
|
1507 |
+
{
|
1508 |
+
global $debug_object;
|
1509 |
+
|
1510 |
+
// prepare
|
1511 |
+
$this->prepare($str, $lowercase, $defaultBRText, $defaultSpanText);
|
1512 |
+
|
1513 |
+
// Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
|
1514 |
+
// Script tags removal now preceeds style tag removal.
|
1515 |
+
// strip out <script> tags
|
1516 |
+
$this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
|
1517 |
+
$this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
|
1518 |
+
|
1519 |
+
// strip out the \r \n's if we are told to.
|
1520 |
+
if ($stripRN) {
|
1521 |
+
$this->doc = str_replace("\r", ' ', $this->doc);
|
1522 |
+
$this->doc = str_replace("\n", ' ', $this->doc);
|
1523 |
+
|
1524 |
+
// set the length of content since we have changed it.
|
1525 |
+
$this->size = strlen($this->doc);
|
1526 |
+
}
|
1527 |
+
|
1528 |
+
// strip out cdata
|
1529 |
+
$this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
|
1530 |
+
// strip out comments
|
1531 |
+
$this->remove_noise("'<!--(.*?)-->'is");
|
1532 |
+
// strip out <style> tags
|
1533 |
+
$this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
|
1534 |
+
$this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
|
1535 |
+
// strip out preformatted tags
|
1536 |
+
$this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
|
1537 |
+
// strip out server side scripts
|
1538 |
+
$this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
|
1539 |
+
|
1540 |
+
if($options & HDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts
|
1541 |
+
$this->remove_noise("'(\{\w)(.*?)(\})'s", true);
|
1542 |
+
}
|
1543 |
+
|
1544 |
+
// parsing
|
1545 |
+
$this->parse();
|
1546 |
+
// end
|
1547 |
+
$this->root->_[HDOM_INFO_END] = $this->cursor;
|
1548 |
+
$this->parse_charset();
|
1549 |
+
|
1550 |
+
// make load function chainable
|
1551 |
+
return $this;
|
1552 |
+
}
|
1553 |
+
|
1554 |
+
function load_file()
|
1555 |
+
{
|
1556 |
+
$args = func_get_args();
|
1557 |
+
|
1558 |
+
if(($doc = call_user_func_array('file_get_contents', $args)) !== false) {
|
1559 |
+
$this->load($doc, true);
|
1560 |
+
} else {
|
1561 |
+
return false;
|
1562 |
+
}
|
1563 |
+
}
|
1564 |
+
|
1565 |
+
function set_callback($function_name)
|
1566 |
+
{
|
1567 |
+
$this->callback = $function_name;
|
1568 |
+
}
|
1569 |
+
|
1570 |
+
function remove_callback()
|
1571 |
+
{
|
1572 |
+
$this->callback = null;
|
1573 |
+
}
|
1574 |
+
|
1575 |
+
function save($filepath = '')
|
1576 |
+
{
|
1577 |
+
$ret = $this->root->innertext();
|
1578 |
+
if ($filepath !== '') { file_put_contents($filepath, $ret, LOCK_EX); }
|
1579 |
+
return $ret;
|
1580 |
+
}
|
1581 |
+
|
1582 |
+
function find($selector, $idx = null, $lowercase = false)
|
1583 |
+
{
|
1584 |
+
return $this->root->find($selector, $idx, $lowercase);
|
1585 |
+
}
|
1586 |
+
|
1587 |
+
function clear()
|
1588 |
+
{
|
1589 |
+
if (isset($this->nodes)) {
|
1590 |
+
foreach ($this->nodes as $n) {
|
1591 |
+
$n->clear();
|
1592 |
+
$n = null;
|
1593 |
+
}
|
1594 |
+
}
|
1595 |
+
|
1596 |
+
// This add next line is documented in the sourceforge repository.
|
1597 |
+
// 2977248 as a fix for ongoing memory leaks that occur even with the
|
1598 |
+
// use of clear.
|
1599 |
+
if (isset($this->children)) {
|
1600 |
+
foreach ($this->children as $n) {
|
1601 |
+
$n->clear();
|
1602 |
+
$n = null;
|
1603 |
+
}
|
1604 |
+
}
|
1605 |
+
|
1606 |
+
if (isset($this->parent)) {
|
1607 |
+
$this->parent->clear();
|
1608 |
+
unset($this->parent);
|
1609 |
+
}
|
1610 |
+
|
1611 |
+
if (isset($this->root)) {
|
1612 |
+
$this->root->clear();
|
1613 |
+
unset($this->root);
|
1614 |
+
}
|
1615 |
+
|
1616 |
+
unset($this->doc);
|
1617 |
+
unset($this->noise);
|
1618 |
+
}
|
1619 |
+
|
1620 |
+
function dump($show_attr = true)
|
1621 |
+
{
|
1622 |
+
$this->root->dump($show_attr);
|
1623 |
+
}
|
1624 |
+
|
1625 |
+
protected function prepare(
|
1626 |
+
$str, $lowercase = true,
|
1627 |
+
$defaultBRText = DEFAULT_BR_TEXT,
|
1628 |
+
$defaultSpanText = DEFAULT_SPAN_TEXT)
|
1629 |
+
{
|
1630 |
+
$this->clear();
|
1631 |
+
|
1632 |
+
$this->doc = trim($str);
|
1633 |
+
$this->size = strlen($this->doc);
|
1634 |
+
$this->original_size = $this->size; // original size of the html
|
1635 |
+
$this->pos = 0;
|
1636 |
+
$this->cursor = 1;
|
1637 |
+
$this->noise = array();
|
1638 |
+
$this->nodes = array();
|
1639 |
+
$this->lowercase = $lowercase;
|
1640 |
+
$this->default_br_text = $defaultBRText;
|
1641 |
+
$this->default_span_text = $defaultSpanText;
|
1642 |
+
$this->root = new simple_html_dom_node($this);
|
1643 |
+
$this->root->tag = 'root';
|
1644 |
+
$this->root->_[HDOM_INFO_BEGIN] = -1;
|
1645 |
+
$this->root->nodetype = HDOM_TYPE_ROOT;
|
1646 |
+
$this->parent = $this->root;
|
1647 |
+
if ($this->size > 0) { $this->char = $this->doc[0]; }
|
1648 |
+
}
|
1649 |
+
|
1650 |
+
protected function parse()
|
1651 |
+
{
|
1652 |
+
while (true) {
|
1653 |
+
// Read next tag if there is no text between current position and the
|
1654 |
+
// next opening tag.
|
1655 |
+
if (($s = $this->copy_until_char('<')) === '') {
|
1656 |
+
if($this->read_tag()) {
|
1657 |
+
continue;
|
1658 |
+
} else {
|
1659 |
+
return true;
|
1660 |
+
}
|
1661 |
+
}
|
1662 |
+
|
1663 |
+
// Add a text node for text between tags
|
1664 |
+
$node = new simple_html_dom_node($this);
|
1665 |
+
++$this->cursor;
|
1666 |
+
$node->_[HDOM_INFO_TEXT] = $s;
|
1667 |
+
$this->link_nodes($node, false);
|
1668 |
+
}
|
1669 |
+
}
|
1670 |
+
|
1671 |
+
protected function parse_charset()
|
1672 |
+
{
|
1673 |
+
global $debug_object;
|
1674 |
+
|
1675 |
+
$charset = null;
|
1676 |
+
|
1677 |
+
if (function_exists('get_last_retrieve_url_contents_content_type')) {
|
1678 |
+
$contentTypeHeader = get_last_retrieve_url_contents_content_type();
|
1679 |
+
$success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
|
1680 |
+
if ($success) {
|
1681 |
+
$charset = $matches[1];
|
1682 |
+
if (is_object($debug_object)) {
|
1683 |
+
$debug_object->debug_log(2,
|
1684 |
+
'header content-type found charset of: '
|
1685 |
+
. $charset
|
1686 |
+
);
|
1687 |
+
}
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
|
1691 |
+
if (empty($charset)) {
|
1692 |
+
// https://www.w3.org/TR/html/document-metadata.html#statedef-http-equiv-content-type
|
1693 |
+
$el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
|
1694 |
+
|
1695 |
+
if (!empty($el)) {
|
1696 |
+
$fullvalue = $el->content;
|
1697 |
+
if (is_object($debug_object)) {
|
1698 |
+
$debug_object->debug_log(2,
|
1699 |
+
'meta content-type tag found'
|
1700 |
+
. $fullvalue
|
1701 |
+
);
|
1702 |
+
}
|
1703 |
+
|
1704 |
+
if (!empty($fullvalue)) {
|
1705 |
+
$success = preg_match(
|
1706 |
+
'/charset=(.+)/i',
|
1707 |
+
$fullvalue,
|
1708 |
+
$matches
|
1709 |
+
);
|
1710 |
+
|
1711 |
+
if ($success) {
|
1712 |
+
$charset = $matches[1];
|
1713 |
+
} else {
|
1714 |
+
// If there is a meta tag, and they don't specify the
|
1715 |
+
// character set, research says that it's typically
|
1716 |
+
// ISO-8859-1
|
1717 |
+
if (is_object($debug_object)) {
|
1718 |
+
$debug_object->debug_log(2,
|
1719 |
+
'meta content-type tag couldn\'t be parsed. using iso-8859 default.'
|
1720 |
+
);
|
1721 |
+
}
|
1722 |
+
|
1723 |
+
$charset = 'ISO-8859-1';
|
1724 |
+
}
|
1725 |
+
}
|
1726 |
+
}
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
if (empty($charset)) {
|
1730 |
+
// https://www.w3.org/TR/html/document-metadata.html#character-encoding-declaration
|
1731 |
+
if ($meta = $this->root->find('meta[charset]', 0)) {
|
1732 |
+
$charset = $meta->charset;
|
1733 |
+
if (is_object($debug_object)) {
|
1734 |
+
$debug_object->debug_log(2, 'meta charset: ' . $charset);
|
1735 |
+
}
|
1736 |
+
}
|
1737 |
+
}
|
1738 |
+
|
1739 |
+
if (empty($charset)) {
|
1740 |
+
// Try to guess the charset based on the content
|
1741 |
+
// Requires Multibyte String (mbstring) support (optional)
|
1742 |
+
if (function_exists('mb_detect_encoding')) {
|
1743 |
+
/**
|
1744 |
+
* mb_detect_encoding() is not intended to distinguish between
|
1745 |
+
* charsets, especially single-byte charsets. Its primary
|
1746 |
+
* purpose is to detect which multibyte encoding is in use,
|
1747 |
+
* i.e. UTF-8, UTF-16, shift-JIS, etc.
|
1748 |
+
*
|
1749 |
+
* -- https://bugs.php.net/bug.php?id=38138
|
1750 |
+
*
|
1751 |
+
* Adding both CP1251/ISO-8859-5 and CP1252/ISO-8859-1 will
|
1752 |
+
* always result in CP1251/ISO-8859-5 and vice versa.
|
1753 |
+
*
|
1754 |
+
* Thus, only detect if it's either UTF-8 or CP1252/ISO-8859-1
|
1755 |
+
* to stay compatible.
|
1756 |
+
*/
|
1757 |
+
$encoding = mb_detect_encoding(
|
1758 |
+
$this->doc,
|
1759 |
+
array( 'UTF-8', 'CP1252', 'ISO-8859-1' )
|
1760 |
+
);
|
1761 |
+
|
1762 |
+
if ($encoding === 'CP1252' || $encoding === 'ISO-8859-1') {
|
1763 |
+
// Due to a limitation of mb_detect_encoding
|
1764 |
+
// 'CP1251'/'ISO-8859-5' will be detected as
|
1765 |
+
// 'CP1252'/'ISO-8859-1'. This will cause iconv to fail, in
|
1766 |
+
// which case we can simply assume it is the other charset.
|
1767 |
+
if (!@iconv('CP1252', 'UTF-8', $this->doc)) {
|
1768 |
+
$encoding = 'CP1251';
|
1769 |
+
}
|
1770 |
+
}
|
1771 |
+
|
1772 |
+
if ($encoding !== false) {
|
1773 |
+
$charset = $encoding;
|
1774 |
+
if (is_object($debug_object)) {
|
1775 |
+
$debug_object->debug_log(2, 'mb_detect: ' . $charset);
|
1776 |
+
}
|
1777 |
+
}
|
1778 |
+
}
|
1779 |
+
}
|
1780 |
+
|
1781 |
+
if (empty($charset)) {
|
1782 |
+
// Assume it's UTF-8 as it is the most likely charset to be used
|
1783 |
+
$charset = 'UTF-8';
|
1784 |
+
if (is_object($debug_object)) {
|
1785 |
+
$debug_object->debug_log(2, 'No match found, assume ' . $charset);
|
1786 |
+
}
|
1787 |
+
}
|
1788 |
+
|
1789 |
+
// Since CP1252 is a superset, if we get one of it's subsets, we want
|
1790 |
+
// it instead.
|
1791 |
+
if ((strtolower($charset) == 'iso-8859-1')
|
1792 |
+
|| (strtolower($charset) == 'latin1')
|
1793 |
+
|| (strtolower($charset) == 'latin-1')) {
|
1794 |
+
$charset = 'CP1252';
|
1795 |
+
if (is_object($debug_object)) {
|
1796 |
+
$debug_object->debug_log(2,
|
1797 |
+
'replacing ' . $charset . ' with CP1252 as its a superset'
|
1798 |
+
);
|
1799 |
+
}
|
1800 |
+
}
|
1801 |
+
|
1802 |
+
if (is_object($debug_object)) {
|
1803 |
+
$debug_object->debug_log(1, 'EXIT - ' . $charset);
|
1804 |
+
}
|
1805 |
+
|
1806 |
+
return $this->_charset = $charset;
|
1807 |
+
}
|
1808 |
+
|
1809 |
+
protected function read_tag()
|
1810 |
+
{
|
1811 |
+
// Set end position if no further tags found
|
1812 |
+
if ($this->char !== '<') {
|
1813 |
+
$this->root->_[HDOM_INFO_END] = $this->cursor;
|
1814 |
+
return false;
|
1815 |
+
}
|
1816 |
+
|
1817 |
+
$begin_tag_pos = $this->pos;
|
1818 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1819 |
+
|
1820 |
+
// end tag
|
1821 |
+
if ($this->char === '/') {
|
1822 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1823 |
+
|
1824 |
+
// Skip whitespace in end tags (i.e. in "</ html>")
|
1825 |
+
$this->skip($this->token_blank);
|
1826 |
+
$tag = $this->copy_until_char('>');
|
1827 |
+
|
1828 |
+
// Skip attributes in end tags
|
1829 |
+
if (($pos = strpos($tag, ' ')) !== false) {
|
1830 |
+
$tag = substr($tag, 0, $pos);
|
1831 |
+
}
|
1832 |
+
|
1833 |
+
$parent_lower = strtolower($this->parent->tag);
|
1834 |
+
$tag_lower = strtolower($tag);
|
1835 |
+
|
1836 |
+
// The end tag is supposed to close the parent tag. Handle situations
|
1837 |
+
// when it doesn't
|
1838 |
+
if ($parent_lower !== $tag_lower) {
|
1839 |
+
// Parent tag does not have to be closed necessarily (optional closing tag)
|
1840 |
+
// Current tag is a block tag, so it may close an ancestor
|
1841 |
+
if (isset($this->optional_closing_tags[$parent_lower])
|
1842 |
+
&& isset($this->block_tags[$tag_lower])) {
|
1843 |
+
|
1844 |
+
$this->parent->_[HDOM_INFO_END] = 0;
|
1845 |
+
$org_parent = $this->parent;
|
1846 |
+
|
1847 |
+
// Traverse ancestors to find a matching opening tag
|
1848 |
+
// Stop at root node
|
1849 |
+
while (($this->parent->parent)
|
1850 |
+
&& strtolower($this->parent->tag) !== $tag_lower
|
1851 |
+
){
|
1852 |
+
$this->parent = $this->parent->parent;
|
1853 |
+
}
|
1854 |
+
|
1855 |
+
// If we don't have a match add current tag as text node
|
1856 |
+
if (strtolower($this->parent->tag) !== $tag_lower) {
|
1857 |
+
$this->parent = $org_parent; // restore origonal parent
|
1858 |
+
|
1859 |
+
if ($this->parent->parent) {
|
1860 |
+
$this->parent = $this->parent->parent;
|
1861 |
+
}
|
1862 |
+
|
1863 |
+
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
1864 |
+
return $this->as_text_node($tag);
|
1865 |
+
}
|
1866 |
+
} elseif (($this->parent->parent)
|
1867 |
+
&& isset($this->block_tags[$tag_lower])
|
1868 |
+
) {
|
1869 |
+
// Grandparent exists and current tag is a block tag, so our
|
1870 |
+
// parent doesn't have an end tag
|
1871 |
+
$this->parent->_[HDOM_INFO_END] = 0; // No end tag
|
1872 |
+
$org_parent = $this->parent;
|
1873 |
+
|
1874 |
+
// Traverse ancestors to find a matching opening tag
|
1875 |
+
// Stop at root node
|
1876 |
+
while (($this->parent->parent)
|
1877 |
+
&& strtolower($this->parent->tag) !== $tag_lower
|
1878 |
+
) {
|
1879 |
+
$this->parent = $this->parent->parent;
|
1880 |
+
}
|
1881 |
+
|
1882 |
+
// If we don't have a match add current tag as text node
|
1883 |
+
if (strtolower($this->parent->tag) !== $tag_lower) {
|
1884 |
+
$this->parent = $org_parent; // restore origonal parent
|
1885 |
+
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
1886 |
+
return $this->as_text_node($tag);
|
1887 |
+
}
|
1888 |
+
} elseif (($this->parent->parent)
|
1889 |
+
&& strtolower($this->parent->parent->tag) === $tag_lower
|
1890 |
+
) { // Grandparent exists and current tag closes it
|
1891 |
+
$this->parent->_[HDOM_INFO_END] = 0;
|
1892 |
+
$this->parent = $this->parent->parent;
|
1893 |
+
} else { // Random tag, add as text node
|
1894 |
+
return $this->as_text_node($tag);
|
1895 |
+
}
|
1896 |
+
}
|
1897 |
+
|
1898 |
+
// Set end position of parent tag to current cursor position
|
1899 |
+
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
1900 |
+
|
1901 |
+
if ($this->parent->parent) {
|
1902 |
+
$this->parent = $this->parent->parent;
|
1903 |
+
}
|
1904 |
+
|
1905 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1906 |
+
return true;
|
1907 |
+
}
|
1908 |
+
|
1909 |
+
// start tag
|
1910 |
+
$node = new simple_html_dom_node($this);
|
1911 |
+
$node->_[HDOM_INFO_BEGIN] = $this->cursor;
|
1912 |
+
++$this->cursor;
|
1913 |
+
$tag = $this->copy_until($this->token_slash); // Get tag name
|
1914 |
+
$node->tag_start = $begin_tag_pos;
|
1915 |
+
|
1916 |
+
// doctype, cdata & comments...
|
1917 |
+
// <!DOCTYPE html>
|
1918 |
+
// <![CDATA[ ... ]]>
|
1919 |
+
// <!-- Comment -->
|
1920 |
+
if (isset($tag[0]) && $tag[0] === '!') {
|
1921 |
+
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
|
1922 |
+
|
1923 |
+
if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--")
|
1924 |
+
$node->nodetype = HDOM_TYPE_COMMENT;
|
1925 |
+
$node->tag = 'comment';
|
1926 |
+
} else { // Could be doctype or CDATA but we don't care
|
1927 |
+
$node->nodetype = HDOM_TYPE_UNKNOWN;
|
1928 |
+
$node->tag = 'unknown';
|
1929 |
+
}
|
1930 |
+
|
1931 |
+
if ($this->char === '>') { $node->_[HDOM_INFO_TEXT] .= '>'; }
|
1932 |
+
|
1933 |
+
$this->link_nodes($node, true);
|
1934 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1935 |
+
return true;
|
1936 |
+
}
|
1937 |
+
|
1938 |
+
// The start tag cannot contain another start tag, if so add as text
|
1939 |
+
// i.e. "<<html>"
|
1940 |
+
if ($pos = strpos($tag, '<') !== false) {
|
1941 |
+
$tag = '<' . substr($tag, 0, -1);
|
1942 |
+
$node->_[HDOM_INFO_TEXT] = $tag;
|
1943 |
+
$this->link_nodes($node, false);
|
1944 |
+
$this->char = $this->doc[--$this->pos]; // prev
|
1945 |
+
return true;
|
1946 |
+
}
|
1947 |
+
|
1948 |
+
// Handle invalid tag names (i.e. "<html#doc>")
|
1949 |
+
if (!preg_match('/^\w[\w:-]*$/', $tag)) {
|
1950 |
+
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
|
1951 |
+
|
1952 |
+
// Next char is the beginning of a new tag, don't touch it.
|
1953 |
+
if ($this->char === '<') {
|
1954 |
+
$this->link_nodes($node, false);
|
1955 |
+
return true;
|
1956 |
+
}
|
1957 |
+
|
1958 |
+
// Next char closes current tag, add and be done with it.
|
1959 |
+
if ($this->char === '>') { $node->_[HDOM_INFO_TEXT] .= '>'; }
|
1960 |
+
$this->link_nodes($node, false);
|
1961 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1962 |
+
return true;
|
1963 |
+
}
|
1964 |
+
|
1965 |
+
// begin tag, add new node
|
1966 |
+
$node->nodetype = HDOM_TYPE_ELEMENT;
|
1967 |
+
$tag_lower = strtolower($tag);
|
1968 |
+
$node->tag = ($this->lowercase) ? $tag_lower : $tag;
|
1969 |
+
|
1970 |
+
// handle optional closing tags
|
1971 |
+
if (isset($this->optional_closing_tags[$tag_lower])) {
|
1972 |
+
// Traverse ancestors to close all optional closing tags
|
1973 |
+
while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
|
1974 |
+
$this->parent->_[HDOM_INFO_END] = 0;
|
1975 |
+
$this->parent = $this->parent->parent;
|
1976 |
+
}
|
1977 |
+
$node->parent = $this->parent;
|
1978 |
+
}
|
1979 |
+
|
1980 |
+
$guard = 0; // prevent infinity loop
|
1981 |
+
|
1982 |
+
// [0] Space between tag and first attribute
|
1983 |
+
$space = array($this->copy_skip($this->token_blank), '', '');
|
1984 |
+
|
1985 |
+
// attributes
|
1986 |
+
do {
|
1987 |
+
// Everything until the first equal sign should be the attribute name
|
1988 |
+
$name = $this->copy_until($this->token_equal);
|
1989 |
+
|
1990 |
+
if ($name === '' && $this->char !== null && $space[0] === '') {
|
1991 |
+
break;
|
1992 |
+
}
|
1993 |
+
|
1994 |
+
if ($guard === $this->pos) { // Escape infinite loop
|
1995 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
1996 |
+
continue;
|
1997 |
+
}
|
1998 |
+
|
1999 |
+
$guard = $this->pos;
|
2000 |
+
|
2001 |
+
// handle endless '<'
|
2002 |
+
// Out of bounds before the tag ended
|
2003 |
+
if ($this->pos >= $this->size - 1 && $this->char !== '>') {
|
2004 |
+
$node->nodetype = HDOM_TYPE_TEXT;
|
2005 |
+
$node->_[HDOM_INFO_END] = 0;
|
2006 |
+
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name;
|
2007 |
+
$node->tag = 'text';
|
2008 |
+
$this->link_nodes($node, false);
|
2009 |
+
return true;
|
2010 |
+
}
|
2011 |
+
|
2012 |
+
// handle mismatch '<'
|
2013 |
+
// Attributes cannot start after opening tag
|
2014 |
+
if ($this->doc[$this->pos - 1] == '<') {
|
2015 |
+
$node->nodetype = HDOM_TYPE_TEXT;
|
2016 |
+
$node->tag = 'text';
|
2017 |
+
$node->attr = array();
|
2018 |
+
$node->_[HDOM_INFO_END] = 0;
|
2019 |
+
$node->_[HDOM_INFO_TEXT] = substr(
|
2020 |
+
$this->doc,
|
2021 |
+
$begin_tag_pos,
|
2022 |
+
$this->pos - $begin_tag_pos - 1
|
2023 |
+
);
|
2024 |
+
$this->pos -= 2;
|
2025 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2026 |
+
$this->link_nodes($node, false);
|
2027 |
+
return true;
|
2028 |
+
}
|
2029 |
+
|
2030 |
+
if ($name !== '/' && $name !== '') { // this is a attribute name
|
2031 |
+
// [1] Whitespace after attribute name
|
2032 |
+
$space[1] = $this->copy_skip($this->token_blank);
|
2033 |
+
|
2034 |
+
$name = $this->restore_noise($name); // might be a noisy name
|
2035 |
+
|
2036 |
+
if ($this->lowercase) { $name = strtolower($name); }
|
2037 |
+
|
2038 |
+
if ($this->char === '=') { // attribute with value
|
2039 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2040 |
+
$this->parse_attr($node, $name, $space); // get attribute value
|
2041 |
+
} else {
|
2042 |
+
//no value attr: nowrap, checked selected...
|
2043 |
+
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
|
2044 |
+
$node->attr[$name] = true;
|
2045 |
+
if ($this->char != '>') { $this->char = $this->doc[--$this->pos]; } // prev
|
2046 |
+
}
|
2047 |
+
|
2048 |
+
$node->_[HDOM_INFO_SPACE][] = $space;
|
2049 |
+
|
2050 |
+
// prepare for next attribute
|
2051 |
+
$space = array(
|
2052 |
+
$this->copy_skip($this->token_blank),
|
2053 |
+
'',
|
2054 |
+
''
|
2055 |
+
);
|
2056 |
+
} else { // no more attributes
|
2057 |
+
break;
|
2058 |
+
}
|
2059 |
+
} while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended
|
2060 |
+
|
2061 |
+
$this->link_nodes($node, true);
|
2062 |
+
$node->_[HDOM_INFO_ENDSPACE] = $space[0];
|
2063 |
+
|
2064 |
+
// handle empty tags (i.e. "<div/>")
|
2065 |
+
if ($this->copy_until_char('>') === '/') {
|
2066 |
+
$node->_[HDOM_INFO_ENDSPACE] .= '/';
|
2067 |
+
$node->_[HDOM_INFO_END] = 0;
|
2068 |
+
} else {
|
2069 |
+
// reset parent
|
2070 |
+
if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
|
2071 |
+
$this->parent = $node;
|
2072 |
+
}
|
2073 |
+
}
|
2074 |
+
|
2075 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2076 |
+
|
2077 |
+
// If it's a BR tag, we need to set it's text to the default text.
|
2078 |
+
// This way when we see it in plaintext, we can generate formatting that the user wants.
|
2079 |
+
// since a br tag never has sub nodes, this works well.
|
2080 |
+
if ($node->tag === 'br') {
|
2081 |
+
$node->_[HDOM_INFO_INNER] = $this->default_br_text;
|
2082 |
+
}
|
2083 |
+
|
2084 |
+
return true;
|
2085 |
+
}
|
2086 |
+
|
2087 |
+
protected function parse_attr($node, $name, &$space)
|
2088 |
+
{
|
2089 |
+
$is_duplicate = isset($node->attr[$name]);
|
2090 |
+
|
2091 |
+
if (!$is_duplicate) // Copy whitespace between "=" and value
|
2092 |
+
$space[2] = $this->copy_skip($this->token_blank);
|
2093 |
+
|
2094 |
+
switch ($this->char) {
|
2095 |
+
case '"':
|
2096 |
+
$quote_type = HDOM_QUOTE_DOUBLE;
|
2097 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2098 |
+
$value = $this->copy_until_char('"');
|
2099 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2100 |
+
break;
|
2101 |
+
case '\'':
|
2102 |
+
$quote_type = HDOM_QUOTE_SINGLE;
|
2103 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2104 |
+
$value = $this->copy_until_char('\'');
|
2105 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2106 |
+
break;
|
2107 |
+
default:
|
2108 |
+
$quote_type = HDOM_QUOTE_NO;
|
2109 |
+
$value = $this->copy_until($this->token_attr);
|
2110 |
+
}
|
2111 |
+
|
2112 |
+
$value = $this->restore_noise($value);
|
2113 |
+
|
2114 |
+
// PaperG: Attributes should not have \r or \n in them, that counts as
|
2115 |
+
// html whitespace.
|
2116 |
+
$value = str_replace("\r", '', $value);
|
2117 |
+
$value = str_replace("\n", '', $value);
|
2118 |
+
|
2119 |
+
// PaperG: If this is a "class" selector, lets get rid of the preceeding
|
2120 |
+
// and trailing space since some people leave it in the multi class case.
|
2121 |
+
if ($name === 'class') {
|
2122 |
+
$value = trim($value);
|
2123 |
+
}
|
2124 |
+
|
2125 |
+
if (!$is_duplicate) {
|
2126 |
+
$node->_[HDOM_INFO_QUOTE][] = $quote_type;
|
2127 |
+
$node->attr[$name] = $value;
|
2128 |
+
}
|
2129 |
+
}
|
2130 |
+
|
2131 |
+
protected function link_nodes(&$node, $is_child)
|
2132 |
+
{
|
2133 |
+
$node->parent = $this->parent;
|
2134 |
+
$this->parent->nodes[] = $node;
|
2135 |
+
if ($is_child) {
|
2136 |
+
$this->parent->children[] = $node;
|
2137 |
+
}
|
2138 |
+
}
|
2139 |
+
|
2140 |
+
protected function as_text_node($tag)
|
2141 |
+
{
|
2142 |
+
$node = new simple_html_dom_node($this);
|
2143 |
+
++$this->cursor;
|
2144 |
+
$node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
|
2145 |
+
$this->link_nodes($node, false);
|
2146 |
+
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2147 |
+
return true;
|
2148 |
+
}
|
2149 |
+
|
2150 |
+
protected function skip($chars)
|
2151 |
+
{
|
2152 |
+
$this->pos += strspn($this->doc, $chars, $this->pos);
|
2153 |
+
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2154 |
+
}
|
2155 |
+
|
2156 |
+
protected function copy_skip($chars)
|
2157 |
+
{
|
2158 |
+
$pos = $this->pos;
|
2159 |
+
$len = strspn($this->doc, $chars, $pos);
|
2160 |
+
$this->pos += $len;
|
2161 |
+
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2162 |
+
if ($len === 0) { return ''; }
|
2163 |
+
return substr($this->doc, $pos, $len);
|
2164 |
+
}
|
2165 |
+
|
2166 |
+
protected function copy_until($chars)
|
2167 |
+
{
|
2168 |
+
$pos = $this->pos;
|
2169 |
+
$len = strcspn($this->doc, $chars, $pos);
|
2170 |
+
$this->pos += $len;
|
2171 |
+
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2172 |
+
return substr($this->doc, $pos, $len);
|
2173 |
+
}
|
2174 |
+
|
2175 |
+
protected function copy_until_char($char)
|
2176 |
+
{
|
2177 |
+
if ($this->char === null) { return ''; }
|
2178 |
+
|
2179 |
+
if (($pos = strpos($this->doc, $char, $this->pos)) === false) {
|
2180 |
+
$ret = substr($this->doc, $this->pos, $this->size - $this->pos);
|
2181 |
+
$this->char = null;
|
2182 |
+
$this->pos = $this->size;
|
2183 |
+
return $ret;
|
2184 |
+
}
|
2185 |
+
|
2186 |
+
if ($pos === $this->pos) { return ''; }
|
2187 |
+
|
2188 |
+
$pos_old = $this->pos;
|
2189 |
+
$this->char = $this->doc[$pos];
|
2190 |
+
$this->pos = $pos;
|
2191 |
+
return substr($this->doc, $pos_old, $pos - $pos_old);
|
2192 |
+
}
|
2193 |
+
|
2194 |
+
protected function remove_noise($pattern, $remove_tag = false)
|
2195 |
+
{
|
2196 |
+
global $debug_object;
|
2197 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
2198 |
+
|
2199 |
+
$count = preg_match_all(
|
2200 |
+
$pattern,
|
2201 |
+
$this->doc,
|
2202 |
+
$matches,
|
2203 |
+
PREG_SET_ORDER | PREG_OFFSET_CAPTURE
|
2204 |
+
);
|
2205 |
+
|
2206 |
+
for ($i = $count - 1; $i > -1; --$i) {
|
2207 |
+
$key = '___noise___' . sprintf('% 5d', count($this->noise) + 1000);
|
2208 |
+
|
2209 |
+
if (is_object($debug_object)) {
|
2210 |
+
$debug_object->debug_log(2, 'key is: ' . $key);
|
2211 |
+
}
|
2212 |
+
|
2213 |
+
$idx = ($remove_tag) ? 0 : 1; // 0 = entire match, 1 = submatch
|
2214 |
+
$this->noise[$key] = $matches[$i][$idx][0];
|
2215 |
+
$this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
|
2216 |
+
}
|
2217 |
+
|
2218 |
+
// reset the length of content
|
2219 |
+
$this->size = strlen($this->doc);
|
2220 |
+
|
2221 |
+
if ($this->size > 0) {
|
2222 |
+
$this->char = $this->doc[0];
|
2223 |
+
}
|
2224 |
+
}
|
2225 |
+
|
2226 |
+
function restore_noise($text)
|
2227 |
+
{
|
2228 |
+
global $debug_object;
|
2229 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
2230 |
+
|
2231 |
+
while (($pos = strpos($text, '___noise___')) !== false) {
|
2232 |
+
// Sometimes there is a broken piece of markup, and we don't GET the
|
2233 |
+
// pos+11 etc... token which indicates a problem outside of us...
|
2234 |
+
|
2235 |
+
// todo: "___noise___1000" (or any number with four or more digits)
|
2236 |
+
// in the DOM causes an infinite loop which could be utilized by
|
2237 |
+
// malicious software
|
2238 |
+
if (strlen($text) > $pos + 15) {
|
2239 |
+
$key = '___noise___'
|
2240 |
+
. $text[$pos + 11]
|
2241 |
+
. $text[$pos + 12]
|
2242 |
+
. $text[$pos + 13]
|
2243 |
+
. $text[$pos + 14]
|
2244 |
+
. $text[$pos + 15];
|
2245 |
+
|
2246 |
+
if (is_object($debug_object)) {
|
2247 |
+
$debug_object->debug_log(2, 'located key of: ' . $key);
|
2248 |
+
}
|
2249 |
+
|
2250 |
+
if (isset($this->noise[$key])) {
|
2251 |
+
$text = substr($text, 0, $pos)
|
2252 |
+
. $this->noise[$key]
|
2253 |
+
. substr($text, $pos + 16);
|
2254 |
+
} else {
|
2255 |
+
// do this to prevent an infinite loop.
|
2256 |
+
$text = substr($text, 0, $pos)
|
2257 |
+
. 'UNDEFINED NOISE FOR KEY: '
|
2258 |
+
. $key
|
2259 |
+
. substr($text, $pos + 16);
|
2260 |
+
}
|
2261 |
+
} else {
|
2262 |
+
// There is no valid key being given back to us... We must get
|
2263 |
+
// rid of the ___noise___ or we will have a problem.
|
2264 |
+
$text = substr($text, 0, $pos)
|
2265 |
+
. 'NO NUMERIC NOISE KEY'
|
2266 |
+
. substr($text, $pos + 11);
|
2267 |
+
}
|
2268 |
+
}
|
2269 |
+
return $text;
|
2270 |
+
}
|
2271 |
+
|
2272 |
+
function search_noise($text)
|
2273 |
+
{
|
2274 |
+
global $debug_object;
|
2275 |
+
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
2276 |
+
|
2277 |
+
foreach($this->noise as $noiseElement) {
|
2278 |
+
if (strpos($noiseElement, $text) !== false) {
|
2279 |
+
return $noiseElement;
|
2280 |
+
}
|
2281 |
+
}
|
2282 |
+
}
|
2283 |
+
|
2284 |
+
function __toString()
|
2285 |
+
{
|
2286 |
+
return $this->root->innertext();
|
2287 |
+
}
|
2288 |
+
|
2289 |
+
function __get($name)
|
2290 |
+
{
|
2291 |
+
switch ($name) {
|
2292 |
+
case 'outertext':
|
2293 |
+
return $this->root->innertext();
|
2294 |
+
case 'innertext':
|
2295 |
+
return $this->root->innertext();
|
2296 |
+
case 'plaintext':
|
2297 |
+
return $this->root->text();
|
2298 |
+
case 'charset':
|
2299 |
+
return $this->_charset;
|
2300 |
+
case 'target_charset':
|
2301 |
+
return $this->_target_charset;
|
2302 |
+
}
|
2303 |
+
}
|
2304 |
+
|
2305 |
+
function childNodes($idx = -1)
|
2306 |
+
{
|
2307 |
+
return $this->root->childNodes($idx);
|
2308 |
+
}
|
2309 |
+
|
2310 |
+
function firstChild()
|
2311 |
+
{
|
2312 |
+
return $this->root->first_child();
|
2313 |
+
}
|
2314 |
+
|
2315 |
+
function lastChild()
|
2316 |
+
{
|
2317 |
+
return $this->root->last_child();
|
2318 |
+
}
|
2319 |
+
|
2320 |
+
function createElement($name, $value = null)
|
2321 |
+
{
|
2322 |
+
return @str_get_html("<$name>$value</$name>")->firstChild();
|
2323 |
+
}
|
2324 |
+
|
2325 |
+
function createTextNode($value)
|
2326 |
+
{
|
2327 |
+
return @end(str_get_html($value)->nodes);
|
2328 |
+
}
|
2329 |
+
|
2330 |
+
function getElementById($id)
|
2331 |
+
{
|
2332 |
+
return $this->find("#$id", 0);
|
2333 |
+
}
|
2334 |
+
|
2335 |
+
function getElementsById($id, $idx = null)
|
2336 |
+
{
|
2337 |
+
return $this->find("#$id", $idx);
|
2338 |
+
}
|
2339 |
+
|
2340 |
+
function getElementByTagName($name)
|
2341 |
+
{
|
2342 |
+
return $this->find($name, 0);
|
2343 |
+
}
|
2344 |
+
|
2345 |
+
function getElementsByTagName($name, $idx = -1)
|
2346 |
+
{
|
2347 |
+
return $this->find($name, $idx);
|
2348 |
+
}
|
2349 |
+
|
2350 |
+
function loadFile()
|
2351 |
+
{
|
2352 |
+
$args = func_get_args();
|
2353 |
+
$this->load_file($args);
|
2354 |
+
}
|
2355 |
+
}
|
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
[![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://packagist.org/packages/rosell-dk/dom-util-for-webp)
|
4 |
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net)
|
5 |
-
[![Build Status](https://img.shields.io/github/workflow/status/rosell-dk/dom-util-for-webp/PHP?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/actions/workflows/php.yml)
|
6 |
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/code-structure/master)
|
7 |
[![Quality Score](https://img.shields.io/scrutinizer/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/)
|
8 |
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/blob/master/LICENSE)
|
2 |
|
3 |
[![Latest Stable Version](https://img.shields.io/packagist/v/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://packagist.org/packages/rosell-dk/dom-util-for-webp)
|
4 |
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%205.6-8892BF.svg?style=flat-square)](https://php.net)
|
5 |
+
[![Build Status](https://img.shields.io/github/workflow/status/rosell-dk/dom-util-for-webp/PHP?logo=GitHub&style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/actions/workflows/php.yml)
|
6 |
[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/code-structure/master)
|
7 |
[![Quality Score](https://img.shields.io/scrutinizer/g/rosell-dk/dom-util-for-webp.svg?style=flat-square)](https://scrutinizer-ci.com/g/rosell-dk/dom-util-for-webp/)
|
8 |
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/rosell-dk/dom-util-for-webp/blob/master/LICENSE)
|
@@ -55,5 +55,8 @@
|
|
55 |
},
|
56 |
"config": {
|
57 |
"sort-packages": true
|
|
|
|
|
|
|
58 |
}
|
59 |
}
|
55 |
},
|
56 |
"config": {
|
57 |
"sort-packages": true
|
58 |
+
},
|
59 |
+
"require": {
|
60 |
+
"kub-at/php-simple-html-dom-parser": "^1.9"
|
61 |
}
|
62 |
}
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
parameters:
|
2 |
+
ignoreErrors:
|
3 |
+
- '#Function str_get_html not found.#'
|
@@ -1,2930 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Website: http://sourceforge.net/projects/simplehtmldom/
|
4 |
-
* Additional projects: http://sourceforge.net/projects/debugobject/
|
5 |
-
* Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
|
6 |
-
* Contributions by:
|
7 |
-
* Yousuke Kumakura (Attribute filters)
|
8 |
-
* Vadim Voituk (Negative indexes supports of "find" method)
|
9 |
-
* Antcs (Constructor with automatically load contents either text or file/url)
|
10 |
-
*
|
11 |
-
* all affected sections have comments starting with "PaperG"
|
12 |
-
*
|
13 |
-
* Paperg - Added case insensitive testing of the value of the selector.
|
14 |
-
*
|
15 |
-
* Paperg - Added tag_start for the starting index of tags - NOTE: This works
|
16 |
-
* but not accurately. This tag_start gets counted AFTER \r\n have been crushed
|
17 |
-
* out, and after the remove_noice calls so it will not reflect the REAL
|
18 |
-
* position of the tag in the source, it will almost always be smaller by some
|
19 |
-
* amount. We use this to determine how far into the file the tag in question
|
20 |
-
* is. This "percentage" will never be accurate as the $dom->size is the "real"
|
21 |
-
* number of bytes the dom was created from. But for most purposes, it's a
|
22 |
-
* really good estimation.
|
23 |
-
*
|
24 |
-
* Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags
|
25 |
-
* closed is great for malformed html, but it CAN lead to parsing errors.
|
26 |
-
*
|
27 |
-
* Allow the user to tell us how much they trust the html.
|
28 |
-
*
|
29 |
-
* Paperg add the text and plaintext to the selectors for the find syntax.
|
30 |
-
* plaintext implies text in the innertext of a node. text implies that the
|
31 |
-
* tag is a text node. This allows for us to find tags based on the text they
|
32 |
-
* contain.
|
33 |
-
*
|
34 |
-
* Create find_ancestor_tag to see if a tag is - at any level - inside of
|
35 |
-
* another specific tag.
|
36 |
-
*
|
37 |
-
* Paperg: added parse_charset so that we know about the character set of
|
38 |
-
* the source document. NOTE: If the user's system has a routine called
|
39 |
-
* get_last_retrieve_url_contents_content_type availalbe, we will assume it's
|
40 |
-
* returning the content-type header from the last transfer or curl_exec, and
|
41 |
-
* we will parse that and use it in preference to any other method of charset
|
42 |
-
* detection.
|
43 |
-
*
|
44 |
-
* Found infinite loop in the case of broken html in restore_noise. Rewrote to
|
45 |
-
* protect from that.
|
46 |
-
*
|
47 |
-
* PaperG (John Schlick) Added get_display_size for "IMG" tags.
|
48 |
-
*
|
49 |
-
* Licensed under The MIT License
|
50 |
-
* Redistributions of files must retain the above copyright notice.
|
51 |
-
*
|
52 |
-
* @author S.C. Chen <me578022@gmail.com>
|
53 |
-
* @author John Schlick
|
54 |
-
* @author Rus Carroll
|
55 |
-
* @version Rev. 1.8.1 (247)
|
56 |
-
* @package PlaceLocalInclude
|
57 |
-
* @subpackage simple_html_dom
|
58 |
-
*/
|
59 |
-
|
60 |
-
/**
|
61 |
-
* All of the Defines for the classes below.
|
62 |
-
* @author S.C. Chen <me578022@gmail.com>
|
63 |
-
*/
|
64 |
-
define('HDOM_TYPE_ELEMENT', 1);
|
65 |
-
define('HDOM_TYPE_COMMENT', 2);
|
66 |
-
define('HDOM_TYPE_TEXT', 3);
|
67 |
-
define('HDOM_TYPE_ENDTAG', 4);
|
68 |
-
define('HDOM_TYPE_ROOT', 5);
|
69 |
-
define('HDOM_TYPE_UNKNOWN', 6);
|
70 |
-
define('HDOM_QUOTE_DOUBLE', 0);
|
71 |
-
define('HDOM_QUOTE_SINGLE', 1);
|
72 |
-
define('HDOM_QUOTE_NO', 3);
|
73 |
-
define('HDOM_INFO_BEGIN', 0);
|
74 |
-
define('HDOM_INFO_END', 1);
|
75 |
-
define('HDOM_INFO_QUOTE', 2);
|
76 |
-
define('HDOM_INFO_SPACE', 3);
|
77 |
-
define('HDOM_INFO_TEXT', 4);
|
78 |
-
define('HDOM_INFO_INNER', 5);
|
79 |
-
define('HDOM_INFO_OUTER', 6);
|
80 |
-
define('HDOM_INFO_ENDSPACE', 7);
|
81 |
-
|
82 |
-
/** The default target charset */
|
83 |
-
defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
|
84 |
-
|
85 |
-
/** The default <br> text used instead of <br> tags when returning text */
|
86 |
-
defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
|
87 |
-
|
88 |
-
/** The default <span> text used instead of <span> tags when returning text */
|
89 |
-
defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
|
90 |
-
|
91 |
-
/** The maximum file size the parser should load */
|
92 |
-
defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
|
93 |
-
|
94 |
-
/** Contents between curly braces "{" and "}" are interpreted as text */
|
95 |
-
define('HDOM_SMARTY_AS_TEXT', 1);
|
96 |
-
|
97 |
-
// helper functions
|
98 |
-
// -----------------------------------------------------------------------------
|
99 |
-
// get html dom from file
|
100 |
-
// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
|
101 |
-
function file_get_html(
|
102 |
-
$url,
|
103 |
-
$use_include_path = false,
|
104 |
-
$context = null,
|
105 |
-
$offset = 0,
|
106 |
-
$maxLen = -1,
|
107 |
-
$lowercase = true,
|
108 |
-
$forceTagsClosed = true,
|
109 |
-
$target_charset = DEFAULT_TARGET_CHARSET,
|
110 |
-
$stripRN = true,
|
111 |
-
$defaultBRText = DEFAULT_BR_TEXT,
|
112 |
-
$defaultSpanText = DEFAULT_SPAN_TEXT
|
113 |
-
) {
|
114 |
-
// Ensure maximum length is greater than zero
|
115 |
-
if ($maxLen <= 0) {
|
116 |
-
$maxLen = MAX_FILE_SIZE;
|
117 |
-
}
|
118 |
-
|
119 |
-
// We DO force the tags to be terminated.
|
120 |
-
$dom = new simple_html_dom(
|
121 |
-
null,
|
122 |
-
$lowercase,
|
123 |
-
$forceTagsClosed,
|
124 |
-
$target_charset,
|
125 |
-
$stripRN,
|
126 |
-
$defaultBRText,
|
127 |
-
$defaultSpanText
|
128 |
-
);
|
129 |
-
|
130 |
-
/**
|
131 |
-
* For sourceforge users: uncomment the next line and comment the
|
132 |
-
* retrieve_url_contents line 2 lines down if it is not already done.
|
133 |
-
*/
|
134 |
-
$contents = file_get_contents(
|
135 |
-
$url,
|
136 |
-
$use_include_path,
|
137 |
-
$context,
|
138 |
-
$offset,
|
139 |
-
$maxLen
|
140 |
-
);
|
141 |
-
|
142 |
-
// Paperg - use our own mechanism for getting the contents as we want to
|
143 |
-
// control the timeout.
|
144 |
-
// $contents = retrieve_url_contents($url);
|
145 |
-
if (empty($contents) || strlen($contents) > $maxLen) {
|
146 |
-
return false;
|
147 |
-
}
|
148 |
-
|
149 |
-
// The second parameter can force the selectors to all be lowercase.
|
150 |
-
$dom->load($contents, $lowercase, $stripRN);
|
151 |
-
return $dom;
|
152 |
-
}
|
153 |
-
|
154 |
-
// get html dom from string
|
155 |
-
function str_get_html(
|
156 |
-
$str,
|
157 |
-
$lowercase = true,
|
158 |
-
$forceTagsClosed = true,
|
159 |
-
$target_charset = DEFAULT_TARGET_CHARSET,
|
160 |
-
$stripRN = true,
|
161 |
-
$defaultBRText = DEFAULT_BR_TEXT,
|
162 |
-
$defaultSpanText = DEFAULT_SPAN_TEXT
|
163 |
-
) {
|
164 |
-
$dom = new simple_html_dom(
|
165 |
-
null,
|
166 |
-
$lowercase,
|
167 |
-
$forceTagsClosed,
|
168 |
-
$target_charset,
|
169 |
-
$stripRN,
|
170 |
-
$defaultBRText,
|
171 |
-
$defaultSpanText
|
172 |
-
);
|
173 |
-
|
174 |
-
if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
|
175 |
-
$dom->clear();
|
176 |
-
return false;
|
177 |
-
}
|
178 |
-
|
179 |
-
$dom->load($str, $lowercase, $stripRN);
|
180 |
-
return $dom;
|
181 |
-
}
|
182 |
-
|
183 |
-
// dump html dom tree
|
184 |
-
function dump_html_tree($node, $show_attr = true, $deep = 0)
|
185 |
-
{
|
186 |
-
$node->dump($node);
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* simple html dom node
|
191 |
-
* PaperG - added ability for "find" routine to lowercase the value of the
|
192 |
-
* selector.
|
193 |
-
*
|
194 |
-
* PaperG - added $tag_start to track the start position of the tag in the total
|
195 |
-
* byte index
|
196 |
-
*
|
197 |
-
* @package PlaceLocalInclude
|
198 |
-
*/
|
199 |
-
class simple_html_dom_node
|
200 |
-
{
|
201 |
-
/**
|
202 |
-
* Node type
|
203 |
-
*
|
204 |
-
* Default is {@see HDOM_TYPE_TEXT}
|
205 |
-
*
|
206 |
-
* @var int
|
207 |
-
*/
|
208 |
-
public $nodetype = HDOM_TYPE_TEXT;
|
209 |
-
|
210 |
-
/**
|
211 |
-
* Tag name
|
212 |
-
*
|
213 |
-
* Default is 'text'
|
214 |
-
*
|
215 |
-
* @var string
|
216 |
-
*/
|
217 |
-
public $tag = 'text';
|
218 |
-
|
219 |
-
/**
|
220 |
-
* List of attributes
|
221 |
-
*
|
222 |
-
* @var array
|
223 |
-
*/
|
224 |
-
public $attr = array();
|
225 |
-
|
226 |
-
/**
|
227 |
-
* List of child node objects
|
228 |
-
*
|
229 |
-
* @var array
|
230 |
-
*/
|
231 |
-
public $children = array();
|
232 |
-
public $nodes = array();
|
233 |
-
|
234 |
-
/**
|
235 |
-
* The parent node object
|
236 |
-
*
|
237 |
-
* @var object|null
|
238 |
-
*/
|
239 |
-
public $parent = null;
|
240 |
-
|
241 |
-
// The "info" array - see HDOM_INFO_... for what each element contains.
|
242 |
-
public $_ = array();
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Start position of the tag in the document
|
246 |
-
*
|
247 |
-
* @var int
|
248 |
-
*/
|
249 |
-
public $tag_start = 0;
|
250 |
-
|
251 |
-
/**
|
252 |
-
* The DOM object
|
253 |
-
*
|
254 |
-
* @var object|null
|
255 |
-
*/
|
256 |
-
private $dom = null;
|
257 |
-
|
258 |
-
/**
|
259 |
-
* Construct new node object
|
260 |
-
*
|
261 |
-
* Adds itself to the list of DOM Nodes {@see simple_html_dom::$nodes}
|
262 |
-
*/
|
263 |
-
function __construct($dom)
|
264 |
-
{
|
265 |
-
$this->dom = $dom;
|
266 |
-
$dom->nodes[] = $this;
|
267 |
-
}
|
268 |
-
|
269 |
-
function __destruct()
|
270 |
-
{
|
271 |
-
$this->clear();
|
272 |
-
}
|
273 |
-
|
274 |
-
function __toString()
|
275 |
-
{
|
276 |
-
return $this->outertext();
|
277 |
-
}
|
278 |
-
|
279 |
-
// clean up memory due to php5 circular references memory leak...
|
280 |
-
function clear()
|
281 |
-
{
|
282 |
-
$this->dom = null;
|
283 |
-
$this->nodes = null;
|
284 |
-
$this->parent = null;
|
285 |
-
$this->children = null;
|
286 |
-
}
|
287 |
-
|
288 |
-
// dump node's tree
|
289 |
-
function dump($show_attr = true, $deep = 0)
|
290 |
-
{
|
291 |
-
$lead = str_repeat(' ', $deep);
|
292 |
-
|
293 |
-
echo $lead . $this->tag;
|
294 |
-
|
295 |
-
if ($show_attr && count($this->attr) > 0) {
|
296 |
-
echo '(';
|
297 |
-
foreach ($this->attr as $k => $v) {
|
298 |
-
echo "[$k]=>\"" . $this->$k . '", ';
|
299 |
-
}
|
300 |
-
echo ')';
|
301 |
-
}
|
302 |
-
|
303 |
-
echo "\n";
|
304 |
-
|
305 |
-
if ($this->nodes) {
|
306 |
-
foreach ($this->nodes as $c) {
|
307 |
-
$c->dump($show_attr, $deep + 1);
|
308 |
-
}
|
309 |
-
}
|
310 |
-
}
|
311 |
-
|
312 |
-
|
313 |
-
// Debugging function to dump a single dom node with a bunch of information about it.
|
314 |
-
function dump_node($echo = true)
|
315 |
-
{
|
316 |
-
$string = $this->tag;
|
317 |
-
|
318 |
-
if (count($this->attr) > 0) {
|
319 |
-
$string .= '(';
|
320 |
-
foreach ($this->attr as $k => $v) {
|
321 |
-
$string .= "[$k]=>\"" . $this->$k . '", ';
|
322 |
-
}
|
323 |
-
$string .= ')';
|
324 |
-
}
|
325 |
-
|
326 |
-
if (count($this->_) > 0) {
|
327 |
-
$string .= ' $_ (';
|
328 |
-
foreach ($this->_ as $k => $v) {
|
329 |
-
if (is_array($v)) {
|
330 |
-
$string .= "[$k]=>(";
|
331 |
-
foreach ($v as $k2 => $v2) {
|
332 |
-
$string .= "[$k2]=>\"" . $v2 . '", ';
|
333 |
-
}
|
334 |
-
$string .= ')';
|
335 |
-
} else {
|
336 |
-
$string .= "[$k]=>\"" . $v . '", ';
|
337 |
-
}
|
338 |
-
}
|
339 |
-
$string .= ')';
|
340 |
-
}
|
341 |
-
|
342 |
-
if (isset($this->text)) {
|
343 |
-
$string .= ' text: (' . $this->text . ')';
|
344 |
-
}
|
345 |
-
|
346 |
-
$string .= " HDOM_INNER_INFO: '";
|
347 |
-
|
348 |
-
if (isset($node->_[HDOM_INFO_INNER])) {
|
349 |
-
$string .= $node->_[HDOM_INFO_INNER] . "'";
|
350 |
-
} else {
|
351 |
-
$string .= ' NULL ';
|
352 |
-
}
|
353 |
-
|
354 |
-
$string .= ' children: ' . count($this->children);
|
355 |
-
$string .= ' nodes: ' . count($this->nodes);
|
356 |
-
$string .= ' tag_start: ' . $this->tag_start;
|
357 |
-
$string .= "\n";
|
358 |
-
|
359 |
-
if ($echo) {
|
360 |
-
echo $string;
|
361 |
-
return;
|
362 |
-
} else {
|
363 |
-
return $string;
|
364 |
-
}
|
365 |
-
}
|
366 |
-
|
367 |
-
/**
|
368 |
-
* Return or set parent node
|
369 |
-
*
|
370 |
-
* @param object|null $parent (optional) The parent node, `null` to return
|
371 |
-
* the current parent node.
|
372 |
-
* @return object|null The parent node
|
373 |
-
*/
|
374 |
-
function parent($parent = null)
|
375 |
-
{
|
376 |
-
// I am SURE that this doesn't work properly.
|
377 |
-
// It fails to unset the current node from it's current parents nodes or
|
378 |
-
// children list first.
|
379 |
-
if ($parent !== null) {
|
380 |
-
$this->parent = $parent;
|
381 |
-
$this->parent->nodes[] = $this;
|
382 |
-
$this->parent->children[] = $this;
|
383 |
-
}
|
384 |
-
|
385 |
-
return $this->parent;
|
386 |
-
}
|
387 |
-
|
388 |
-
/**
|
389 |
-
* @return bool True if the node has at least one child node
|
390 |
-
*/
|
391 |
-
function has_child()
|
392 |
-
{
|
393 |
-
return !empty($this->children);
|
394 |
-
}
|
395 |
-
|
396 |
-
/**
|
397 |
-
* Get child node at specified index
|
398 |
-
*
|
399 |
-
* @param int $idx The index of the child node to return, `-1` to return all
|
400 |
-
* child nodes.
|
401 |
-
* @return object|array|null The child node at the specified index, all child
|
402 |
-
* nodes or null if the index is invalid.
|
403 |
-
*/
|
404 |
-
function children($idx = -1)
|
405 |
-
{
|
406 |
-
if ($idx === -1) {
|
407 |
-
return $this->children;
|
408 |
-
}
|
409 |
-
|
410 |
-
if (isset($this->children[$idx])) {
|
411 |
-
return $this->children[$idx];
|
412 |
-
}
|
413 |
-
|
414 |
-
return null;
|
415 |
-
}
|
416 |
-
|
417 |
-
/**
|
418 |
-
* Get first child node
|
419 |
-
*
|
420 |
-
* @return object|null The first child node or null if the current node has
|
421 |
-
* no child nodes.
|
422 |
-
*
|
423 |
-
* @todo Use `empty()` instead of `count()` to improve performance on large
|
424 |
-
* arrays.
|
425 |
-
*/
|
426 |
-
function first_child()
|
427 |
-
{
|
428 |
-
if (count($this->children) > 0) {
|
429 |
-
return $this->children[0];
|
430 |
-
}
|
431 |
-
return null;
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Get last child node
|
436 |
-
*
|
437 |
-
* @return object|null The last child node or null if the current node has
|
438 |
-
* no child nodes.
|
439 |
-
*
|
440 |
-
* @todo Use `end()` to slightly improve performance on large arrays.
|
441 |
-
*/
|
442 |
-
function last_child()
|
443 |
-
{
|
444 |
-
if (($count = count($this->children)) > 0) {
|
445 |
-
return $this->children[$count - 1];
|
446 |
-
}
|
447 |
-
return null;
|
448 |
-
}
|
449 |
-
|
450 |
-
/**
|
451 |
-
* Get next sibling node
|
452 |
-
*
|
453 |
-
* @return object|null The sibling node or null if the current node has no
|
454 |
-
* sibling nodes.
|
455 |
-
*/
|
456 |
-
function next_sibling()
|
457 |
-
{
|
458 |
-
if ($this->parent === null) {
|
459 |
-
return null;
|
460 |
-
}
|
461 |
-
|
462 |
-
$idx = 0;
|
463 |
-
$count = count($this->parent->children);
|
464 |
-
|
465 |
-
while ($idx < $count && $this !== $this->parent->children[$idx]) {
|
466 |
-
++$idx;
|
467 |
-
}
|
468 |
-
|
469 |
-
if (++$idx >= $count) {
|
470 |
-
return null;
|
471 |
-
}
|
472 |
-
|
473 |
-
return $this->parent->children[$idx];
|
474 |
-
}
|
475 |
-
|
476 |
-
/**
|
477 |
-
* Get previous sibling node
|
478 |
-
*
|
479 |
-
* @return object|null The sibling node or null if the current node has no
|
480 |
-
* sibling nodes.
|
481 |
-
*/
|
482 |
-
function prev_sibling()
|
483 |
-
{
|
484 |
-
if ($this->parent === null) {
|
485 |
-
return null;
|
486 |
-
}
|
487 |
-
|
488 |
-
$idx = 0;
|
489 |
-
$count = count($this->parent->children);
|
490 |
-
|
491 |
-
while ($idx < $count && $this !== $this->parent->children[$idx]) {
|
492 |
-
++$idx;
|
493 |
-
}
|
494 |
-
|
495 |
-
if (--$idx < 0) {
|
496 |
-
return null;
|
497 |
-
}
|
498 |
-
|
499 |
-
return $this->parent->children[$idx];
|
500 |
-
}
|
501 |
-
|
502 |
-
/**
|
503 |
-
* Traverse ancestors to the first matching tag.
|
504 |
-
*
|
505 |
-
* @param string $tag Tag to find
|
506 |
-
* @return object|null First matching node in the DOM tree or null if no
|
507 |
-
* match was found.
|
508 |
-
*
|
509 |
-
* @todo Null is returned implicitly by calling ->parent on the root node.
|
510 |
-
* This behaviour could change at any time, rendering this function invalid.
|
511 |
-
*/
|
512 |
-
function find_ancestor_tag($tag)
|
513 |
-
{
|
514 |
-
global $debug_object;
|
515 |
-
if (is_object($debug_object)) {
|
516 |
-
$debug_object->debug_log_entry(1);
|
517 |
-
}
|
518 |
-
|
519 |
-
// Start by including ourselves in the comparison.
|
520 |
-
$returnDom = $this;
|
521 |
-
|
522 |
-
while (!is_null($returnDom)) {
|
523 |
-
if (is_object($debug_object)) {
|
524 |
-
$debug_object->debug_log(2, 'Current tag is: ' . $returnDom->tag);
|
525 |
-
}
|
526 |
-
|
527 |
-
if ($returnDom->tag == $tag) {
|
528 |
-
break;
|
529 |
-
}
|
530 |
-
|
531 |
-
$returnDom = $returnDom->parent;
|
532 |
-
}
|
533 |
-
|
534 |
-
return $returnDom;
|
535 |
-
}
|
536 |
-
|
537 |
-
/**
|
538 |
-
* Get node's inner text (everything inside the opening and closing tags)
|
539 |
-
*
|
540 |
-
* @return string
|
541 |
-
*/
|
542 |
-
function innertext()
|
543 |
-
{
|
544 |
-
if (isset($this->_[HDOM_INFO_INNER])) {
|
545 |
-
return $this->_[HDOM_INFO_INNER];
|
546 |
-
}
|
547 |
-
|
548 |
-
if (isset($this->_[HDOM_INFO_TEXT])) {
|
549 |
-
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
550 |
-
}
|
551 |
-
|
552 |
-
$ret = '';
|
553 |
-
|
554 |
-
foreach ($this->nodes as $n) {
|
555 |
-
$ret .= $n->outertext();
|
556 |
-
}
|
557 |
-
|
558 |
-
return $ret;
|
559 |
-
}
|
560 |
-
|
561 |
-
/**
|
562 |
-
* Get node's outer text (everything including the opening and closing tags)
|
563 |
-
*
|
564 |
-
* @return string
|
565 |
-
*/
|
566 |
-
function outertext()
|
567 |
-
{
|
568 |
-
global $debug_object;
|
569 |
-
|
570 |
-
if (is_object($debug_object)) {
|
571 |
-
$text = '';
|
572 |
-
|
573 |
-
if ($this->tag === 'text') {
|
574 |
-
if (!empty($this->text)) {
|
575 |
-
$text = ' with text: ' . $this->text;
|
576 |
-
}
|
577 |
-
}
|
578 |
-
|
579 |
-
$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
|
580 |
-
}
|
581 |
-
|
582 |
-
if ($this->tag === 'root') {
|
583 |
-
return $this->innertext();
|
584 |
-
}
|
585 |
-
|
586 |
-
// trigger callback
|
587 |
-
if ($this->dom && $this->dom->callback !== null) {
|
588 |
-
call_user_func_array($this->dom->callback, array($this));
|
589 |
-
}
|
590 |
-
|
591 |
-
if (isset($this->_[HDOM_INFO_OUTER])) {
|
592 |
-
return $this->_[HDOM_INFO_OUTER];
|
593 |
-
}
|
594 |
-
|
595 |
-
if (isset($this->_[HDOM_INFO_TEXT])) {
|
596 |
-
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
597 |
-
}
|
598 |
-
|
599 |
-
// render begin tag
|
600 |
-
if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
|
601 |
-
$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
|
602 |
-
} else {
|
603 |
-
$ret = '';
|
604 |
-
}
|
605 |
-
|
606 |
-
// render inner text
|
607 |
-
if (isset($this->_[HDOM_INFO_INNER])) {
|
608 |
-
// If it's a br tag... don't return the HDOM_INNER_INFO that we
|
609 |
-
// may or may not have added.
|
610 |
-
if ($this->tag !== 'br') {
|
611 |
-
$ret .= $this->_[HDOM_INFO_INNER];
|
612 |
-
}
|
613 |
-
} else {
|
614 |
-
if ($this->nodes) {
|
615 |
-
foreach ($this->nodes as $n) {
|
616 |
-
$ret .= $this->convert_text($n->outertext());
|
617 |
-
}
|
618 |
-
}
|
619 |
-
}
|
620 |
-
|
621 |
-
// render end tag
|
622 |
-
if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
|
623 |
-
$ret .= '</' . $this->tag . '>';
|
624 |
-
}
|
625 |
-
|
626 |
-
return $ret;
|
627 |
-
}
|
628 |
-
|
629 |
-
/**
|
630 |
-
* Get node's plain text (everything excluding all tags)
|
631 |
-
*
|
632 |
-
* @return string
|
633 |
-
*/
|
634 |
-
function text()
|
635 |
-
{
|
636 |
-
if (isset($this->_[HDOM_INFO_INNER])) {
|
637 |
-
return $this->_[HDOM_INFO_INNER];
|
638 |
-
}
|
639 |
-
|
640 |
-
switch ($this->nodetype) {
|
641 |
-
case HDOM_TYPE_TEXT:
|
642 |
-
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
643 |
-
case HDOM_TYPE_COMMENT:
|
644 |
-
return '';
|
645 |
-
case HDOM_TYPE_UNKNOWN:
|
646 |
-
return '';
|
647 |
-
}
|
648 |
-
|
649 |
-
if (strcasecmp($this->tag, 'script') === 0) {
|
650 |
-
return '';
|
651 |
-
}
|
652 |
-
if (strcasecmp($this->tag, 'style') === 0) {
|
653 |
-
return '';
|
654 |
-
}
|
655 |
-
|
656 |
-
$ret = '';
|
657 |
-
|
658 |
-
// In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed
|
659 |
-
// for some span tags, and some p tags) $this->nodes is set to NULL.
|
660 |
-
// NOTE: This indicates that there is a problem where it's set to NULL
|
661 |
-
// without a clear happening.
|
662 |
-
// WHY is this happening?
|
663 |
-
if (!is_null($this->nodes)) {
|
664 |
-
foreach ($this->nodes as $n) {
|
665 |
-
// Start paragraph after a blank line
|
666 |
-
if ($n->tag === 'p') {
|
667 |
-
$ret .= "\n\n";
|
668 |
-
}
|
669 |
-
|
670 |
-
$ret .= $this->convert_text($n->text());
|
671 |
-
|
672 |
-
// If this node is a span... add a space at the end of it so
|
673 |
-
// multiple spans don't run into each other. This is plaintext
|
674 |
-
// after all.
|
675 |
-
if ($n->tag === 'span') {
|
676 |
-
$ret .= $this->dom->default_span_text;
|
677 |
-
}
|
678 |
-
}
|
679 |
-
}
|
680 |
-
return trim($ret);
|
681 |
-
}
|
682 |
-
|
683 |
-
/**
|
684 |
-
* Get node's xml text (inner text as a CDATA section)
|
685 |
-
*
|
686 |
-
* @return string
|
687 |
-
*/
|
688 |
-
function xmltext()
|
689 |
-
{
|
690 |
-
$ret = $this->innertext();
|
691 |
-
$ret = str_ireplace('<![CDATA[', '', $ret);
|
692 |
-
$ret = str_replace(']]>', '', $ret);
|
693 |
-
return $ret;
|
694 |
-
}
|
695 |
-
|
696 |
-
// build node's text with tag
|
697 |
-
function makeup()
|
698 |
-
{
|
699 |
-
// text, comment, unknown
|
700 |
-
if (isset($this->_[HDOM_INFO_TEXT])) {
|
701 |
-
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
702 |
-
}
|
703 |
-
|
704 |
-
$ret = '<' . $this->tag;
|
705 |
-
$i = -1;
|
706 |
-
|
707 |
-
foreach ($this->attr as $key => $val) {
|
708 |
-
++$i;
|
709 |
-
|
710 |
-
// skip removed attribute
|
711 |
-
if ($val === null || $val === false) {
|
712 |
-
continue;
|
713 |
-
}
|
714 |
-
|
715 |
-
$ret .= $this->_[HDOM_INFO_SPACE][$i][0];
|
716 |
-
|
717 |
-
//no value attr: nowrap, checked selected...
|
718 |
-
if ($val === true) {
|
719 |
-
$ret .= $key;
|
720 |
-
} else {
|
721 |
-
switch ($this->_[HDOM_INFO_QUOTE][$i]) {
|
722 |
-
case HDOM_QUOTE_DOUBLE:
|
723 |
-
$quote = '"';
|
724 |
-
break;
|
725 |
-
case HDOM_QUOTE_SINGLE:
|
726 |
-
$quote = '\'';
|
727 |
-
break;
|
728 |
-
default:
|
729 |
-
$quote = '';
|
730 |
-
}
|
731 |
-
|
732 |
-
$ret .= $key
|
733 |
-
. $this->_[HDOM_INFO_SPACE][$i][1]
|
734 |
-
. '='
|
735 |
-
. $this->_[HDOM_INFO_SPACE][$i][2]
|
736 |
-
. $quote
|
737 |
-
. $val
|
738 |
-
. $quote;
|
739 |
-
}
|
740 |
-
}
|
741 |
-
|
742 |
-
$ret = $this->dom->restore_noise($ret);
|
743 |
-
return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
|
744 |
-
}
|
745 |
-
|
746 |
-
/**
|
747 |
-
* Find elements by CSS selector
|
748 |
-
*
|
749 |
-
* @param string $selector The CSS selector
|
750 |
-
* @param int|null $idx Index of element to return form the list of matching
|
751 |
-
* elements (default: `null` = disabled).
|
752 |
-
* @param bool $lowercase Matches tag names case insensitive (lowercase) if
|
753 |
-
* enabled (default: `false`)
|
754 |
-
* @return array|object|null A list of elements matching the specified CSS
|
755 |
-
* selector or a single element if $idx is specified or null if no element
|
756 |
-
* was found.
|
757 |
-
*/
|
758 |
-
function find($selector, $idx = null, $lowercase = false)
|
759 |
-
{
|
760 |
-
$selectors = $this->parse_selector($selector);
|
761 |
-
if (($count = count($selectors)) === 0) {
|
762 |
-
return array();
|
763 |
-
}
|
764 |
-
$found_keys = array();
|
765 |
-
|
766 |
-
// find each selector
|
767 |
-
for ($c = 0; $c < $count; ++$c) {
|
768 |
-
// The change on the below line was documented on the sourceforge
|
769 |
-
// code tracker id 2788009
|
770 |
-
// used to be: if (($levle=count($selectors[0]))===0) return array();
|
771 |
-
if (($levle = count($selectors[$c])) === 0) {
|
772 |
-
return array();
|
773 |
-
}
|
774 |
-
if (!isset($this->_[HDOM_INFO_BEGIN])) {
|
775 |
-
return array();
|
776 |
-
}
|
777 |
-
|
778 |
-
$head = array($this->_[HDOM_INFO_BEGIN] => 1);
|
779 |
-
$cmd = ' '; // Combinator
|
780 |
-
|
781 |
-
// handle descendant selectors, no recursive!
|
782 |
-
for ($l = 0; $l < $levle; ++$l) {
|
783 |
-
$ret = array();
|
784 |
-
|
785 |
-
foreach ($head as $k => $v) {
|
786 |
-
$n = ($k === -1) ? $this->dom->root : $this->dom->nodes[$k];
|
787 |
-
//PaperG - Pass this optional parameter on to the seek function.
|
788 |
-
$n->seek($selectors[$c][$l], $ret, $cmd, $lowercase);
|
789 |
-
}
|
790 |
-
|
791 |
-
$head = $ret;
|
792 |
-
$cmd = $selectors[$c][$l][4]; // Next Combinator
|
793 |
-
}
|
794 |
-
|
795 |
-
foreach ($head as $k => $v) {
|
796 |
-
if (!isset($found_keys[$k])) {
|
797 |
-
$found_keys[$k] = 1;
|
798 |
-
}
|
799 |
-
}
|
800 |
-
}
|
801 |
-
|
802 |
-
// sort keys
|
803 |
-
ksort($found_keys);
|
804 |
-
|
805 |
-
$found = array();
|
806 |
-
foreach ($found_keys as $k => $v) {
|
807 |
-
$found[] = $this->dom->nodes[$k];
|
808 |
-
}
|
809 |
-
|
810 |
-
// return nth-element or array
|
811 |
-
if (is_null($idx)) {
|
812 |
-
return $found;
|
813 |
-
} elseif ($idx < 0) {
|
814 |
-
$idx = count($found) + $idx;
|
815 |
-
}
|
816 |
-
return (isset($found[$idx])) ? $found[$idx] : null;
|
817 |
-
}
|
818 |
-
|
819 |
-
/**
|
820 |
-
* Seek DOM elements by selector
|
821 |
-
*
|
822 |
-
* **Note**
|
823 |
-
* The selector element must be compatible to a selector from
|
824 |
-
* {@see simple_html_dom_node::parse_selector()}
|
825 |
-
*
|
826 |
-
* @param array $selector A selector element
|
827 |
-
* @param array $ret An array of matches
|
828 |
-
* @param bool $lowercase Matches tag names case insensitive (lowercase) if
|
829 |
-
* enabled (default: `false`)
|
830 |
-
* @return void
|
831 |
-
*/
|
832 |
-
protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
|
833 |
-
{
|
834 |
-
global $debug_object;
|
835 |
-
if (is_object($debug_object)) {
|
836 |
-
$debug_object->debug_log_entry(1);
|
837 |
-
}
|
838 |
-
|
839 |
-
list($tag, $id, $class, $attributes, $cmb) = $selector;
|
840 |
-
$nodes = array();
|
841 |
-
|
842 |
-
if ($parent_cmd === ' ') { // Descendant Combinator
|
843 |
-
// Find parent closing tag if the current element doesn't have a closing
|
844 |
-
// tag (i.e. void element)
|
845 |
-
$end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0;
|
846 |
-
if ($end == 0) {
|
847 |
-
$parent = $this->parent;
|
848 |
-
while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) {
|
849 |
-
$end -= 1;
|
850 |
-
$parent = $parent->parent;
|
851 |
-
}
|
852 |
-
$end += $parent->_[HDOM_INFO_END];
|
853 |
-
}
|
854 |
-
|
855 |
-
// Get list of target nodes
|
856 |
-
$nodes_start = $this->_[HDOM_INFO_BEGIN] + 1;
|
857 |
-
$nodes_count = $end - $nodes_start;
|
858 |
-
$nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true);
|
859 |
-
} elseif ($parent_cmd === '>') { // Child Combinator
|
860 |
-
$nodes = $this->children;
|
861 |
-
} elseif ($parent_cmd === '+'
|
862 |
-
&& $this->parent
|
863 |
-
&& in_array($this, $this->parent->children)) { // Next-Sibling Combinator
|
864 |
-
$index = array_search($this, $this->parent->children, true) + 1;
|
865 |
-
$nodes[] = $this->parent->children[$index];
|
866 |
-
} elseif ($parent_cmd === '~'
|
867 |
-
&& $this->parent
|
868 |
-
&& in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
|
869 |
-
$index = array_search($this, $this->parent->children, true);
|
870 |
-
$nodes = array_slice($this->parent->children, $index);
|
871 |
-
}
|
872 |
-
|
873 |
-
// Go throgh each element starting at this element until the end tag
|
874 |
-
// Note: If this element is a void tag, any previous void element is
|
875 |
-
// skipped.
|
876 |
-
foreach ($nodes as $node) {
|
877 |
-
$pass = true;
|
878 |
-
|
879 |
-
// Skip root nodes
|
880 |
-
if (!$node->parent) {
|
881 |
-
$pass = false;
|
882 |
-
}
|
883 |
-
|
884 |
-
// Skip if node isn't a child node (i.e. text nodes)
|
885 |
-
if ($pass && !in_array($node, $node->parent->children, true)) {
|
886 |
-
$pass = false;
|
887 |
-
}
|
888 |
-
|
889 |
-
// Skip if tag doesn't match
|
890 |
-
if ($pass && $tag !== '' && $tag !== $node->tag && $tag !== '*') {
|
891 |
-
$pass = false;
|
892 |
-
}
|
893 |
-
|
894 |
-
// Skip if ID doesn't exist
|
895 |
-
if ($pass && $id !== '' && !isset($node->attr['id'])) {
|
896 |
-
$pass = false;
|
897 |
-
}
|
898 |
-
|
899 |
-
// Check if ID matches
|
900 |
-
if ($pass && $id !== '' && isset($node->attr['id'])) {
|
901 |
-
// Note: Only consider the first ID (as browsers do)
|
902 |
-
$node_id = explode(' ', trim($node->attr['id']))[0];
|
903 |
-
|
904 |
-
if ($id !== $node_id) {
|
905 |
-
$pass = false;
|
906 |
-
}
|
907 |
-
}
|
908 |
-
|
909 |
-
// Check if all class(es) exist
|
910 |
-
if ($pass && $class !== '' && is_array($class) && !empty($class)) {
|
911 |
-
if (isset($node->attr['class'])) {
|
912 |
-
$node_classes = explode(' ', $node->attr['class']);
|
913 |
-
|
914 |
-
if ($lowercase) {
|
915 |
-
$node_classes = array_map('strtolower', $node_classes);
|
916 |
-
}
|
917 |
-
|
918 |
-
foreach ($class as $c) {
|
919 |
-
if (!in_array($c, $node_classes)) {
|
920 |
-
$pass = false;
|
921 |
-
break;
|
922 |
-
}
|
923 |
-
}
|
924 |
-
} else {
|
925 |
-
$pass = false;
|
926 |
-
}
|
927 |
-
}
|
928 |
-
|
929 |
-
// Check attributes
|
930 |
-
if ($pass
|
931 |
-
&& $attributes !== ''
|
932 |
-
&& is_array($attributes)
|
933 |
-
&& !empty($attributes)) {
|
934 |
-
foreach ($attributes as $a) {
|
935 |
-
list (
|
936 |
-
$att_name,
|
937 |
-
$att_expr,
|
938 |
-
$att_val,
|
939 |
-
$att_inv,
|
940 |
-
$att_case_sensitivity
|
941 |
-
) = $a;
|
942 |
-
|
943 |
-
// Handle indexing attributes (i.e. "[2]")
|
944 |
-
/**
|
945 |
-
* Note: This is not supported by the CSS Standard but adds
|
946 |
-
* the ability to select items compatible to XPath (i.e.
|
947 |
-
* the 3rd element within it's parent).
|
948 |
-
*
|
949 |
-
* Note: This doesn't conflict with the CSS Standard which
|
950 |
-
* doesn't work on numeric attributes anyway.
|
951 |
-
*/
|
952 |
-
if (is_numeric($att_name)
|
953 |
-
&& $att_expr === ''
|
954 |
-
&& $att_val === '') {
|
955 |
-
$count = 0;
|
956 |
-
|
957 |
-
// Find index of current element in parent
|
958 |
-
foreach ($node->parent->children as $c) {
|
959 |
-
if ($c->tag === $node->tag) {
|
960 |
-
++$count;
|
961 |
-
}
|
962 |
-
if ($c === $node) {
|
963 |
-
break;
|
964 |
-
}
|
965 |
-
}
|
966 |
-
|
967 |
-
// If this is the correct node, continue with next
|
968 |
-
// attribute
|
969 |
-
if ($count === (int)$att_name) {
|
970 |
-
continue;
|
971 |
-
}
|
972 |
-
}
|
973 |
-
|
974 |
-
// Check attribute availability
|
975 |
-
if ($att_inv) { // Attribute should NOT be set
|
976 |
-
if (isset($node->attr[$att_name])) {
|
977 |
-
$pass = false;
|
978 |
-
break;
|
979 |
-
}
|
980 |
-
} else { // Attribute should be set
|
981 |
-
// todo: "plaintext" is not a valid CSS selector!
|
982 |
-
if ($att_name !== 'plaintext'
|
983 |
-
&& !isset($node->attr[$att_name])) {
|
984 |
-
$pass = false;
|
985 |
-
break;
|
986 |
-
}
|
987 |
-
}
|
988 |
-
|
989 |
-
// Continue with next attribute if expression isn't defined
|
990 |
-
if ($att_expr === '') {
|
991 |
-
continue;
|
992 |
-
}
|
993 |
-
|
994 |
-
// If they have told us that this is a "plaintext"
|
995 |
-
// search then we want the plaintext of the node - right?
|
996 |
-
// todo "plaintext" is not a valid CSS selector!
|
997 |
-
if ($att_name === 'plaintext') {
|
998 |
-
$nodeKeyValue = $node->text();
|
999 |
-
} else {
|
1000 |
-
$nodeKeyValue = $node->attr[$att_name];
|
1001 |
-
}
|
1002 |
-
|
1003 |
-
if (is_object($debug_object)) {
|
1004 |
-
$debug_object->debug_log(
|
1005 |
-
2,
|
1006 |
-
'testing node: '
|
1007 |
-
. $node->tag
|
1008 |
-
. ' for attribute: '
|
1009 |
-
. $att_name
|
1010 |
-
. $att_expr
|
1011 |
-
. $att_val
|
1012 |
-
. ' where nodes value is: '
|
1013 |
-
. $nodeKeyValue
|
1014 |
-
);
|
1015 |
-
}
|
1016 |
-
|
1017 |
-
// If lowercase is set, do a case insensitive test of
|
1018 |
-
// the value of the selector.
|
1019 |
-
if ($lowercase) {
|
1020 |
-
$check = $this->match(
|
1021 |
-
$att_expr,
|
1022 |
-
strtolower($att_val),
|
1023 |
-
strtolower($nodeKeyValue),
|
1024 |
-
$att_case_sensitivity
|
1025 |
-
);
|
1026 |
-
} else {
|
1027 |
-
$check = $this->match(
|
1028 |
-
$att_expr,
|
1029 |
-
$att_val,
|
1030 |
-
$nodeKeyValue,
|
1031 |
-
$att_case_sensitivity
|
1032 |
-
);
|
1033 |
-
}
|
1034 |
-
|
1035 |
-
if (is_object($debug_object)) {
|
1036 |
-
$debug_object->debug_log(
|
1037 |
-
2,
|
1038 |
-
'after match: '
|
1039 |
-
. ($check ? 'true' : 'false')
|
1040 |
-
);
|
1041 |
-
}
|
1042 |
-
|
1043 |
-
if (!$check) {
|
1044 |
-
$pass = false;
|
1045 |
-
break;
|
1046 |
-
}
|
1047 |
-
}
|
1048 |
-
}
|
1049 |
-
|
1050 |
-
// Found a match. Add to list and clear node
|
1051 |
-
if ($pass) {
|
1052 |
-
$ret[$node->_[HDOM_INFO_BEGIN]] = 1;
|
1053 |
-
}
|
1054 |
-
unset($node);
|
1055 |
-
}
|
1056 |
-
// It's passed by reference so this is actually what this function returns.
|
1057 |
-
if (is_object($debug_object)) {
|
1058 |
-
$debug_object->debug_log(1, 'EXIT - ret: ', $ret);
|
1059 |
-
}
|
1060 |
-
}
|
1061 |
-
|
1062 |
-
/**
|
1063 |
-
* Match value and pattern for a given CSS expression
|
1064 |
-
*
|
1065 |
-
* **Supported Expressions**
|
1066 |
-
*
|
1067 |
-
* | Expression | Description
|
1068 |
-
* | ---------- | -----------
|
1069 |
-
* | `=` | $value and $pattern must be equal
|
1070 |
-
* | `!=` | $value and $pattern must not be equal
|
1071 |
-
* | `^=` | $value must start with $pattern
|
1072 |
-
* | `$=` | $value must end with $pattern
|
1073 |
-
* | `*=` | $value must contain $pattern
|
1074 |
-
*
|
1075 |
-
* @param string $exp The expression.
|
1076 |
-
* @param string $pattern The pattern
|
1077 |
-
* @param string $value The value
|
1078 |
-
* @value bool True if $value matches $pattern
|
1079 |
-
*/
|
1080 |
-
protected function match($exp, $pattern, $value, $case_sensitivity)
|
1081 |
-
{
|
1082 |
-
global $debug_object;
|
1083 |
-
if (is_object($debug_object)) {
|
1084 |
-
$debug_object->debug_log_entry(1);
|
1085 |
-
}
|
1086 |
-
|
1087 |
-
if ($case_sensitivity === 'i') {
|
1088 |
-
$pattern = strtolower($pattern);
|
1089 |
-
$value = strtolower($value);
|
1090 |
-
}
|
1091 |
-
|
1092 |
-
switch ($exp) {
|
1093 |
-
case '=':
|
1094 |
-
return ($value === $pattern);
|
1095 |
-
case '!=':
|
1096 |
-
return ($value !== $pattern);
|
1097 |
-
case '^=':
|
1098 |
-
return preg_match('/^' . preg_quote($pattern, '/') . '/', $value);
|
1099 |
-
case '$=':
|
1100 |
-
return preg_match('/' . preg_quote($pattern, '/') . '$/', $value);
|
1101 |
-
case '*=':
|
1102 |
-
return preg_match('/' . preg_quote($pattern, '/') . '/', $value);
|
1103 |
-
case '|=':
|
1104 |
-
/**
|
1105 |
-
* [att|=val]
|
1106 |
-
*
|
1107 |
-
* Represents an element with the att attribute, its value
|
1108 |
-
* either being exactly "val" or beginning with "val"
|
1109 |
-
* immediately followed by "-" (U+002D).
|
1110 |
-
*/
|
1111 |
-
return strpos($value, $pattern) === 0;
|
1112 |
-
case '~=':
|
1113 |
-
/**
|
1114 |
-
* [att~=val]
|
1115 |
-
*
|
1116 |
-
* Represents an element with the att attribute whose value is a
|
1117 |
-
* whitespace-separated list of words, one of which is exactly
|
1118 |
-
* "val". If "val" contains whitespace, it will never represent
|
1119 |
-
* anything (since the words are separated by spaces). Also if
|
1120 |
-
* "val" is the empty string, it will never represent anything.
|
1121 |
-
*/
|
1122 |
-
return in_array($pattern, explode(' ', trim($value)), true);
|
1123 |
-
}
|
1124 |
-
return false;
|
1125 |
-
}
|
1126 |
-
|
1127 |
-
/**
|
1128 |
-
* Parse CSS selector
|
1129 |
-
*
|
1130 |
-
* @param string $selector_string CSS selector string
|
1131 |
-
* @return array List of CSS selectors. The format depends on the type of
|
1132 |
-
* selector:
|
1133 |
-
*
|
1134 |
-
* ```php
|
1135 |
-
*
|
1136 |
-
* array( // list of selectors (each separated by a comma), i.e. 'img, p, div'
|
1137 |
-
* array( // list of combinator selectors, i.e. 'img > p > div'
|
1138 |
-
* array( // selector element
|
1139 |
-
* [0], // (string) The element tag
|
1140 |
-
* [1], // (string) The element id
|
1141 |
-
* [2], // (array<string>) The element classes
|
1142 |
-
* [3], // (array<array<string>>) The list of attributes, each
|
1143 |
-
* // with four elements: name, expression, value, inverted
|
1144 |
-
* [4] // (string) The selector combinator (' ' | '>' | '+' | '~')
|
1145 |
-
* )
|
1146 |
-
* )
|
1147 |
-
* )
|
1148 |
-
* ```
|
1149 |
-
*
|
1150 |
-
* @link https://www.w3.org/TR/selectors/#compound Compound selector
|
1151 |
-
*/
|
1152 |
-
protected function parse_selector($selector_string)
|
1153 |
-
{
|
1154 |
-
global $debug_object;
|
1155 |
-
if (is_object($debug_object)) {
|
1156 |
-
$debug_object->debug_log_entry(1);
|
1157 |
-
}
|
1158 |
-
|
1159 |
-
/**
|
1160 |
-
* Pattern of CSS selectors, modified from mootools (https://mootools.net/)
|
1161 |
-
*
|
1162 |
-
* Paperg: Add the colon to the attribute, so that it properly finds
|
1163 |
-
* <tag attr:ibute="something" > like google does.
|
1164 |
-
*
|
1165 |
-
* Note: if you try to look at this attribute, you MUST use getAttribute
|
1166 |
-
* since $dom->x:y will fail the php syntax check.
|
1167 |
-
*
|
1168 |
-
* Notice the \[ starting the attribute? and the @? following? This
|
1169 |
-
* implies that an attribute can begin with an @ sign that is not
|
1170 |
-
* captured. This implies that an html attribute specifier may start
|
1171 |
-
* with an @ sign that is NOT captured by the expression. Farther study
|
1172 |
-
* is required to determine of this should be documented or removed.
|
1173 |
-
*
|
1174 |
-
* Matches selectors in this order:
|
1175 |
-
*
|
1176 |
-
* [0] - full match
|
1177 |
-
*
|
1178 |
-
* [1] - tag name
|
1179 |
-
* ([\w:\*-]*)
|
1180 |
-
* Matches the tag name consisting of zero or more words, colons,
|
1181 |
-
* asterisks and hyphens.
|
1182 |
-
*
|
1183 |
-
* [2] - id name
|
1184 |
-
* (?:\#([\w-]+))
|
1185 |
-
* Optionally matches a id name, consisting of an "#" followed by
|
1186 |
-
* the id name (one or more words and hyphens).
|
1187 |
-
*
|
1188 |
-
* [3] - class names (including dots)
|
1189 |
-
* (?:\.([\w\.-]+))?
|
1190 |
-
* Optionally matches a list of classs, consisting of an "."
|
1191 |
-
* followed by the class name (one or more words and hyphens)
|
1192 |
-
* where multiple classes can be chained (i.e. ".foo.bar.baz")
|
1193 |
-
*
|
1194 |
-
* [4] - attributes
|
1195 |
-
* ((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?
|
1196 |
-
* Optionally matches the attributes list
|
1197 |
-
*
|
1198 |
-
* [5] - separator
|
1199 |
-
* ([\/, >+~]+)
|
1200 |
-
* Matches the selector list separator
|
1201 |
-
*/
|
1202 |
-
// phpcs:ignore Generic.Files.LineLength
|
1203 |
-
$pattern = "/([\w:\*-]*)(?:\#([\w-]+))?(?:|\.([\w\.-]+))?((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?([\/, >+~]+)/is";
|
1204 |
-
|
1205 |
-
preg_match_all(
|
1206 |
-
$pattern,
|
1207 |
-
trim($selector_string) . ' ', // Add final ' ' as pseudo separator
|
1208 |
-
$matches,
|
1209 |
-
PREG_SET_ORDER
|
1210 |
-
);
|
1211 |
-
|
1212 |
-
if (is_object($debug_object)) {
|
1213 |
-
$debug_object->debug_log(2, 'Matches Array: ', $matches);
|
1214 |
-
}
|
1215 |
-
|
1216 |
-
$selectors = array();
|
1217 |
-
$result = array();
|
1218 |
-
|
1219 |
-
foreach ($matches as $m) {
|
1220 |
-
$m[0] = trim($m[0]);
|
1221 |
-
|
1222 |
-
// Skip NoOps
|
1223 |
-
if ($m[0] === '' || $m[0] === '/' || $m[0] === '//') {
|
1224 |
-
continue;
|
1225 |
-
}
|
1226 |
-
|
1227 |
-
// Convert to lowercase
|
1228 |
-
if ($this->dom->lowercase) {
|
1229 |
-
$m[1] = strtolower($m[1]);
|
1230 |
-
}
|
1231 |
-
|
1232 |
-
// Extract classes
|
1233 |
-
if ($m[3] !== '') {
|
1234 |
-
$m[3] = explode('.', $m[3]);
|
1235 |
-
}
|
1236 |
-
|
1237 |
-
/* Extract attributes (pattern based on the pattern above!)
|
1238 |
-
|
1239 |
-
* [0] - full match
|
1240 |
-
* [1] - attribute name
|
1241 |
-
* [2] - attribute expression
|
1242 |
-
* [3] - attribute value
|
1243 |
-
* [4] - case sensitivity
|
1244 |
-
*
|
1245 |
-
* Note: Attributes can be negated with a "!" prefix to their name
|
1246 |
-
*/
|
1247 |
-
if ($m[4] !== '') {
|
1248 |
-
preg_match_all(
|
1249 |
-
"/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s*?([iIsS])?)?\]/is",
|
1250 |
-
trim($m[4]),
|
1251 |
-
$attributes,
|
1252 |
-
PREG_SET_ORDER
|
1253 |
-
);
|
1254 |
-
|
1255 |
-
// Replace element by array
|
1256 |
-
$m[4] = array();
|
1257 |
-
|
1258 |
-
foreach ($attributes as $att) {
|
1259 |
-
// Skip empty matches
|
1260 |
-
if (trim($att[0]) === '') {
|
1261 |
-
continue;
|
1262 |
-
}
|
1263 |
-
|
1264 |
-
$inverted = (isset($att[1][0]) && $att[1][0] === '!');
|
1265 |
-
$m[4][] = array(
|
1266 |
-
$inverted ? substr($att[1], 1) : $att[1], // Name
|
1267 |
-
(isset($att[2])) ? $att[2] : '', // Expression
|
1268 |
-
(isset($att[3])) ? $att[3] : '', // Value
|
1269 |
-
$inverted, // Inverted Flag
|
1270 |
-
(isset($att[4])) ? strtolower($att[4]) : '', // Case-Sensitivity
|
1271 |
-
);
|
1272 |
-
}
|
1273 |
-
}
|
1274 |
-
|
1275 |
-
// Sanitize Separator
|
1276 |
-
if ($m[5] !== '' && trim($m[5]) === '') { // Descendant Separator
|
1277 |
-
$m[5] = ' ';
|
1278 |
-
} else { // Other Separator
|
1279 |
-
$m[5] = trim($m[5]);
|
1280 |
-
}
|
1281 |
-
|
1282 |
-
// Clear Separator if it's a Selector List
|
1283 |
-
if ($is_list = ($m[5] === ',')) {
|
1284 |
-
$m[5] = '';
|
1285 |
-
}
|
1286 |
-
|
1287 |
-
// Remove full match before adding to results
|
1288 |
-
array_shift($m);
|
1289 |
-
$result[] = $m;
|
1290 |
-
|
1291 |
-
if ($is_list) { // Selector List
|
1292 |
-
$selectors[] = $result;
|
1293 |
-
$result = array();
|
1294 |
-
}
|
1295 |
-
}
|
1296 |
-
|
1297 |
-
if (count($result) > 0) {
|
1298 |
-
$selectors[] = $result;
|
1299 |
-
}
|
1300 |
-
return $selectors;
|
1301 |
-
}
|
1302 |
-
|
1303 |
-
function __get($name)
|
1304 |
-
{
|
1305 |
-
if (isset($this->attr[$name])) {
|
1306 |
-
return $this->convert_text($this->attr[$name]);
|
1307 |
-
}
|
1308 |
-
switch ($name) {
|
1309 |
-
case 'outertext':
|
1310 |
-
return $this->outertext();
|
1311 |
-
case 'innertext':
|
1312 |
-
return $this->innertext();
|
1313 |
-
case 'plaintext':
|
1314 |
-
return $this->text();
|
1315 |
-
case 'xmltext':
|
1316 |
-
return $this->xmltext();
|
1317 |
-
default:
|
1318 |
-
return array_key_exists($name, $this->attr);
|
1319 |
-
}
|
1320 |
-
}
|
1321 |
-
|
1322 |
-
function __set($name, $value)
|
1323 |
-
{
|
1324 |
-
global $debug_object;
|
1325 |
-
if (is_object($debug_object)) {
|
1326 |
-
$debug_object->debug_log_entry(1);
|
1327 |
-
}
|
1328 |
-
|
1329 |
-
switch ($name) {
|
1330 |
-
case 'outertext':
|
1331 |
-
return $this->_[HDOM_INFO_OUTER] = $value;
|
1332 |
-
case 'innertext':
|
1333 |
-
if (isset($this->_[HDOM_INFO_TEXT])) {
|
1334 |
-
return $this->_[HDOM_INFO_TEXT] = $value;
|
1335 |
-
}
|
1336 |
-
return $this->_[HDOM_INFO_INNER] = $value;
|
1337 |
-
}
|
1338 |
-
|
1339 |
-
if (!isset($this->attr[$name])) {
|
1340 |
-
$this->_[HDOM_INFO_SPACE][] = array(' ', '', '');
|
1341 |
-
$this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
|
1342 |
-
}
|
1343 |
-
|
1344 |
-
$this->attr[$name] = $value;
|
1345 |
-
}
|
1346 |
-
|
1347 |
-
function __isset($name)
|
1348 |
-
{
|
1349 |
-
switch ($name) {
|
1350 |
-
case 'outertext':
|
1351 |
-
return true;
|
1352 |
-
case 'innertext':
|
1353 |
-
return true;
|
1354 |
-
case 'plaintext':
|
1355 |
-
return true;
|
1356 |
-
}
|
1357 |
-
//no value attr: nowrap, checked selected...
|
1358 |
-
return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
|
1359 |
-
}
|
1360 |
-
|
1361 |
-
function __unset($name)
|
1362 |
-
{
|
1363 |
-
if (isset($this->attr[$name])) {
|
1364 |
-
unset($this->attr[$name]);
|
1365 |
-
}
|
1366 |
-
}
|
1367 |
-
|
1368 |
-
// PaperG - Function to convert the text from one character set to another
|
1369 |
-
// if the two sets are not the same.
|
1370 |
-
function convert_text($text)
|
1371 |
-
{
|
1372 |
-
global $debug_object;
|
1373 |
-
if (is_object($debug_object)) {
|
1374 |
-
$debug_object->debug_log_entry(1);
|
1375 |
-
}
|
1376 |
-
|
1377 |
-
$converted_text = $text;
|
1378 |
-
|
1379 |
-
$sourceCharset = '';
|
1380 |
-
$targetCharset = '';
|
1381 |
-
|
1382 |
-
if ($this->dom) {
|
1383 |
-
$sourceCharset = strtoupper($this->dom->_charset);
|
1384 |
-
$targetCharset = strtoupper($this->dom->_target_charset);
|
1385 |
-
}
|
1386 |
-
|
1387 |
-
if (is_object($debug_object)) {
|
1388 |
-
$debug_object->debug_log(
|
1389 |
-
3,
|
1390 |
-
'source charset: '
|
1391 |
-
. $sourceCharset
|
1392 |
-
. ' target charaset: '
|
1393 |
-
. $targetCharset
|
1394 |
-
);
|
1395 |
-
}
|
1396 |
-
|
1397 |
-
if (!empty($sourceCharset)
|
1398 |
-
&& !empty($targetCharset)
|
1399 |
-
&& (strcasecmp($sourceCharset, $targetCharset) != 0)) {
|
1400 |
-
// Check if the reported encoding could have been incorrect and the text is actually already UTF-8
|
1401 |
-
if ((strcasecmp($targetCharset, 'UTF-8') == 0)
|
1402 |
-
&& ($this->is_utf8($text))) {
|
1403 |
-
$converted_text = $text;
|
1404 |
-
} else {
|
1405 |
-
$converted_text = iconv($sourceCharset, $targetCharset, $text);
|
1406 |
-
}
|
1407 |
-
}
|
1408 |
-
|
1409 |
-
// Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
|
1410 |
-
if ($targetCharset === 'UTF-8') {
|
1411 |
-
if (substr($converted_text, 0, 3) === "\xef\xbb\xbf") {
|
1412 |
-
$converted_text = substr($converted_text, 3);
|
1413 |
-
}
|
1414 |
-
|
1415 |
-
if (substr($converted_text, -3) === "\xef\xbb\xbf") {
|
1416 |
-
$converted_text = substr($converted_text, 0, -3);
|
1417 |
-
}
|
1418 |
-
}
|
1419 |
-
|
1420 |
-
return $converted_text;
|
1421 |
-
}
|
1422 |
-
|
1423 |
-
/**
|
1424 |
-
* Returns true if $string is valid UTF-8 and false otherwise.
|
1425 |
-
*
|
1426 |
-
* @param mixed $str String to be tested
|
1427 |
-
* @return boolean
|
1428 |
-
*/
|
1429 |
-
static function is_utf8($str)
|
1430 |
-
{
|
1431 |
-
$c = 0;
|
1432 |
-
$b = 0;
|
1433 |
-
$bits = 0;
|
1434 |
-
$len = strlen($str);
|
1435 |
-
for ($i = 0; $i < $len; $i++) {
|
1436 |
-
$c = ord($str[$i]);
|
1437 |
-
if ($c > 128) {
|
1438 |
-
if (($c >= 254)) {
|
1439 |
-
return false;
|
1440 |
-
} elseif ($c >= 252) {
|
1441 |
-
$bits = 6;
|
1442 |
-
} elseif ($c >= 248) {
|
1443 |
-
$bits = 5;
|
1444 |
-
} elseif ($c >= 240) {
|
1445 |
-
$bits = 4;
|
1446 |
-
} elseif ($c >= 224) {
|
1447 |
-
$bits = 3;
|
1448 |
-
} elseif ($c >= 192) {
|
1449 |
-
$bits = 2;
|
1450 |
-
} else {
|
1451 |
-
return false;
|
1452 |
-
}
|
1453 |
-
if (($i + $bits) > $len) {
|
1454 |
-
return false;
|
1455 |
-
}
|
1456 |
-
while ($bits > 1) {
|
1457 |
-
$i++;
|
1458 |
-
$b = ord($str[$i]);
|
1459 |
-
if ($b < 128 || $b > 191) {
|
1460 |
-
return false;
|
1461 |
-
}
|
1462 |
-
$bits--;
|
1463 |
-
}
|
1464 |
-
}
|
1465 |
-
}
|
1466 |
-
return true;
|
1467 |
-
}
|
1468 |
-
|
1469 |
-
/**
|
1470 |
-
* Function to try a few tricks to determine the displayed size of an img on
|
1471 |
-
* the page. NOTE: This will ONLY work on an IMG tag. Returns FALSE on all
|
1472 |
-
* other tag types.
|
1473 |
-
*
|
1474 |
-
* @author John Schlick
|
1475 |
-
* @version April 19 2012
|
1476 |
-
* @return array an array containing the 'height' and 'width' of the image
|
1477 |
-
* on the page or -1 if we can't figure it out.
|
1478 |
-
*/
|
1479 |
-
function get_display_size()
|
1480 |
-
{
|
1481 |
-
global $debug_object;
|
1482 |
-
|
1483 |
-
$width = -1;
|
1484 |
-
$height = -1;
|
1485 |
-
|
1486 |
-
if ($this->tag !== 'img') {
|
1487 |
-
return false;
|
1488 |
-
}
|
1489 |
-
|
1490 |
-
// See if there is aheight or width attribute in the tag itself.
|
1491 |
-
if (isset($this->attr['width'])) {
|
1492 |
-
$width = $this->attr['width'];
|
1493 |
-
}
|
1494 |
-
|
1495 |
-
if (isset($this->attr['height'])) {
|
1496 |
-
$height = $this->attr['height'];
|
1497 |
-
}
|
1498 |
-
|
1499 |
-
// Now look for an inline style.
|
1500 |
-
if (isset($this->attr['style'])) {
|
1501 |
-
// Thanks to user gnarf from stackoverflow for this regular expression.
|
1502 |
-
$attributes = array();
|
1503 |
-
|
1504 |
-
preg_match_all(
|
1505 |
-
'/([\w-]+)\s*:\s*([^;]+)\s*;?/',
|
1506 |
-
$this->attr['style'],
|
1507 |
-
$matches,
|
1508 |
-
PREG_SET_ORDER
|
1509 |
-
);
|
1510 |
-
|
1511 |
-
foreach ($matches as $match) {
|
1512 |
-
$attributes[$match[1]] = $match[2];
|
1513 |
-
}
|
1514 |
-
|
1515 |
-
// If there is a width in the style attributes:
|
1516 |
-
if (isset($attributes['width']) && $width == -1) {
|
1517 |
-
// check that the last two characters are px (pixels)
|
1518 |
-
if (strtolower(substr($attributes['width'], -2)) === 'px') {
|
1519 |
-
$proposed_width = substr($attributes['width'], 0, -2);
|
1520 |
-
// Now make sure that it's an integer and not something stupid.
|
1521 |
-
if (filter_var($proposed_width, FILTER_VALIDATE_INT)) {
|
1522 |
-
$width = $proposed_width;
|
1523 |
-
}
|
1524 |
-
}
|
1525 |
-
}
|
1526 |
-
|
1527 |
-
// If there is a width in the style attributes:
|
1528 |
-
if (isset($attributes['height']) && $height == -1) {
|
1529 |
-
// check that the last two characters are px (pixels)
|
1530 |
-
if (strtolower(substr($attributes['height'], -2)) == 'px') {
|
1531 |
-
$proposed_height = substr($attributes['height'], 0, -2);
|
1532 |
-
// Now make sure that it's an integer and not something stupid.
|
1533 |
-
if (filter_var($proposed_height, FILTER_VALIDATE_INT)) {
|
1534 |
-
$height = $proposed_height;
|
1535 |
-
}
|
1536 |
-
}
|
1537 |
-
}
|
1538 |
-
}
|
1539 |
-
|
1540 |
-
// Future enhancement:
|
1541 |
-
// Look in the tag to see if there is a class or id specified that has
|
1542 |
-
// a height or width attribute to it.
|
1543 |
-
|
1544 |
-
// Far future enhancement
|
1545 |
-
// Look at all the parent tags of this image to see if they specify a
|
1546 |
-
// class or id that has an img selector that specifies a height or width
|
1547 |
-
// Note that in this case, the class or id will have the img subselector
|
1548 |
-
// for it to apply to the image.
|
1549 |
-
|
1550 |
-
// ridiculously far future development
|
1551 |
-
// If the class or id is specified in a SEPARATE css file thats not on
|
1552 |
-
// the page, go get it and do what we were just doing for the ones on
|
1553 |
-
// the page.
|
1554 |
-
|
1555 |
-
$result = array(
|
1556 |
-
'height' => $height,
|
1557 |
-
'width' => $width
|
1558 |
-
);
|
1559 |
-
|
1560 |
-
return $result;
|
1561 |
-
}
|
1562 |
-
|
1563 |
-
// camel naming conventions
|
1564 |
-
function getAllAttributes()
|
1565 |
-
{
|
1566 |
-
return $this->attr;
|
1567 |
-
}
|
1568 |
-
|
1569 |
-
function getAttribute($name)
|
1570 |
-
{
|
1571 |
-
return $this->__get($name);
|
1572 |
-
}
|
1573 |
-
|
1574 |
-
function setAttribute($name, $value)
|
1575 |
-
{
|
1576 |
-
$this->__set($name, $value);
|
1577 |
-
}
|
1578 |
-
|
1579 |
-
function hasAttribute($name)
|
1580 |
-
{
|
1581 |
-
return $this->__isset($name);
|
1582 |
-
}
|
1583 |
-
|
1584 |
-
function removeAttribute($name)
|
1585 |
-
{
|
1586 |
-
$this->__set($name, null);
|
1587 |
-
}
|
1588 |
-
|
1589 |
-
function getElementById($id)
|
1590 |
-
{
|
1591 |
-
return $this->find("#$id", 0);
|
1592 |
-
}
|
1593 |
-
|
1594 |
-
function getElementsById($id, $idx = null)
|
1595 |
-
{
|
1596 |
-
return $this->find("#$id", $idx);
|
1597 |
-
}
|
1598 |
-
|
1599 |
-
function getElementByTagName($name)
|
1600 |
-
{
|
1601 |
-
return $this->find($name, 0);
|
1602 |
-
}
|
1603 |
-
|
1604 |
-
function getElementsByTagName($name, $idx = null)
|
1605 |
-
{
|
1606 |
-
return $this->find($name, $idx);
|
1607 |
-
}
|
1608 |
-
|
1609 |
-
function parentNode()
|
1610 |
-
{
|
1611 |
-
return $this->parent();
|
1612 |
-
}
|
1613 |
-
|
1614 |
-
function childNodes($idx = -1)
|
1615 |
-
{
|
1616 |
-
return $this->children($idx);
|
1617 |
-
}
|
1618 |
-
|
1619 |
-
function firstChild()
|
1620 |
-
{
|
1621 |
-
return $this->first_child();
|
1622 |
-
}
|
1623 |
-
|
1624 |
-
function lastChild()
|
1625 |
-
{
|
1626 |
-
return $this->last_child();
|
1627 |
-
}
|
1628 |
-
|
1629 |
-
function nextSibling()
|
1630 |
-
{
|
1631 |
-
return $this->next_sibling();
|
1632 |
-
}
|
1633 |
-
|
1634 |
-
function previousSibling()
|
1635 |
-
{
|
1636 |
-
return $this->prev_sibling();
|
1637 |
-
}
|
1638 |
-
|
1639 |
-
function hasChildNodes()
|
1640 |
-
{
|
1641 |
-
return $this->has_child();
|
1642 |
-
}
|
1643 |
-
|
1644 |
-
function nodeName()
|
1645 |
-
{
|
1646 |
-
return $this->tag;
|
1647 |
-
}
|
1648 |
-
|
1649 |
-
function appendChild($node)
|
1650 |
-
{
|
1651 |
-
$node->parent($this);
|
1652 |
-
return $node;
|
1653 |
-
}
|
1654 |
-
}
|
1655 |
-
|
1656 |
-
/**
|
1657 |
-
* simple html dom parser
|
1658 |
-
*
|
1659 |
-
* Paperg - in the find routine: allow us to specify that we want case
|
1660 |
-
* insensitive testing of the value of the selector.
|
1661 |
-
*
|
1662 |
-
* Paperg - change $size from protected to public so we can easily access it
|
1663 |
-
*
|
1664 |
-
* Paperg - added ForceTagsClosed in the constructor which tells us whether we
|
1665 |
-
* trust the html or not. Default is to NOT trust it.
|
1666 |
-
*
|
1667 |
-
* @package PlaceLocalInclude
|
1668 |
-
*/
|
1669 |
-
class simple_html_dom
|
1670 |
-
{
|
1671 |
-
/**
|
1672 |
-
* The root node of the document
|
1673 |
-
*
|
1674 |
-
* @var object
|
1675 |
-
*/
|
1676 |
-
public $root = null;
|
1677 |
-
|
1678 |
-
/**
|
1679 |
-
* List of nodes in the current DOM
|
1680 |
-
*
|
1681 |
-
* @var array
|
1682 |
-
*/
|
1683 |
-
public $nodes = array();
|
1684 |
-
|
1685 |
-
/**
|
1686 |
-
* Callback function to run for each element in the DOM.
|
1687 |
-
*
|
1688 |
-
* @var callable|null
|
1689 |
-
*/
|
1690 |
-
public $callback = null;
|
1691 |
-
|
1692 |
-
/**
|
1693 |
-
* Indicates how tags and attributes are matched
|
1694 |
-
*
|
1695 |
-
* @var bool When set to **true** tags and attributes will be converted to
|
1696 |
-
* lowercase before matching.
|
1697 |
-
*/
|
1698 |
-
public $lowercase = false;
|
1699 |
-
|
1700 |
-
/**
|
1701 |
-
* Original document size
|
1702 |
-
*
|
1703 |
-
* Holds the original document size.
|
1704 |
-
*
|
1705 |
-
* @var int
|
1706 |
-
*/
|
1707 |
-
public $original_size;
|
1708 |
-
|
1709 |
-
/**
|
1710 |
-
* Current document size
|
1711 |
-
*
|
1712 |
-
* Holds the current document size. The document size is determined by the
|
1713 |
-
* string length of ({@see simple_html_dom::$doc}).
|
1714 |
-
*
|
1715 |
-
* _Note_: Using this variable is more efficient than calling `strlen($doc)`
|
1716 |
-
*
|
1717 |
-
* @var int
|
1718 |
-
* */
|
1719 |
-
public $size;
|
1720 |
-
|
1721 |
-
/**
|
1722 |
-
* Current position in the document
|
1723 |
-
*
|
1724 |
-
* @var int
|
1725 |
-
*/
|
1726 |
-
protected $pos;
|
1727 |
-
|
1728 |
-
/**
|
1729 |
-
* The document
|
1730 |
-
*
|
1731 |
-
* @var string
|
1732 |
-
*/
|
1733 |
-
protected $doc;
|
1734 |
-
|
1735 |
-
/**
|
1736 |
-
* Current character
|
1737 |
-
*
|
1738 |
-
* Holds the current character at position {@see simple_html_dom::$pos} in
|
1739 |
-
* the document {@see simple_html_dom::$doc}
|
1740 |
-
*
|
1741 |
-
* _Note_: Using this variable is more efficient than calling
|
1742 |
-
* `substr($doc, $pos, 1)`
|
1743 |
-
*
|
1744 |
-
* @var string
|
1745 |
-
*/
|
1746 |
-
protected $char;
|
1747 |
-
|
1748 |
-
protected $cursor;
|
1749 |
-
|
1750 |
-
/**
|
1751 |
-
* Parent node of the next node detected by the parser
|
1752 |
-
*
|
1753 |
-
* @var object
|
1754 |
-
*/
|
1755 |
-
protected $parent;
|
1756 |
-
protected $noise = array();
|
1757 |
-
|
1758 |
-
/**
|
1759 |
-
* Tokens considered blank in HTML
|
1760 |
-
*
|
1761 |
-
* @var string
|
1762 |
-
*/
|
1763 |
-
protected $token_blank = " \t\r\n";
|
1764 |
-
|
1765 |
-
/**
|
1766 |
-
* Tokens to identify the equal sign for attributes, stopping either at the
|
1767 |
-
* closing tag ("/" i.e. "<html />") or the end of an opening tag (">" i.e.
|
1768 |
-
* "<html>")
|
1769 |
-
*
|
1770 |
-
* @var string
|
1771 |
-
*/
|
1772 |
-
protected $token_equal = ' =/>';
|
1773 |
-
|
1774 |
-
/**
|
1775 |
-
* Tokens to identify the end of a tag name. A tag name either ends on the
|
1776 |
-
* ending slash ("/" i.e. "<html/>") or whitespace ("\s\r\n\t")
|
1777 |
-
*
|
1778 |
-
* @var string
|
1779 |
-
*/
|
1780 |
-
protected $token_slash = " />\r\n\t";
|
1781 |
-
|
1782 |
-
/**
|
1783 |
-
* Tokens to identify the end of an attribute
|
1784 |
-
*
|
1785 |
-
* @var string
|
1786 |
-
*/
|
1787 |
-
protected $token_attr = ' >';
|
1788 |
-
|
1789 |
-
// Note that this is referenced by a child node, and so it needs to be
|
1790 |
-
// public for that node to see this information.
|
1791 |
-
public $_charset = '';
|
1792 |
-
public $_target_charset = '';
|
1793 |
-
|
1794 |
-
/**
|
1795 |
-
* Innertext for <br> elements
|
1796 |
-
*
|
1797 |
-
* @var string
|
1798 |
-
*/
|
1799 |
-
protected $default_br_text = '';
|
1800 |
-
|
1801 |
-
/**
|
1802 |
-
* Suffix for <span> elements
|
1803 |
-
*
|
1804 |
-
* @var string
|
1805 |
-
*/
|
1806 |
-
public $default_span_text = '';
|
1807 |
-
|
1808 |
-
/**
|
1809 |
-
* Defines a list of self-closing tags (Void elements) according to the HTML
|
1810 |
-
* Specification
|
1811 |
-
*
|
1812 |
-
* _Remarks_:
|
1813 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1814 |
-
* performance about 30%
|
1815 |
-
* - Sort elements by name for better readability!
|
1816 |
-
*
|
1817 |
-
* @link https://www.w3.org/TR/html HTML Specification
|
1818 |
-
* @link https://www.w3.org/TR/html/syntax.html#void-elements Void elements
|
1819 |
-
*/
|
1820 |
-
protected $self_closing_tags = array(
|
1821 |
-
'area' => 1,
|
1822 |
-
'base' => 1,
|
1823 |
-
'br' => 1,
|
1824 |
-
'col' => 1,
|
1825 |
-
'embed' => 1,
|
1826 |
-
'hr' => 1,
|
1827 |
-
'img' => 1,
|
1828 |
-
'input' => 1,
|
1829 |
-
'link' => 1,
|
1830 |
-
'meta' => 1,
|
1831 |
-
'param' => 1,
|
1832 |
-
'source' => 1,
|
1833 |
-
'track' => 1,
|
1834 |
-
'wbr' => 1
|
1835 |
-
);
|
1836 |
-
|
1837 |
-
/**
|
1838 |
-
* Defines a list of tags which - if closed - close all optional closing
|
1839 |
-
* elements within if they haven't been closed yet. (So, an element where
|
1840 |
-
* neither opening nor closing tag is omissible consistently closes every
|
1841 |
-
* optional closing element within)
|
1842 |
-
*
|
1843 |
-
* _Remarks_:
|
1844 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1845 |
-
* performance about 30%
|
1846 |
-
* - Sort elements by name for better readability!
|
1847 |
-
*/
|
1848 |
-
protected $block_tags = array(
|
1849 |
-
'body' => 1,
|
1850 |
-
'div' => 1,
|
1851 |
-
'form' => 1,
|
1852 |
-
'root' => 1,
|
1853 |
-
'span' => 1,
|
1854 |
-
'table' => 1
|
1855 |
-
);
|
1856 |
-
|
1857 |
-
/**
|
1858 |
-
* Defines elements whose end tag is omissible.
|
1859 |
-
*
|
1860 |
-
* * key = Name of an element whose end tag is omissible.
|
1861 |
-
* * value = Names of elements whose end tag is omissible, that are closed
|
1862 |
-
* by the current element.
|
1863 |
-
*
|
1864 |
-
* _Remarks_:
|
1865 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1866 |
-
* performance about 30%
|
1867 |
-
* - Sort elements by name for better readability!
|
1868 |
-
*
|
1869 |
-
* **Example**
|
1870 |
-
*
|
1871 |
-
* An `li` element’s end tag may be omitted if the `li` element is immediately
|
1872 |
-
* followed by another `li` element. To do that, add following element to the
|
1873 |
-
* array:
|
1874 |
-
*
|
1875 |
-
* ```php
|
1876 |
-
* 'li' => array('li'),
|
1877 |
-
* ```
|
1878 |
-
*
|
1879 |
-
* With this, the following two examples are considered equal. Note that the
|
1880 |
-
* second example is missing the closing tags on `li` elements.
|
1881 |
-
*
|
1882 |
-
* ```html
|
1883 |
-
* <ul><li>First Item</li><li>Second Item</li></ul>
|
1884 |
-
* ```
|
1885 |
-
*
|
1886 |
-
* <ul><li>First Item</li><li>Second Item</li></ul>
|
1887 |
-
*
|
1888 |
-
* ```html
|
1889 |
-
* <ul><li>First Item<li>Second Item</ul>
|
1890 |
-
* ```
|
1891 |
-
*
|
1892 |
-
* <ul><li>First Item<li>Second Item</ul>
|
1893 |
-
*
|
1894 |
-
* @var array A two-dimensional array where the key is the name of an
|
1895 |
-
* element whose end tag is omissible and the value is an array of elements
|
1896 |
-
* whose end tag is omissible, that are closed by the current element.
|
1897 |
-
*
|
1898 |
-
* @link https://www.w3.org/TR/html/syntax.html#optional-tags Optional tags
|
1899 |
-
*
|
1900 |
-
* @todo The implementation of optional closing tags doesn't work in all cases
|
1901 |
-
* because it only consideres elements who close other optional closing
|
1902 |
-
* tags, not taking into account that some (non-blocking) tags should close
|
1903 |
-
* these optional closing tags. For example, the end tag for "p" is omissible
|
1904 |
-
* and can be closed by an "address" element, whose end tag is NOT omissible.
|
1905 |
-
* Currently a "p" element without closing tag stops at the next "p" element
|
1906 |
-
* or blocking tag, even if it contains other elements.
|
1907 |
-
*
|
1908 |
-
* @todo Known sourceforge issue #2977341
|
1909 |
-
* B tags that are not closed cause us to return everything to the end of
|
1910 |
-
* the document.
|
1911 |
-
*/
|
1912 |
-
protected $optional_closing_tags = array(
|
1913 |
-
// Not optional, see
|
1914 |
-
// https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
|
1915 |
-
'b' => array('b' => 1),
|
1916 |
-
'dd' => array('dd' => 1, 'dt' => 1),
|
1917 |
-
// Not optional, see
|
1918 |
-
// https://www.w3.org/TR/html/grouping-content.html#the-dl-element
|
1919 |
-
'dl' => array('dd' => 1, 'dt' => 1),
|
1920 |
-
'dt' => array('dd' => 1, 'dt' => 1),
|
1921 |
-
'li' => array('li' => 1),
|
1922 |
-
'optgroup' => array('optgroup' => 1, 'option' => 1),
|
1923 |
-
'option' => array('optgroup' => 1, 'option' => 1),
|
1924 |
-
'p' => array('p' => 1),
|
1925 |
-
'rp' => array('rp' => 1, 'rt' => 1),
|
1926 |
-
'rt' => array('rp' => 1, 'rt' => 1),
|
1927 |
-
'td' => array('td' => 1, 'th' => 1),
|
1928 |
-
'th' => array('td' => 1, 'th' => 1),
|
1929 |
-
'tr' => array('td' => 1, 'th' => 1, 'tr' => 1),
|
1930 |
-
);
|
1931 |
-
|
1932 |
-
function __construct(
|
1933 |
-
$str = null,
|
1934 |
-
$lowercase = true,
|
1935 |
-
$forceTagsClosed = true,
|
1936 |
-
$target_charset = DEFAULT_TARGET_CHARSET,
|
1937 |
-
$stripRN = true,
|
1938 |
-
$defaultBRText = DEFAULT_BR_TEXT,
|
1939 |
-
$defaultSpanText = DEFAULT_SPAN_TEXT,
|
1940 |
-
$options = 0
|
1941 |
-
) {
|
1942 |
-
if ($str) {
|
1943 |
-
if (preg_match('/^http:\/\//i', $str) || is_file($str)) {
|
1944 |
-
$this->load_file($str);
|
1945 |
-
} else {
|
1946 |
-
$this->load(
|
1947 |
-
$str,
|
1948 |
-
$lowercase,
|
1949 |
-
$stripRN,
|
1950 |
-
$defaultBRText,
|
1951 |
-
$defaultSpanText,
|
1952 |
-
$options
|
1953 |
-
);
|
1954 |
-
}
|
1955 |
-
}
|
1956 |
-
// Forcing tags to be closed implies that we don't trust the html, but
|
1957 |
-
// it can lead to parsing errors if we SHOULD trust the html.
|
1958 |
-
if (!$forceTagsClosed) {
|
1959 |
-
$this->optional_closing_array = array();
|
1960 |
-
}
|
1961 |
-
|
1962 |
-
$this->_target_charset = $target_charset;
|
1963 |
-
}
|
1964 |
-
|
1965 |
-
function __destruct()
|
1966 |
-
{
|
1967 |
-
$this->clear();
|
1968 |
-
}
|
1969 |
-
|
1970 |
-
// load html from string
|
1971 |
-
function load(
|
1972 |
-
$str,
|
1973 |
-
$lowercase = true,
|
1974 |
-
$stripRN = true,
|
1975 |
-
$defaultBRText = DEFAULT_BR_TEXT,
|
1976 |
-
$defaultSpanText = DEFAULT_SPAN_TEXT,
|
1977 |
-
$options = 0
|
1978 |
-
) {
|
1979 |
-
global $debug_object;
|
1980 |
-
|
1981 |
-
// prepare
|
1982 |
-
$this->prepare($str, $lowercase, $defaultBRText, $defaultSpanText);
|
1983 |
-
|
1984 |
-
// Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037
|
1985 |
-
// Script tags removal now preceeds style tag removal.
|
1986 |
-
// strip out <script> tags
|
1987 |
-
$this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is");
|
1988 |
-
$this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is");
|
1989 |
-
|
1990 |
-
// strip out the \r \n's if we are told to.
|
1991 |
-
if ($stripRN) {
|
1992 |
-
$this->doc = str_replace("\r", ' ', $this->doc);
|
1993 |
-
$this->doc = str_replace("\n", ' ', $this->doc);
|
1994 |
-
|
1995 |
-
// set the length of content since we have changed it.
|
1996 |
-
$this->size = strlen($this->doc);
|
1997 |
-
}
|
1998 |
-
|
1999 |
-
// strip out cdata
|
2000 |
-
$this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true);
|
2001 |
-
// strip out comments
|
2002 |
-
$this->remove_noise("'<!--(.*?)-->'is");
|
2003 |
-
// strip out <style> tags
|
2004 |
-
$this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is");
|
2005 |
-
$this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is");
|
2006 |
-
// strip out preformatted tags
|
2007 |
-
$this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is");
|
2008 |
-
// strip out server side scripts
|
2009 |
-
$this->remove_noise("'(<\?)(.*?)(\?>)'s", true);
|
2010 |
-
|
2011 |
-
if ($options & HDOM_SMARTY_AS_TEXT) { // Strip Smarty scripts
|
2012 |
-
$this->remove_noise("'(\{\w)(.*?)(\})'s", true);
|
2013 |
-
}
|
2014 |
-
|
2015 |
-
// parsing
|
2016 |
-
$this->parse();
|
2017 |
-
// end
|
2018 |
-
$this->root->_[HDOM_INFO_END] = $this->cursor;
|
2019 |
-
$this->parse_charset();
|
2020 |
-
|
2021 |
-
// make load function chainable
|
2022 |
-
return $this;
|
2023 |
-
}
|
2024 |
-
|
2025 |
-
// load html from file
|
2026 |
-
function load_file()
|
2027 |
-
{
|
2028 |
-
$args = func_get_args();
|
2029 |
-
|
2030 |
-
if (($doc = call_user_func_array('file_get_contents', $args)) !== false) {
|
2031 |
-
$this->load($doc, true);
|
2032 |
-
} else {
|
2033 |
-
return false;
|
2034 |
-
}
|
2035 |
-
}
|
2036 |
-
|
2037 |
-
/**
|
2038 |
-
* Set the callback function
|
2039 |
-
*
|
2040 |
-
* @param callable $function_name Callback function to run for each element
|
2041 |
-
* in the DOM.
|
2042 |
-
* @return void
|
2043 |
-
*/
|
2044 |
-
function set_callback($function_name)
|
2045 |
-
{
|
2046 |
-
$this->callback = $function_name;
|
2047 |
-
}
|
2048 |
-
|
2049 |
-
/**
|
2050 |
-
* Remove callback function
|
2051 |
-
*
|
2052 |
-
* @return void
|
2053 |
-
*/
|
2054 |
-
function remove_callback()
|
2055 |
-
{
|
2056 |
-
$this->callback = null;
|
2057 |
-
}
|
2058 |
-
|
2059 |
-
// save dom as string
|
2060 |
-
function save($filepath = '')
|
2061 |
-
{
|
2062 |
-
$ret = $this->root->innertext();
|
2063 |
-
if ($filepath !== '') {
|
2064 |
-
file_put_contents($filepath, $ret, LOCK_EX);
|
2065 |
-
}
|
2066 |
-
return $ret;
|
2067 |
-
}
|
2068 |
-
|
2069 |
-
// find dom node by css selector
|
2070 |
-
// Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
|
2071 |
-
function find($selector, $idx = null, $lowercase = false)
|
2072 |
-
{
|
2073 |
-
return $this->root->find($selector, $idx, $lowercase);
|
2074 |
-
}
|
2075 |
-
|
2076 |
-
// clean up memory due to php5 circular references memory leak...
|
2077 |
-
function clear()
|
2078 |
-
{
|
2079 |
-
foreach ($this->nodes as $n) {
|
2080 |
-
$n->clear();
|
2081 |
-
$n = null;
|
2082 |
-
}
|
2083 |
-
|
2084 |
-
// This add next line is documented in the sourceforge repository.
|
2085 |
-
// 2977248 as a fix for ongoing memory leaks that occur even with the
|
2086 |
-
// use of clear.
|
2087 |
-
if (isset($this->children)) {
|
2088 |
-
foreach ($this->children as $n) {
|
2089 |
-
$n->clear();
|
2090 |
-
$n = null;
|
2091 |
-
}
|
2092 |
-
}
|
2093 |
-
|
2094 |
-
if (isset($this->parent)) {
|
2095 |
-
$this->parent->clear();
|
2096 |
-
unset($this->parent);
|
2097 |
-
}
|
2098 |
-
|
2099 |
-
if (isset($this->root)) {
|
2100 |
-
$this->root->clear();
|
2101 |
-
unset($this->root);
|
2102 |
-
}
|
2103 |
-
|
2104 |
-
unset($this->doc);
|
2105 |
-
unset($this->noise);
|
2106 |
-
}
|
2107 |
-
|
2108 |
-
function dump($show_attr = true)
|
2109 |
-
{
|
2110 |
-
$this->root->dump($show_attr);
|
2111 |
-
}
|
2112 |
-
|
2113 |
-
// prepare HTML data and init everything
|
2114 |
-
protected function prepare(
|
2115 |
-
$str,
|
2116 |
-
$lowercase = true,
|
2117 |
-
$defaultBRText = DEFAULT_BR_TEXT,
|
2118 |
-
$defaultSpanText = DEFAULT_SPAN_TEXT
|
2119 |
-
) {
|
2120 |
-
$this->clear();
|
2121 |
-
|
2122 |
-
$this->doc = trim($str);
|
2123 |
-
$this->size = strlen($this->doc);
|
2124 |
-
$this->original_size = $this->size; // original size of the html
|
2125 |
-
$this->pos = 0;
|
2126 |
-
$this->cursor = 1;
|
2127 |
-
$this->noise = array();
|
2128 |
-
$this->nodes = array();
|
2129 |
-
$this->lowercase = $lowercase;
|
2130 |
-
$this->default_br_text = $defaultBRText;
|
2131 |
-
$this->default_span_text = $defaultSpanText;
|
2132 |
-
$this->root = new simple_html_dom_node($this);
|
2133 |
-
$this->root->tag = 'root';
|
2134 |
-
$this->root->_[HDOM_INFO_BEGIN] = -1;
|
2135 |
-
$this->root->nodetype = HDOM_TYPE_ROOT;
|
2136 |
-
$this->parent = $this->root;
|
2137 |
-
if ($this->size > 0) {
|
2138 |
-
$this->char = $this->doc[0];
|
2139 |
-
}
|
2140 |
-
}
|
2141 |
-
|
2142 |
-
/**
|
2143 |
-
* Parse HTML content
|
2144 |
-
*
|
2145 |
-
* @return bool True on success
|
2146 |
-
*/
|
2147 |
-
protected function parse()
|
2148 |
-
{
|
2149 |
-
while (true) {
|
2150 |
-
// Read next tag if there is no text between current position and the
|
2151 |
-
// next opening tag.
|
2152 |
-
if (($s = $this->copy_until_char('<')) === '') {
|
2153 |
-
if ($this->read_tag()) {
|
2154 |
-
continue;
|
2155 |
-
} else {
|
2156 |
-
return true;
|
2157 |
-
}
|
2158 |
-
}
|
2159 |
-
|
2160 |
-
// Add a text node for text between tags
|
2161 |
-
$node = new simple_html_dom_node($this);
|
2162 |
-
++$this->cursor;
|
2163 |
-
$node->_[HDOM_INFO_TEXT] = $s;
|
2164 |
-
$this->link_nodes($node, false);
|
2165 |
-
}
|
2166 |
-
}
|
2167 |
-
|
2168 |
-
// PAPERG - dkchou - added this to try to identify the character set of the
|
2169 |
-
// page we have just parsed so we know better how to spit it out later.
|
2170 |
-
// NOTE: IF you provide a routine called
|
2171 |
-
// get_last_retrieve_url_contents_content_type which returns the
|
2172 |
-
// CURLINFO_CONTENT_TYPE from the last curl_exec
|
2173 |
-
// (or the content_type header from the last transfer), we will parse THAT,
|
2174 |
-
// and if a charset is specified, we will use it over any other mechanism.
|
2175 |
-
protected function parse_charset()
|
2176 |
-
{
|
2177 |
-
global $debug_object;
|
2178 |
-
|
2179 |
-
$charset = null;
|
2180 |
-
|
2181 |
-
if (function_exists('get_last_retrieve_url_contents_content_type')) {
|
2182 |
-
$contentTypeHeader = get_last_retrieve_url_contents_content_type();
|
2183 |
-
$success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
|
2184 |
-
if ($success) {
|
2185 |
-
$charset = $matches[1];
|
2186 |
-
if (is_object($debug_object)) {
|
2187 |
-
$debug_object->debug_log(
|
2188 |
-
2,
|
2189 |
-
'header content-type found charset of: '
|
2190 |
-
. $charset
|
2191 |
-
);
|
2192 |
-
}
|
2193 |
-
}
|
2194 |
-
}
|
2195 |
-
|
2196 |
-
if (empty($charset)) {
|
2197 |
-
$el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
|
2198 |
-
|
2199 |
-
if (!empty($el)) {
|
2200 |
-
$fullvalue = $el->content;
|
2201 |
-
if (is_object($debug_object)) {
|
2202 |
-
$debug_object->debug_log(
|
2203 |
-
2,
|
2204 |
-
'meta content-type tag found'
|
2205 |
-
. $fullvalue
|
2206 |
-
);
|
2207 |
-
}
|
2208 |
-
|
2209 |
-
if (!empty($fullvalue)) {
|
2210 |
-
$success = preg_match(
|
2211 |
-
'/charset=(.+)/i',
|
2212 |
-
$fullvalue,
|
2213 |
-
$matches
|
2214 |
-
);
|
2215 |
-
|
2216 |
-
if ($success) {
|
2217 |
-
$charset = $matches[1];
|
2218 |
-
} else {
|
2219 |
-
// If there is a meta tag, and they don't specify the
|
2220 |
-
// character set, research says that it's typically
|
2221 |
-
// ISO-8859-1
|
2222 |
-
if (is_object($debug_object)) {
|
2223 |
-
$debug_object->debug_log(
|
2224 |
-
2,
|
2225 |
-
'meta content-type tag couldn\'t be parsed. using iso-8859 default.'
|
2226 |
-
);
|
2227 |
-
}
|
2228 |
-
|
2229 |
-
$charset = 'ISO-8859-1';
|
2230 |
-
}
|
2231 |
-
}
|
2232 |
-
}
|
2233 |
-
}
|
2234 |
-
|
2235 |
-
// If we couldn't find a charset above, then lets try to detect one
|
2236 |
-
// based on the text we got...
|
2237 |
-
if (empty($charset)) {
|
2238 |
-
// Use this in case mb_detect_charset isn't installed/loaded on
|
2239 |
-
// this machine.
|
2240 |
-
$charset = false;
|
2241 |
-
if (function_exists('mb_detect_encoding')) {
|
2242 |
-
// Have php try to detect the encoding from the text given to us.
|
2243 |
-
$charset = mb_detect_encoding(
|
2244 |
-
$this->doc . 'ascii',
|
2245 |
-
$encoding_list = array( 'UTF-8', 'CP1252' )
|
2246 |
-
);
|
2247 |
-
|
2248 |
-
if (is_object($debug_object)) {
|
2249 |
-
$debug_object->debug_log(2, 'mb_detect found: ' . $charset);
|
2250 |
-
}
|
2251 |
-
}
|
2252 |
-
|
2253 |
-
// and if this doesn't work... then we need to just wrongheadedly
|
2254 |
-
// assume it's UTF-8 so that we can move on - cause this will
|
2255 |
-
// usually give us most of what we need...
|
2256 |
-
if ($charset === false) {
|
2257 |
-
if (is_object($debug_object)) {
|
2258 |
-
$debug_object->debug_log(
|
2259 |
-
2,
|
2260 |
-
'since mb_detect failed - using default of utf-8'
|
2261 |
-
);
|
2262 |
-
}
|
2263 |
-
|
2264 |
-
$charset = 'UTF-8';
|
2265 |
-
}
|
2266 |
-
}
|
2267 |
-
|
2268 |
-
// Since CP1252 is a superset, if we get one of it's subsets, we want
|
2269 |
-
// it instead.
|
2270 |
-
if ((strtolower($charset) == strtolower('ISO-8859-1'))
|
2271 |
-
|| (strtolower($charset) == strtolower('Latin1'))
|
2272 |
-
|| (strtolower($charset) == strtolower('Latin-1'))) {
|
2273 |
-
if (is_object($debug_object)) {
|
2274 |
-
$debug_object->debug_log(
|
2275 |
-
2,
|
2276 |
-
'replacing ' . $charset . ' with CP1252 as its a superset'
|
2277 |
-
);
|
2278 |
-
}
|
2279 |
-
|
2280 |
-
$charset = 'CP1252';
|
2281 |
-
}
|
2282 |
-
|
2283 |
-
if (is_object($debug_object)) {
|
2284 |
-
$debug_object->debug_log(1, 'EXIT - ' . $charset);
|
2285 |
-
}
|
2286 |
-
|
2287 |
-
return $this->_charset = $charset;
|
2288 |
-
}
|
2289 |
-
|
2290 |
-
/**
|
2291 |
-
* Parse tag from current document position.
|
2292 |
-
*
|
2293 |
-
* @return bool True if a tag was found, false otherwise
|
2294 |
-
*/
|
2295 |
-
protected function read_tag()
|
2296 |
-
{
|
2297 |
-
// Set end position if no further tags found
|
2298 |
-
if ($this->char !== '<') {
|
2299 |
-
$this->root->_[HDOM_INFO_END] = $this->cursor;
|
2300 |
-
return false;
|
2301 |
-
}
|
2302 |
-
|
2303 |
-
$begin_tag_pos = $this->pos;
|
2304 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2305 |
-
|
2306 |
-
// end tag
|
2307 |
-
if ($this->char === '/') {
|
2308 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2309 |
-
|
2310 |
-
// Skip whitespace in end tags (i.e. in "</ html>")
|
2311 |
-
$this->skip($this->token_blank);
|
2312 |
-
$tag = $this->copy_until_char('>');
|
2313 |
-
|
2314 |
-
// Skip attributes in end tags
|
2315 |
-
if (($pos = strpos($tag, ' ')) !== false) {
|
2316 |
-
$tag = substr($tag, 0, $pos);
|
2317 |
-
}
|
2318 |
-
|
2319 |
-
$parent_lower = strtolower($this->parent->tag);
|
2320 |
-
$tag_lower = strtolower($tag);
|
2321 |
-
|
2322 |
-
// The end tag is supposed to close the parent tag. Handle situations
|
2323 |
-
// when it doesn't
|
2324 |
-
if ($parent_lower !== $tag_lower) {
|
2325 |
-
// Parent tag does not have to be closed necessarily (optional closing tag)
|
2326 |
-
// Current tag is a block tag, so it may close an ancestor
|
2327 |
-
if (isset($this->optional_closing_tags[$parent_lower])
|
2328 |
-
&& isset($this->block_tags[$tag_lower])) {
|
2329 |
-
$this->parent->_[HDOM_INFO_END] = 0;
|
2330 |
-
$org_parent = $this->parent;
|
2331 |
-
|
2332 |
-
// Traverse ancestors to find a matching opening tag
|
2333 |
-
// Stop at root node
|
2334 |
-
while (($this->parent->parent)
|
2335 |
-
&& strtolower($this->parent->tag) !== $tag_lower
|
2336 |
-
) {
|
2337 |
-
$this->parent = $this->parent->parent;
|
2338 |
-
}
|
2339 |
-
|
2340 |
-
// If we don't have a match add current tag as text node
|
2341 |
-
if (strtolower($this->parent->tag) !== $tag_lower) {
|
2342 |
-
$this->parent = $org_parent; // restore origonal parent
|
2343 |
-
|
2344 |
-
if ($this->parent->parent) {
|
2345 |
-
$this->parent = $this->parent->parent;
|
2346 |
-
}
|
2347 |
-
|
2348 |
-
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
2349 |
-
return $this->as_text_node($tag);
|
2350 |
-
}
|
2351 |
-
} elseif (($this->parent->parent)
|
2352 |
-
&& isset($this->block_tags[$tag_lower])
|
2353 |
-
) {
|
2354 |
-
// Grandparent exists and current tag is a block tag, so our
|
2355 |
-
// parent doesn't have an end tag
|
2356 |
-
$this->parent->_[HDOM_INFO_END] = 0; // No end tag
|
2357 |
-
$org_parent = $this->parent;
|
2358 |
-
|
2359 |
-
// Traverse ancestors to find a matching opening tag
|
2360 |
-
// Stop at root node
|
2361 |
-
while (($this->parent->parent)
|
2362 |
-
&& strtolower($this->parent->tag) !== $tag_lower
|
2363 |
-
) {
|
2364 |
-
$this->parent = $this->parent->parent;
|
2365 |
-
}
|
2366 |
-
|
2367 |
-
// If we don't have a match add current tag as text node
|
2368 |
-
if (strtolower($this->parent->tag) !== $tag_lower) {
|
2369 |
-
$this->parent = $org_parent; // restore origonal parent
|
2370 |
-
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
2371 |
-
return $this->as_text_node($tag);
|
2372 |
-
}
|
2373 |
-
} elseif (($this->parent->parent)
|
2374 |
-
&& strtolower($this->parent->parent->tag) === $tag_lower
|
2375 |
-
) { // Grandparent exists and current tag closes it
|
2376 |
-
$this->parent->_[HDOM_INFO_END] = 0;
|
2377 |
-
$this->parent = $this->parent->parent;
|
2378 |
-
} else { // Random tag, add as text node
|
2379 |
-
return $this->as_text_node($tag);
|
2380 |
-
}
|
2381 |
-
}
|
2382 |
-
|
2383 |
-
// Set end position of parent tag to current cursor position
|
2384 |
-
$this->parent->_[HDOM_INFO_END] = $this->cursor;
|
2385 |
-
|
2386 |
-
if ($this->parent->parent) {
|
2387 |
-
$this->parent = $this->parent->parent;
|
2388 |
-
}
|
2389 |
-
|
2390 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2391 |
-
return true;
|
2392 |
-
}
|
2393 |
-
|
2394 |
-
// start tag
|
2395 |
-
$node = new simple_html_dom_node($this);
|
2396 |
-
$node->_[HDOM_INFO_BEGIN] = $this->cursor;
|
2397 |
-
++$this->cursor;
|
2398 |
-
$tag = $this->copy_until($this->token_slash); // Get tag name
|
2399 |
-
$node->tag_start = $begin_tag_pos;
|
2400 |
-
|
2401 |
-
// doctype, cdata & comments...
|
2402 |
-
// <!DOCTYPE html>
|
2403 |
-
// <![CDATA[ ... ]]>
|
2404 |
-
// <!-- Comment -->
|
2405 |
-
if (isset($tag[0]) && $tag[0] === '!') {
|
2406 |
-
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>');
|
2407 |
-
|
2408 |
-
if (isset($tag[2]) && $tag[1] === '-' && $tag[2] === '-') { // Comment ("<!--")
|
2409 |
-
$node->nodetype = HDOM_TYPE_COMMENT;
|
2410 |
-
$node->tag = 'comment';
|
2411 |
-
} else { // Could be doctype or CDATA but we don't care
|
2412 |
-
$node->nodetype = HDOM_TYPE_UNKNOWN;
|
2413 |
-
$node->tag = 'unknown';
|
2414 |
-
}
|
2415 |
-
|
2416 |
-
if ($this->char === '>') {
|
2417 |
-
$node->_[HDOM_INFO_TEXT] .= '>';
|
2418 |
-
}
|
2419 |
-
|
2420 |
-
$this->link_nodes($node, true);
|
2421 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2422 |
-
return true;
|
2423 |
-
}
|
2424 |
-
|
2425 |
-
// The start tag cannot contain another start tag, if so add as text
|
2426 |
-
// i.e. "<<html>"
|
2427 |
-
if ($pos = strpos($tag, '<') !== false) {
|
2428 |
-
$tag = '<' . substr($tag, 0, -1);
|
2429 |
-
$node->_[HDOM_INFO_TEXT] = $tag;
|
2430 |
-
$this->link_nodes($node, false);
|
2431 |
-
$this->char = $this->doc[--$this->pos]; // prev
|
2432 |
-
return true;
|
2433 |
-
}
|
2434 |
-
|
2435 |
-
// Handle invalid tag names (i.e. "<html#doc>")
|
2436 |
-
if (!preg_match('/^\w[\w:-]*$/', $tag)) {
|
2437 |
-
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>');
|
2438 |
-
|
2439 |
-
// Next char is the beginning of a new tag, don't touch it.
|
2440 |
-
if ($this->char === '<') {
|
2441 |
-
$this->link_nodes($node, false);
|
2442 |
-
return true;
|
2443 |
-
}
|
2444 |
-
|
2445 |
-
// Next char closes current tag, add and be done with it.
|
2446 |
-
if ($this->char === '>') {
|
2447 |
-
$node->_[HDOM_INFO_TEXT] .= '>';
|
2448 |
-
}
|
2449 |
-
$this->link_nodes($node, false);
|
2450 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2451 |
-
return true;
|
2452 |
-
}
|
2453 |
-
|
2454 |
-
// begin tag, add new node
|
2455 |
-
$node->nodetype = HDOM_TYPE_ELEMENT;
|
2456 |
-
$tag_lower = strtolower($tag);
|
2457 |
-
$node->tag = ($this->lowercase) ? $tag_lower : $tag;
|
2458 |
-
|
2459 |
-
// handle optional closing tags
|
2460 |
-
if (isset($this->optional_closing_tags[$tag_lower])) {
|
2461 |
-
// Traverse ancestors to close all optional closing tags
|
2462 |
-
while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
|
2463 |
-
$this->parent->_[HDOM_INFO_END] = 0;
|
2464 |
-
$this->parent = $this->parent->parent;
|
2465 |
-
}
|
2466 |
-
$node->parent = $this->parent;
|
2467 |
-
}
|
2468 |
-
|
2469 |
-
$guard = 0; // prevent infinity loop
|
2470 |
-
|
2471 |
-
// [0] Space between tag and first attribute
|
2472 |
-
$space = array($this->copy_skip($this->token_blank), '', '');
|
2473 |
-
|
2474 |
-
// attributes
|
2475 |
-
do {
|
2476 |
-
// Everything until the first equal sign should be the attribute name
|
2477 |
-
$name = $this->copy_until($this->token_equal);
|
2478 |
-
|
2479 |
-
if ($name === '' && $this->char !== null && $space[0] === '') {
|
2480 |
-
break;
|
2481 |
-
}
|
2482 |
-
|
2483 |
-
if ($guard === $this->pos) { // Escape infinite loop
|
2484 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2485 |
-
continue;
|
2486 |
-
}
|
2487 |
-
|
2488 |
-
$guard = $this->pos;
|
2489 |
-
|
2490 |
-
// handle endless '<'
|
2491 |
-
// Out of bounds before the tag ended
|
2492 |
-
if ($this->pos >= $this->size - 1 && $this->char !== '>') {
|
2493 |
-
$node->nodetype = HDOM_TYPE_TEXT;
|
2494 |
-
$node->_[HDOM_INFO_END] = 0;
|
2495 |
-
$node->_[HDOM_INFO_TEXT] = '<' . $tag . $space[0] . $name;
|
2496 |
-
$node->tag = 'text';
|
2497 |
-
$this->link_nodes($node, false);
|
2498 |
-
return true;
|
2499 |
-
}
|
2500 |
-
|
2501 |
-
// handle mismatch '<'
|
2502 |
-
// Attributes cannot start after opening tag
|
2503 |
-
if ($this->doc[$this->pos - 1] == '<') {
|
2504 |
-
$node->nodetype = HDOM_TYPE_TEXT;
|
2505 |
-
$node->tag = 'text';
|
2506 |
-
$node->attr = array();
|
2507 |
-
$node->_[HDOM_INFO_END] = 0;
|
2508 |
-
$node->_[HDOM_INFO_TEXT] = substr(
|
2509 |
-
$this->doc,
|
2510 |
-
$begin_tag_pos,
|
2511 |
-
$this->pos - $begin_tag_pos - 1
|
2512 |
-
);
|
2513 |
-
$this->pos -= 2;
|
2514 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2515 |
-
$this->link_nodes($node, false);
|
2516 |
-
return true;
|
2517 |
-
}
|
2518 |
-
|
2519 |
-
if ($name !== '/' && $name !== '') { // this is a attribute name
|
2520 |
-
// [1] Whitespace after attribute name
|
2521 |
-
$space[1] = $this->copy_skip($this->token_blank);
|
2522 |
-
|
2523 |
-
$name = $this->restore_noise($name); // might be a noisy name
|
2524 |
-
|
2525 |
-
if ($this->lowercase) {
|
2526 |
-
$name = strtolower($name);
|
2527 |
-
}
|
2528 |
-
|
2529 |
-
if ($this->char === '=') { // attribute with value
|
2530 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2531 |
-
$this->parse_attr($node, $name, $space); // get attribute value
|
2532 |
-
} else {
|
2533 |
-
//no value attr: nowrap, checked selected...
|
2534 |
-
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
|
2535 |
-
$node->attr[$name] = true;
|
2536 |
-
if ($this->char != '>') {
|
2537 |
-
$this->char = $this->doc[--$this->pos];
|
2538 |
-
} // prev
|
2539 |
-
}
|
2540 |
-
|
2541 |
-
$node->_[HDOM_INFO_SPACE][] = $space;
|
2542 |
-
|
2543 |
-
// prepare for next attribute
|
2544 |
-
$space = array(
|
2545 |
-
$this->copy_skip($this->token_blank),
|
2546 |
-
'',
|
2547 |
-
''
|
2548 |
-
);
|
2549 |
-
} else { // no more attributes
|
2550 |
-
break;
|
2551 |
-
}
|
2552 |
-
} while ($this->char !== '>' && $this->char !== '/'); // go until the tag ended
|
2553 |
-
|
2554 |
-
$this->link_nodes($node, true);
|
2555 |
-
$node->_[HDOM_INFO_ENDSPACE] = $space[0];
|
2556 |
-
|
2557 |
-
// handle empty tags (i.e. "<div/>")
|
2558 |
-
if ($this->copy_until_char('>') === '/') {
|
2559 |
-
$node->_[HDOM_INFO_ENDSPACE] .= '/';
|
2560 |
-
$node->_[HDOM_INFO_END] = 0;
|
2561 |
-
} else {
|
2562 |
-
// reset parent
|
2563 |
-
if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
|
2564 |
-
$this->parent = $node;
|
2565 |
-
}
|
2566 |
-
}
|
2567 |
-
|
2568 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2569 |
-
|
2570 |
-
// If it's a BR tag, we need to set it's text to the default text.
|
2571 |
-
// This way when we see it in plaintext, we can generate formatting that the user wants.
|
2572 |
-
// since a br tag never has sub nodes, this works well.
|
2573 |
-
if ($node->tag === 'br') {
|
2574 |
-
$node->_[HDOM_INFO_INNER] = $this->default_br_text;
|
2575 |
-
}
|
2576 |
-
|
2577 |
-
return true;
|
2578 |
-
}
|
2579 |
-
|
2580 |
-
/**
|
2581 |
-
* Parse attribute from current document position
|
2582 |
-
*
|
2583 |
-
* @param object $node Node for the attributes
|
2584 |
-
* @param string $name Name of the current attribute
|
2585 |
-
* @param array $space Array for spacing information
|
2586 |
-
* @return void
|
2587 |
-
*/
|
2588 |
-
protected function parse_attr($node, $name, &$space)
|
2589 |
-
{
|
2590 |
-
// Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
|
2591 |
-
// If the attribute is already defined inside a tag, only pay attention
|
2592 |
-
// to the first one as opposed to the last one.
|
2593 |
-
// https://stackoverflow.com/a/26341866
|
2594 |
-
if (isset($node->attr[$name])) {
|
2595 |
-
return;
|
2596 |
-
}
|
2597 |
-
|
2598 |
-
// [2] Whitespace between "=" and the value
|
2599 |
-
$space[2] = $this->copy_skip($this->token_blank);
|
2600 |
-
|
2601 |
-
switch ($this->char) {
|
2602 |
-
case '"': // value is anything between double quotes
|
2603 |
-
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE;
|
2604 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2605 |
-
$node->attr[$name] = $this->restore_noise($this->copy_until_char('"'));
|
2606 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2607 |
-
break;
|
2608 |
-
case '\'': // value is anything between single quotes
|
2609 |
-
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE;
|
2610 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2611 |
-
$node->attr[$name] = $this->restore_noise($this->copy_until_char('\''));
|
2612 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2613 |
-
break;
|
2614 |
-
default: // value is anything until the first space or end tag
|
2615 |
-
$node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO;
|
2616 |
-
$node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr));
|
2617 |
-
}
|
2618 |
-
// PaperG: Attributes should not have \r or \n in them, that counts as
|
2619 |
-
// html whitespace.
|
2620 |
-
$node->attr[$name] = str_replace("\r", '', $node->attr[$name]);
|
2621 |
-
$node->attr[$name] = str_replace("\n", '', $node->attr[$name]);
|
2622 |
-
// PaperG: If this is a "class" selector, lets get rid of the preceeding
|
2623 |
-
// and trailing space since some people leave it in the multi class case.
|
2624 |
-
if ($name === 'class') {
|
2625 |
-
$node->attr[$name] = trim($node->attr[$name]);
|
2626 |
-
}
|
2627 |
-
}
|
2628 |
-
|
2629 |
-
/**
|
2630 |
-
* Link node to parent node
|
2631 |
-
*
|
2632 |
-
* @param object $node Node to link to parent
|
2633 |
-
* @param bool $is_child True if the node is a child of parent
|
2634 |
-
* @return void
|
2635 |
-
*/
|
2636 |
-
// link node's parent
|
2637 |
-
protected function link_nodes(&$node, $is_child)
|
2638 |
-
{
|
2639 |
-
$node->parent = $this->parent;
|
2640 |
-
$this->parent->nodes[] = $node;
|
2641 |
-
if ($is_child) {
|
2642 |
-
$this->parent->children[] = $node;
|
2643 |
-
}
|
2644 |
-
}
|
2645 |
-
|
2646 |
-
/**
|
2647 |
-
* Add tag as text node to current node
|
2648 |
-
*
|
2649 |
-
* @param string $tag Tag name
|
2650 |
-
* @return bool True on success
|
2651 |
-
*/
|
2652 |
-
protected function as_text_node($tag)
|
2653 |
-
{
|
2654 |
-
$node = new simple_html_dom_node($this);
|
2655 |
-
++$this->cursor;
|
2656 |
-
$node->_[HDOM_INFO_TEXT] = '</' . $tag . '>';
|
2657 |
-
$this->link_nodes($node, false);
|
2658 |
-
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2659 |
-
return true;
|
2660 |
-
}
|
2661 |
-
|
2662 |
-
/**
|
2663 |
-
* Seek from the current document position to the first occurrence of a
|
2664 |
-
* character not defined by the provided string. Update the current document
|
2665 |
-
* position to the new position.
|
2666 |
-
*
|
2667 |
-
* @param string $chars A string containing every allowed character.
|
2668 |
-
* @return void
|
2669 |
-
*/
|
2670 |
-
protected function skip($chars)
|
2671 |
-
{
|
2672 |
-
$this->pos += strspn($this->doc, $chars, $this->pos);
|
2673 |
-
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2674 |
-
}
|
2675 |
-
|
2676 |
-
/**
|
2677 |
-
* Copy substring from the current document position to the first occurrence
|
2678 |
-
* of a character not defined by the provided string.
|
2679 |
-
*
|
2680 |
-
* @param string $chars A string containing every allowed character.
|
2681 |
-
* @return string Substring from the current document position to the first
|
2682 |
-
* occurrence of a character not defined by the provided string.
|
2683 |
-
*/
|
2684 |
-
protected function copy_skip($chars)
|
2685 |
-
{
|
2686 |
-
$pos = $this->pos;
|
2687 |
-
$len = strspn($this->doc, $chars, $pos);
|
2688 |
-
$this->pos += $len;
|
2689 |
-
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2690 |
-
if ($len === 0) {
|
2691 |
-
return '';
|
2692 |
-
}
|
2693 |
-
return substr($this->doc, $pos, $len);
|
2694 |
-
}
|
2695 |
-
|
2696 |
-
/**
|
2697 |
-
* Copy substring from the current document position to the first occurrence
|
2698 |
-
* of any of the provided characters.
|
2699 |
-
*
|
2700 |
-
* @param string $chars A string containing every character to stop at.
|
2701 |
-
* @return string Substring from the current document position to the first
|
2702 |
-
* occurrence of any of the provided characters.
|
2703 |
-
*/
|
2704 |
-
protected function copy_until($chars)
|
2705 |
-
{
|
2706 |
-
$pos = $this->pos;
|
2707 |
-
$len = strcspn($this->doc, $chars, $pos);
|
2708 |
-
$this->pos += $len;
|
2709 |
-
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2710 |
-
return substr($this->doc, $pos, $len);
|
2711 |
-
}
|
2712 |
-
|
2713 |
-
/**
|
2714 |
-
* Copy substring from the current document position to the first occurrence
|
2715 |
-
* of the provided string.
|
2716 |
-
*
|
2717 |
-
* @param string $char The string to stop at.
|
2718 |
-
* @return string Substring from the current document position to the first
|
2719 |
-
* occurrence of the provided string.
|
2720 |
-
*/
|
2721 |
-
protected function copy_until_char($char)
|
2722 |
-
{
|
2723 |
-
if ($this->char === null) {
|
2724 |
-
return '';
|
2725 |
-
}
|
2726 |
-
|
2727 |
-
if (($pos = strpos($this->doc, $char, $this->pos)) === false) {
|
2728 |
-
$ret = substr($this->doc, $this->pos, $this->size - $this->pos);
|
2729 |
-
$this->char = null;
|
2730 |
-
$this->pos = $this->size;
|
2731 |
-
return $ret;
|
2732 |
-
}
|
2733 |
-
|
2734 |
-
if ($pos === $this->pos) {
|
2735 |
-
return '';
|
2736 |
-
}
|
2737 |
-
|
2738 |
-
$pos_old = $this->pos;
|
2739 |
-
$this->char = $this->doc[$pos];
|
2740 |
-
$this->pos = $pos;
|
2741 |
-
return substr($this->doc, $pos_old, $pos - $pos_old);
|
2742 |
-
}
|
2743 |
-
|
2744 |
-
/**
|
2745 |
-
* Remove noise from HTML content
|
2746 |
-
*
|
2747 |
-
* Noise is stored to {@see simple_html_dom::$noise}
|
2748 |
-
*
|
2749 |
-
* @param string $pattern The regex pattern used for finding noise
|
2750 |
-
* @param bool $remove_tag True to remove the entire match. Default is false
|
2751 |
-
* to only remove the captured data.
|
2752 |
-
*/
|
2753 |
-
protected function remove_noise($pattern, $remove_tag = false)
|
2754 |
-
{
|
2755 |
-
global $debug_object;
|
2756 |
-
if (is_object($debug_object)) {
|
2757 |
-
$debug_object->debug_log_entry(1);
|
2758 |
-
}
|
2759 |
-
|
2760 |
-
$count = preg_match_all(
|
2761 |
-
$pattern,
|
2762 |
-
$this->doc,
|
2763 |
-
$matches,
|
2764 |
-
PREG_SET_ORDER | PREG_OFFSET_CAPTURE
|
2765 |
-
);
|
2766 |
-
|
2767 |
-
for ($i = $count - 1; $i > -1; --$i) {
|
2768 |
-
$key = '___noise___' . sprintf('% 5d', count($this->noise) + 1000);
|
2769 |
-
|
2770 |
-
if (is_object($debug_object)) {
|
2771 |
-
$debug_object->debug_log(2, 'key is: ' . $key);
|
2772 |
-
}
|
2773 |
-
|
2774 |
-
$idx = ($remove_tag) ? 0 : 1; // 0 = entire match, 1 = submatch
|
2775 |
-
$this->noise[$key] = $matches[$i][$idx][0];
|
2776 |
-
$this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
|
2777 |
-
}
|
2778 |
-
|
2779 |
-
// reset the length of content
|
2780 |
-
$this->size = strlen($this->doc);
|
2781 |
-
|
2782 |
-
if ($this->size > 0) {
|
2783 |
-
$this->char = $this->doc[0];
|
2784 |
-
}
|
2785 |
-
}
|
2786 |
-
|
2787 |
-
/**
|
2788 |
-
* Restore noise to HTML content
|
2789 |
-
*
|
2790 |
-
* Noise is restored from {@see simple_html_dom::$noise}
|
2791 |
-
*
|
2792 |
-
* @param string $text A subset of HTML containing noise
|
2793 |
-
* @return string The same content with noise restored
|
2794 |
-
*/
|
2795 |
-
function restore_noise($text)
|
2796 |
-
{
|
2797 |
-
global $debug_object;
|
2798 |
-
if (is_object($debug_object)) {
|
2799 |
-
$debug_object->debug_log_entry(1);
|
2800 |
-
}
|
2801 |
-
|
2802 |
-
while (($pos = strpos($text, '___noise___')) !== false) {
|
2803 |
-
// Sometimes there is a broken piece of markup, and we don't GET the
|
2804 |
-
// pos+11 etc... token which indicates a problem outside of us...
|
2805 |
-
|
2806 |
-
// todo: "___noise___1000" (or any number with four or more digits)
|
2807 |
-
// in the DOM causes an infinite loop which could be utilized by
|
2808 |
-
// malicious software
|
2809 |
-
if (strlen($text) > $pos + 15) {
|
2810 |
-
$key = '___noise___'
|
2811 |
-
. $text[$pos + 11]
|
2812 |
-
. $text[$pos + 12]
|
2813 |
-
. $text[$pos + 13]
|
2814 |
-
. $text[$pos + 14]
|
2815 |
-
. $text[$pos + 15];
|
2816 |
-
|
2817 |
-
if (is_object($debug_object)) {
|
2818 |
-
$debug_object->debug_log(2, 'located key of: ' . $key);
|
2819 |
-
}
|
2820 |
-
|
2821 |
-
if (isset($this->noise[$key])) {
|
2822 |
-
$text = substr($text, 0, $pos)
|
2823 |
-
. $this->noise[$key]
|
2824 |
-
. substr($text, $pos + 16);
|
2825 |
-
} else {
|
2826 |
-
// do this to prevent an infinite loop.
|
2827 |
-
$text = substr($text, 0, $pos)
|
2828 |
-
. 'UNDEFINED NOISE FOR KEY: '
|
2829 |
-
. $key
|
2830 |
-
. substr($text, $pos + 16);
|
2831 |
-
}
|
2832 |
-
} else {
|
2833 |
-
// There is no valid key being given back to us... We must get
|
2834 |
-
// rid of the ___noise___ or we will have a problem.
|
2835 |
-
$text = substr($text, 0, $pos)
|
2836 |
-
. 'NO NUMERIC NOISE KEY'
|
2837 |
-
. substr($text, $pos + 11);
|
2838 |
-
}
|
2839 |
-
}
|
2840 |
-
return $text;
|
2841 |
-
}
|
2842 |
-
|
2843 |
-
// Sometimes we NEED one of the noise elements.
|
2844 |
-
function search_noise($text)
|
2845 |
-
{
|
2846 |
-
global $debug_object;
|
2847 |
-
if (is_object($debug_object)) {
|
2848 |
-
$debug_object->debug_log_entry(1);
|
2849 |
-
}
|
2850 |
-
|
2851 |
-
foreach ($this->noise as $noiseElement) {
|
2852 |
-
if (strpos($noiseElement, $text) !== false) {
|
2853 |
-
return $noiseElement;
|
2854 |
-
}
|
2855 |
-
}
|
2856 |
-
}
|
2857 |
-
|
2858 |
-
function __toString()
|
2859 |
-
{
|
2860 |
-
return $this->root->innertext();
|
2861 |
-
}
|
2862 |
-
|
2863 |
-
function __get($name)
|
2864 |
-
{
|
2865 |
-
switch ($name) {
|
2866 |
-
case 'outertext':
|
2867 |
-
return $this->root->innertext();
|
2868 |
-
case 'innertext':
|
2869 |
-
return $this->root->innertext();
|
2870 |
-
case 'plaintext':
|
2871 |
-
return $this->root->text();
|
2872 |
-
case 'charset':
|
2873 |
-
return $this->_charset;
|
2874 |
-
case 'target_charset':
|
2875 |
-
return $this->_target_charset;
|
2876 |
-
}
|
2877 |
-
}
|
2878 |
-
|
2879 |
-
// camel naming conventions
|
2880 |
-
function childNodes($idx = -1)
|
2881 |
-
{
|
2882 |
-
return $this->root->childNodes($idx);
|
2883 |
-
}
|
2884 |
-
|
2885 |
-
function firstChild()
|
2886 |
-
{
|
2887 |
-
return $this->root->first_child();
|
2888 |
-
}
|
2889 |
-
|
2890 |
-
function lastChild()
|
2891 |
-
{
|
2892 |
-
return $this->root->last_child();
|
2893 |
-
}
|
2894 |
-
|
2895 |
-
function createElement($name, $value = null)
|
2896 |
-
{
|
2897 |
-
return @str_get_html("<$name>$value</$name>")->first_child();
|
2898 |
-
}
|
2899 |
-
|
2900 |
-
function createTextNode($value)
|
2901 |
-
{
|
2902 |
-
return @end(str_get_html($value)->nodes);
|
2903 |
-
}
|
2904 |
-
|
2905 |
-
function getElementById($id)
|
2906 |
-
{
|
2907 |
-
return $this->find("#$id", 0);
|
2908 |
-
}
|
2909 |
-
|
2910 |
-
function getElementsById($id, $idx = null)
|
2911 |
-
{
|
2912 |
-
return $this->find("#$id", $idx);
|
2913 |
-
}
|
2914 |
-
|
2915 |
-
function getElementByTagName($name)
|
2916 |
-
{
|
2917 |
-
return $this->find($name, 0);
|
2918 |
-
}
|
2919 |
-
|
2920 |
-
function getElementsByTagName($name, $idx = -1)
|
2921 |
-
{
|
2922 |
-
return $this->find($name, $idx);
|
2923 |
-
}
|
2924 |
-
|
2925 |
-
function loadFile()
|
2926 |
-
{
|
2927 |
-
$args = func_get_args();
|
2928 |
-
$this->load_file($args);
|
2929 |
-
}
|
2930 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -3,6 +3,7 @@
|
|
3 |
namespace DOMUtilForWebP;
|
4 |
|
5 |
//use Sunra\PhpSimple\HtmlDomParser;
|
|
|
6 |
|
7 |
/**
|
8 |
* Highly configurable class for replacing image URLs in HTML (both src and srcset syntax)
|
@@ -179,8 +180,9 @@ class ImageUrlReplacer
|
|
179 |
// function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET,
|
180 |
// $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
|
181 |
|
182 |
-
|
183 |
-
|
|
|
184 |
|
185 |
// MAX_FILE_SIZE is defined in simple_html_dom.
|
186 |
// For safety sake, we make sure it is defined before using
|
@@ -232,9 +234,9 @@ class ImageUrlReplacer
|
|
232 |
/* Main replacer function */
|
233 |
public static function replace($html)
|
234 |
{
|
235 |
-
if (!function_exists('str_get_html')) {
|
236 |
require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
|
237 |
-
}
|
238 |
$iur = new static();
|
239 |
return $iur->replaceHtml($html);
|
240 |
}
|
3 |
namespace DOMUtilForWebP;
|
4 |
|
5 |
//use Sunra\PhpSimple\HtmlDomParser;
|
6 |
+
use KubAT\PhpSimple\HtmlDomParser;
|
7 |
|
8 |
/**
|
9 |
* Highly configurable class for replacing image URLs in HTML (both src and srcset syntax)
|
180 |
// function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET,
|
181 |
// $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
|
182 |
|
183 |
+
$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
|
184 |
+
//$dom = str_get_html($html, false, false, 'UTF-8', false);
|
185 |
+
|
186 |
|
187 |
// MAX_FILE_SIZE is defined in simple_html_dom.
|
188 |
// For safety sake, we make sure it is defined before using
|
234 |
/* Main replacer function */
|
235 |
public static function replace($html)
|
236 |
{
|
237 |
+
/*if (!function_exists('str_get_html')) {
|
238 |
require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
|
239 |
+
}*/
|
240 |
$iur = new static();
|
241 |
return $iur->replaceHtml($html);
|
242 |
}
|
@@ -3,6 +3,8 @@
|
|
3 |
namespace DOMUtilForWebP;
|
4 |
|
5 |
//use Sunra\PhpSimple\HtmlDomParser;
|
|
|
|
|
6 |
/**
|
7 |
* Class PictureTags - convert an <img> tag to a <picture> tag and add the webp versions of the images
|
8 |
* Code is based on code from the ShortPixel plugin, which in turn used code from Responsify WP plugin
|
@@ -22,7 +24,6 @@ namespace DOMUtilForWebP;
|
|
22 |
* https://packagist.org/packages/masterminds/html5
|
23 |
*/
|
24 |
|
25 |
-
use \WebPExpress\AlterHtmlHelper;
|
26 |
|
27 |
class PictureTags
|
28 |
{
|
@@ -127,11 +128,12 @@ class PictureTags
|
|
127 |
return $attributes;
|
128 |
} else {
|
129 |
//$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
|
130 |
-
if (!function_exists('str_get_html')) {
|
131 |
require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
|
132 |
-
}
|
|
|
133 |
|
134 |
-
$dom = str_get_html($html, false, false, 'UTF-8', false);
|
135 |
if ($dom !== false) {
|
136 |
$elems = $dom->find('img,IMG');
|
137 |
foreach ($elems as $index => $elem) {
|
3 |
namespace DOMUtilForWebP;
|
4 |
|
5 |
//use Sunra\PhpSimple\HtmlDomParser;
|
6 |
+
use KubAT\PhpSimple\HtmlDomParser;
|
7 |
+
|
8 |
/**
|
9 |
* Class PictureTags - convert an <img> tag to a <picture> tag and add the webp versions of the images
|
10 |
* Code is based on code from the ShortPixel plugin, which in turn used code from Responsify WP plugin
|
24 |
* https://packagist.org/packages/masterminds/html5
|
25 |
*/
|
26 |
|
|
|
27 |
|
28 |
class PictureTags
|
29 |
{
|
128 |
return $attributes;
|
129 |
} else {
|
130 |
//$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
|
131 |
+
/*if (!function_exists('str_get_html')) {
|
132 |
require_once __DIR__ . '/../src-vendor/simple_html_dom/simple_html_dom.inc';
|
133 |
+
}*/
|
134 |
+
|
135 |
|
136 |
+
$dom = HtmlDomParser::str_get_html($html, false, false, 'UTF-8', false);
|
137 |
if ($dom !== false) {
|
138 |
$elems = $dom->find('img,IMG');
|
139 |
foreach ($elems as $index => $elem) {
|
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
-
* Version: 0.
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
+
* Version: 0.23.0
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|